diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml new file mode 100644 index 000000000..57336cfef --- /dev/null +++ b/.github/workflows/backport.yaml @@ -0,0 +1,17 @@ +name: Backport merged pull request +on: + pull_request_target: + types: [closed] +permissions: + contents: write # so it can comment + pull-requests: write # so it can create pull requests +jobs: + backport: + name: Backport pull request + runs-on: ubuntu-latest + # Don't run on closed unmerged pull requests + if: github.event.pull_request.merged + steps: + - uses: actions/checkout@v3 + - name: Create backport pull requests + uses: korthout/backport-action@v1 diff --git a/.github/workflows/build-test-linux-arm64.yml b/.github/workflows/build-test-linux-arm64.yml new file mode 100644 index 000000000..7f74d3fd6 --- /dev/null +++ b/.github/workflows/build-test-linux-arm64.yml @@ -0,0 +1,62 @@ +name: Build and Test on Linux ARCH64 + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build-and-test-arm64: + name: Build and Test on Linux ARM64 + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + submodules: "true" + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.21 + + - name: Install prerequisites + run: | + sudo apt-get update + sudo apt-get install -y git wget curl make python3 python3-pip clang-12 lld-12 + sudo ln -sf /usr/bin/clang-12 /usr/bin/clang + + - name: Install rust nightly toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.76 + override: true + components: clippy, rustfmt + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Pull custom ARM64 Docker image + run: | + docker pull --platform linux/arm64 kcllang/kcl-builder-arm64 + + - name: Run custom ARM64 Docker image + run: | + docker run --rm --platform linux/arm64 \ + -v ${{ github.workspace }}:/workspace -w /workspace \ + kcllang/kcl-builder-arm64 \ + make && make release + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: kcl-linux-arm64 + path: _build/dist/ubuntu/kclvm diff --git a/.github/workflows/build-test-macos-arm64.yml b/.github/workflows/build-test-macos-arm64.yml new file mode 100644 index 000000000..35e16aa2c --- /dev/null +++ b/.github/workflows/build-test-macos-arm64.yml @@ -0,0 +1,46 @@ +name: Build and Test on MacOS ARCH64 + +on: ["push", "pull_request"] +jobs: + build-and-test: + # Ref: https://github.com/actions/runner-images/tree/main/images/macos + strategy: + matrix: + os: [macos-13-xlarge] + runs-on: ${{ matrix.os }} + steps: + - name: Git checkout + uses: actions/checkout@v2 + with: + submodules: "true" + + - name: Set up Go 1.21 + uses: actions/setup-go@v2 + with: + go-version: 1.21 + + - run: clang --version + - run: cargo --version + - run: rustc --print sysroot + + - name: Delete rust cargo + run: rm -rf /root/.cargo/bin + shell: bash + - name: Install LLVM 12 + run: brew install llvm@12 + shell: bash + - name: Install rust nightly toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.76 + override: true + components: clippy, rustfmt + - name: Grammar test + working-directory: ./kclvm + run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/opt/homebrew/opt/llvm@12/bin/ && make && make test-grammar + shell: bash + + - uses: actions/upload-artifact@v3 + with: + name: kcl-darwin-arm64 + path: _build/dist/Darwin/kclvm diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index 9f0505b5e..dd691550b 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -14,7 +14,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # the below token should have repo scope and must be manually added by you in the repository's secret - PERSONAL_ACCESS_TOKEN : ${{ secrets.KCL_LANG_BOT_TOKEN }} + PERSONAL_ACCESS_TOKEN : ${{ secrets.DEPLOY_ACCESS_TOKEN }} with: path-to-document: 'https://github.com/kcl-lang/.github/blob/main/CLA.md' # e.g. a CLA or a DCO document diff --git a/.github/workflows/daily-release.yaml b/.github/workflows/daily-release.yaml new file mode 100644 index 000000000..1320471bc --- /dev/null +++ b/.github/workflows/daily-release.yaml @@ -0,0 +1,134 @@ +name: Daily Release CI + +on: + schedule: + - cron: '0 0 * * *' + +permissions: + contents: write + +jobs: + macos-release: + name: Build and release on macos + runs-on: macos-11 + steps: + - name: Git checkout + uses: actions/checkout@v2 + with: + submodules: "true" + + - run: clang --version + - run: cargo --version + - run: rustc --print sysroot + + - name: Delete rust cargo + run: rm -rf /root/.cargo/bin + shell: bash + - name: Install LLVM 12 + run: brew install llvm@12 + shell: bash + - name: Install rust nightly toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.76 + override: true + components: clippy, rustfmt + + - name: Build KCL + run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make build + shell: bash + + - uses: actions/upload-artifact@v3 + with: + name: kcl-darwin-amd64-nightly + path: _build/dist/Darwin/kclvm + + linux-release: + name: Build and release on linux + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v3 + with: + submodules: "true" + + # Prerequisite + + - name: Install LLVM + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y git wget curl make + sudo apt-get install -y clang-12 lld-12 + sudo ln -sf /usr/bin/clang-12 /usr/bin/clang + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.76 + override: true + components: clippy, rustfmt + + - name: Build KCL + run: make build + shell: bash + + - uses: actions/upload-artifact@v3 + with: + name: kcl-linux-amd64-nightly + path: _build/dist/ubuntu/kclvm + + - name: Copy Dockerfile to the current work directory + run: cp scripts/docker/kcl/Dockerfile . + shell: bash + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: kcllang/kclvm + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + windows-release: + name: Build and release on windows + runs-on: windows-latest + env: + LLVM_SYS_120_PREFIX: "C:/LLVM" + KCLVM_CLANG: "C:/LLVM/bin/clang.exe" + steps: + - name: Git checkout + uses: actions/checkout@v2 + with: + submodules: "true" + + - uses: ilammy/msvc-dev-cmd@v1 + + - run: clang --version + - run: cargo --version + + # Install LLVM-12 + - run: Invoke-WebRequest -Uri https://github.com/kcl-lang/llvm-package-windows/releases/download/v12.0.1/LLVM-12.0.1-win64.7z -OutFile C:/LLVM-12.0.1-win64.7z + - run: Get-FileHash -Algorithm MD5 C:/LLVM-12.0.1-win64.7z # md5: 3fcf77f82c6c3ee650711439b20aebe5 + - run: 7z x -y C:/LLVM-12.0.1-win64.7z -o"C:/LLVM" + - run: Remove-Item C:/LLVM-12.0.1-win64.7z + + - run: echo "C:/LLVM/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - run: .\scripts\build-windows\build.ps1 + + - run: echo ";$(pwd)\scripts\build-windows\_output\kclvm-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + working-directory: . + + - uses: actions/upload-artifact@v3 + with: + name: kcl-windows-nightly + path: scripts/build-windows/_output/kclvm-windows diff --git a/.github/workflows/macos_test.yaml b/.github/workflows/macos_test.yaml index b7aea8238..4f887b6f3 100644 --- a/.github/workflows/macos_test.yaml +++ b/.github/workflows/macos_test.yaml @@ -13,13 +13,18 @@ jobs: with: submodules: "true" - - name: Set up Go 1.18 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.19 + go-version: 1.21 - - name: Install kpm - run: go install kcl-lang.io/kpm@latest + - name: Install KCL CLI + run: go install kcl-lang.io/cli/cmd/kcl@latest - run: clang --version - run: cargo --version @@ -34,7 +39,7 @@ jobs: - name: Install rust nightly toolchain uses: actions-rs/toolchain@v1 with: - toolchain: 1.67 + toolchain: 1.76 override: true components: clippy, rustfmt - name: Code format check @@ -43,21 +48,24 @@ jobs: shell: bash - name: Grammar test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make install-rustc-wasm && make && make test-grammar + run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make && make test-grammar shell: bash - name: Runtime test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make install-rustc-wasm && make && make test-runtime + run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make && make test-runtime shell: bash + - name: Unit test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make install-rustc-wasm && make && make codecov-lcov - shell: bash - - name: Konfig test - working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make install-rustc-wasm && make && make test-konfig + run: export PATH=$PATH:$PWD/../_build/dist/Darwin/kclvm/bin:/usr/local/opt/llvm@12/bin && make && make codecov-lcov shell: bash + - name: Coveralls upload + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: ./kclvm/.kclvm_cov/lcov.info + - uses: actions/upload-artifact@v3 with: name: kcl-darwin-amd64 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index fa7bbdbf6..000000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,62 +0,0 @@ -name: release -on: - push: - branches: - - "main" - tags: - - "v*" -permissions: - contents: write -jobs: - test: - name: Build and release - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v3 - with: - submodules: "true" - - # Prerequisite - - - name: Install Python3 and LLVM - shell: bash - run: | - sudo apt-get update - sudo apt-get install -y git wget curl make - sudo apt-get install python3 python3-pip -y - sudo apt-get install -y clang-12 lld-12 - sudo ln -sf /usr/bin/clang-12 /usr/bin/clang - - name: Install Rust Toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: 1.67 - override: true - components: clippy, rustfmt - - # KCL build - - - name: Build KCL - run: export PATH=$PATH:$PWD/_build/dist/ubuntu/kclvm/bin && make build - shell: bash - - - name: Copy Dockerfile to the current work directory - run: cp scripts/docker/kcl/Dockerfile . - shell: bash - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: kcllang/kcl - - name: Build and push Docker image - uses: docker/build-push-action@v3 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/test_compiler_base.yaml b/.github/workflows/test_compiler_base.yaml index 1649ee595..94e2b0a7f 100644 --- a/.github/workflows/test_compiler_base.yaml +++ b/.github/workflows/test_compiler_base.yaml @@ -1,5 +1,12 @@ name: build-and-test-compiler-base -on: ["push", "pull_request"] +on: + push: + paths: + - 'compiler_base/**' + pull_request: + paths: + - 'compiler_base/**' + jobs: check-fmt: name: Test @@ -15,7 +22,7 @@ jobs: - name: Install rust nightly toolchain uses: actions-rs/toolchain@v1 with: - toolchain: 1.67 + toolchain: 1.76 override: true components: clippy, rustfmt - name: Rust code format check @@ -36,7 +43,7 @@ jobs: - name: Install rust nightly toolchain uses: actions-rs/toolchain@v1 with: - toolchain: 1.67 + toolchain: 1.76 override: true components: clippy, rustfmt - name: Compiler_base rust unit test diff --git a/.github/workflows/ubuntu_test.yaml b/.github/workflows/ubuntu_test.yaml index aadc775f5..4fbb4678d 100644 --- a/.github/workflows/ubuntu_test.yaml +++ b/.github/workflows/ubuntu_test.yaml @@ -5,24 +5,30 @@ jobs: # Ref: https://github.com/actions/runner-images/tree/main/images/linux name: Test runs-on: ubuntu-latest - container: - image: kcllang/kcl-builder steps: - name: Check out code uses: actions/checkout@v3 with: submodules: "true" - - name: Set up Go 1.18 + - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.19 - - name: Delete rust cargo - run: rm -rf /root/.cargo/bin + go-version: 1.21 + + # Prerequisite + + - name: Install Python3 and LLVM shell: bash + run: | + sudo apt-get update + sudo apt-get install -y git wget curl make + sudo apt-get install python3 python3-pip -y + sudo apt-get install -y clang-12 lld-12 + sudo ln -sf /usr/bin/clang-12 /usr/bin/clang - name: Install rust nightly toolchain uses: actions-rs/toolchain@v1 with: - toolchain: 1.67 + toolchain: 1.76 override: true components: clippy, rustfmt - name: Code format check @@ -35,28 +41,19 @@ jobs: shell: bash - name: Grammar test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make install-rustc-wasm && make && make test-grammar + run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make && make test-grammar shell: bash - name: Runtime test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make install-rustc-wasm && make && make test-runtime + run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make && make test-runtime shell: bash - - name: Install kpm - run: go install kcl-lang.io/kpm@latest + - name: Install KCL CLI + run: go install kcl-lang.io/cli/cmd/kcl@latest - name: Unit test working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make install-rustc-wasm && make && make codecov-lcov + run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make && make test shell: bash - - name: Konfig test - working-directory: ./kclvm - run: export PATH=$PATH:$PWD/../_build/dist/ubuntu/kclvm/bin && make install-rustc-wasm && make && make test-konfig - shell: bash - - name: Coveralls upload - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./kclvm/.kclvm/lcov.info - uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/windows_test.yaml b/.github/workflows/windows_test.yaml index 81d36c920..2ae7dd3fe 100644 --- a/.github/workflows/windows_test.yaml +++ b/.github/workflows/windows_test.yaml @@ -13,13 +13,13 @@ jobs: with: submodules: "true" - - name: Set up Go 1.18 + - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.19 + go-version: 1.21 - - name: Install kpm - run: go install kcl-lang.io/kpm@latest + - name: Install KCL + run: go install kcl-lang.io/cli/cmd/kcl@latest - uses: ilammy/msvc-dev-cmd@v1 @@ -34,10 +34,10 @@ jobs: - run: echo "C:/LLVM/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - # Build kclvm-cli - - run: .\scripts\build-windows\build.bat + # Build kclvm CLI + - run: .\scripts\build-windows\build.ps1 - # Set kclvm-cli path + # Set kclvm CLI into PATH - run: echo ";$(pwd)\scripts\build-windows\_output\kclvm-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append working-directory: . @@ -45,10 +45,6 @@ jobs: - run: cargo test -p kclvm-* working-directory: ./kclvm - # Rust runtime test - - run: python3 -m pip install --upgrade pip && python3 -m pip install pytest && kclvm -m pytest -vv - working-directory: ./kclvm/tests/test_units - - uses: actions/upload-artifact@v3 with: name: kcl-windows diff --git a/.gitignore b/.gitignore index 29d5ee571..0d57d4d98 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ lark_parser.pickle # KCLVM cache and temp output .kclvm +.kclvm_cov *.dylib *.so *.dll @@ -93,5 +94,5 @@ _a.out_*.* llvm* llvm-* -# kpm +# KCL mod lock file !.mod.lock diff --git a/ADOPTERS.md b/ADOPTERS.md new file mode 100644 index 000000000..e0143c3e8 --- /dev/null +++ b/ADOPTERS.md @@ -0,0 +1,11 @@ +# Adopters + +This list shows non-exhaustive adopters of KCL. If you are using to KCL, then please add your team and use-case to this file. + +## Adopters list + +### Organizations + ++ *[Ant Group](https://www.antgroup.com/)* - Large scale Kubernetes configuration abstration and management with GitOps. ++ *[Youzan](https://www.youzan.com/)* - Large scale Kubernetes configuration abstration and management with GitOps. ++ *[Huawei](https://www.huawei.com/)* - Terraform resource model abstraction and management. diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 000000000..79eff78c1 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,65 @@ +# KCL Project Governance + +As a CNCF sandbox project, the KCL project adheres to the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). + +## Overview + +- [KCL Project Governance](#kcl-project-governance) + - [Overview](#overview) + - [Maintainer Ship](#maintainer-ship) + - [Adding Maintainers](#adding-maintainers) + - [Removal of Inactive Maintainers](#removal-of-inactive-maintainers) + - [Decision-Making Process](#decision-making-process) + - [Updating Governance](#updating-governance) + +## Maintainer Ship + +Maintainers of the KCL project share the responsibility of its success. They have three main responsibilities: + ++ Share responsibility for the project's success. ++ Make a long-term investment to improve the project. ++ Spend time on tasks that may not be the most interesting, but are essential for the project's success. + +Maintainers often work tirelessly, but their contributions may not always be fully appreciated. While it may be easy to focus on the more exciting and technically advanced features, it is equally important to work on minor bug fixes, small improvements, long-term stability optimizations, and other essential aspects of the project. + +## Adding Maintainers + +Maintainers are individuals who have shown dedication to the long-term success of the project. Contributors wishing to become maintainers should have actively participated in tackling issues, contributing code, and reviewing proposals and code for a period of at least two months. + +Maintainer ship is built on trust, which extends beyond code contributions. It is important for potential maintainers to earn the trust of current maintainers by demonstrating their commitment to the best interests of the project. + +Current maintainers hold regular maintainer meetings to identify active contributors who have consistently invested time in the project over the prior months. From this list, if one or more individuals are deemed qualified candidates, a proposal to add them as maintainers can be submitted on GitHub via a pull request. If at least 50% of the maintainers agree with the proposal, the newly added maintainer(s) will be considered valid. + +## Removal of Inactive Maintainers + +Similar to adding maintainers, existing maintainers can be removed from the active maintainer list. If an existing maintainer meets one of the following conditions, any other maintainer can propose their removal via a pull request: + ++ The maintainer has not participated in community activities for more than three months. ++ The maintainer has violated the governance rules more than twice. + +Once the above conditions are confirmed, the maintainer can be removed from the list, unless the original maintainer requests to remain and receives at least 50% of the votes from other maintainers. + +If a maintainer is removed from the maintaining list, the other maintainers should acknowledge their contribution by adding their name to an alumni section. + +## Decision-Making Process + +The KCL project is an open-source project that values openness. This means that the KCL repository is the source of truth for every aspect of the project, including values, design, documentation, roadmap, interfaces, etc. If it is part of the project, it should be in the repository. + +All decisions, regardless of their size, should follow the following three steps to be considered an update to the project: + +1. Open a pull request. +2. Discuss the changes under the pull request. +3. Merge or reject the pull request. + +When the KCL project has less than seven maintainers, a pull request (except for adding maintainers) may be merged if it meets the following conditions: + ++ At least one maintainer comments "LGTM" (Looks Good To Me) on the pull request. ++ No other maintainers have opposing opinions. + +When the KCL project has more than seven maintainers, a pull request (except for adding maintainers) may be merged if it meets the following conditions: + ++ At least two maintainers comment "LGTM" (Looks Good To Me) on the pull request. + +## Updating Governance + +Any substantive updates to the Governance require a supermajority vote from the maintainers. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 000000000..6443f3449 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,10 @@ +Pengfei Xu Ant Group Peefy +Xiaodong Duo Ant Group ldxdl +Chaoqun Huang TuSimple ekkoful +Shushan Chai Ant Group chai2010 +Rui Xia Ant Group amyXia1994 +Zhe Zong Ant Group zong-zhe +Xiangfei Chen <897013703@qq.com> Ant Group NeverRaR +Zheng Zhang <18012015693@163.com> Ant Group He1pa +Yi Zhen Ant Group i-zhen +Junxing Zhu Southeast University jakezhu9 diff --git a/Makefile b/Makefile index e146c6c33..69bf5fd46 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ PROJECT_NAME = KCLVM PWD:=$(shell pwd) -KCLVM_VERSION := $(shell cat VERSION) +VERSION := $(shell cat VERSION) BUILD_IMAGE:=kcllang/kcl-builder # export DOCKER_DEFAULT_PLATFORM=linux/amd64 @@ -45,6 +45,10 @@ test-grammar: fmt: make -C ./kclvm fmt +.PHONY: tag +tag: + scripts/tag.sh v$(VERSION) + # ---------------- # Docker # ---------------- diff --git a/README-zh.md b/README-zh.md index b0ca5c82a..37ab6b2f8 100644 --- a/README-zh.md +++ b/README-zh.md @@ -4,7 +4,7 @@ English | 简体中文

-介绍 | 特性 | 场景 | 安装 | 快速开始 | 文档 | 贡献 | 路线规划 +介绍 | 特性 | 场景 | 安装 | 文档 | 贡献 | 路线规划

@@ -13,12 +13,18 @@ + +

## 介绍 KCL 是一个开源的基于约束的记录及函数语言并通过成熟的编程语言技术和实践来改进对大量繁杂配置比如云原生 Kubernetes 配置场景的编写,致力于构建围绕配置的更好的模块化、扩展性和稳定性,更简单的逻辑编写,以及更简单的自动化和生态工具集成。 +

+ +

+ ## 场景 您可以将 KCL 用于 @@ -27,103 +33,35 @@ KCL 是一个开源的基于约束的记录及函数语言并通过成熟的编 + [使用 Schema 对配置数据进行抽象建模](https://kcl-lang.io/docs/user_docs/guides/schema-definition)并减少配置数据中的样板文件 + [为配置数据定义带有规则约束](https://kcl-lang.io/docs/user_docs/guides/validation)的 Schema 并对数据进行自动验证 + [通过梯度自动化方案和 GitOps](https://kcl-lang.io/docs/user_docs/guides/automation)无副作用地组织、简化、统一和管理庞大的配置 -+ 通过[分块编写配置数据](https://kcl-lang.io/docs/reference/lang/tour#config-operations)可扩展地管理庞大的配置 ++ 通过[分块编写配置数据](https://kcl-lang.io/docs/reference/lang/tour#config-operations)为不同的环境可扩展地管理庞大的配置 + 通过与[云原生配置工具](https://kcl-lang.io/docs/user_docs/guides/working-with-k8s/)集成直接编辑或校验存量 Kubernetes 资源 -+ 与 [Kusion Stack](https://kusionstack.io) 一起,用作平台工程语言来交付现代应用程序 ++ 与 [KusionStack](https://kusionstack.io) 一起,用作平台工程语言来交付现代应用程序 ## 特性 + **简单易用**:源于 Python、Golang 等高级语言,采纳函数式编程语言特性,低副作用 -+ **设计良好**:独立的 Spec 驱动的语法、语义、运行时和系统库设计 -+ **快速建模**:以 [Schema](https://kcl-lang.io/docs/reference/lang/tour#schema) 为中心的配置类型及模块化抽象 ++ **设计良好**:独立的规范驱动的语法、语义、运行时和系统库设计 ++ **快速建模**:[开箱即用的模型库](https://artifacthub.io/packages/search?org=kcl&sort=relevance&page=1)和以 [Schema](https://kcl-lang.io/docs/reference/lang/tour#schema) 为中心的配置类型及模块化抽象 + **功能完备**:基于 [Config](https://kcl-lang.io/docs/reference/lang/tour#config-operations)、[Schema](https://kcl-lang.io/docs/reference/lang/tour#schema)、[Lambda](https://kcl-lang.io/docs/reference/lang/tour#function)、[Rule](https://kcl-lang.io/docs/reference/lang/tour#rule) 的配置及其模型、逻辑和策略编写 + **可靠稳定**:依赖[静态类型系统](https://kcl-lang.io/docs/reference/lang/tour/#type-system)、[约束](https://kcl-lang.io/docs/reference/lang/tour/#validation)和[自定义规则](https://kcl-lang.io/docs/reference/lang/tour#rule)的配置稳定性 + **强可扩展**:通过独立配置块[自动合并机制](https://kcl-lang.io/docs/reference/lang/tour/#-operators-1)保证配置编写的高可扩展性 + **易自动化**:[CRUD APIs](https://kcl-lang.io/docs/reference/lang/tour/#kcl-cli-variable-override),[多语言 SDK](https://kcl-lang.io/docs/reference/xlang-api/overview),[语言插件](https://github.com/kcl-lang/kcl-plugin) 构成的梯度自动化方案 + **极致性能**:使用 Rust & C,[LLVM](https://llvm.org/) 实现,支持编译到本地代码和 [WASM](https://webassembly.org/) 的高性能编译时和运行时 -+ **API 亲和**:原生支持 [OpenAPI](https://github.com/kcl-lang/kcl-openapi)、 Kubernetes CRD, Kubernetes YAML 等 API 生态规范 -+ **开发友好**:[语言工具](https://kcl-lang.io/docs/tools/cli/kcl/) (Format,Lint,Test,Vet,Doc 等)、[包管理工具](https://github.com/kcl-lang/kpm)和 [IDE 插件](https://github.com/kcl-lang/vscode-kcl) 构建良好的研发体验 ++ **API 亲和**:原生支持 [OpenAPI](https://github.com/kcl-lang/kcl-openapi)、 Kubernetes CRD, Kubernetes Resource Model (KRM) 等 API 生态规范 ++ **开发友好**:[语言工具](https://kcl-lang.io/docs/tools/cli/kcl/) (Format,Lint,Test,Vet,Doc, 包管理工具等) 和 [IDE 插件](https://kcl-lang.io/docs/tools/Ide/) 构建良好的研发体验 + **安全可控**:面向领域,不原生提供线程、IO 等系统级功能,低噪音,低安全风险,易维护,易治理 + **多语言 SDK**:[Go](https://github.com/kcl-lang/kcl-go),[Python](https://github.com/kcl-lang/kcl-py) 和 [Java](https://github.com/kcl-lang/kcl-java) SDK 满足不同场景和应用使用需求 -+ **生态集成**:通过 [Kubectl KCL 插件](https://github.com/kcl-lang/kubectl-kcl)、[Kustomize KCL 插件](https://github.com/kcl-lang/kustomize-kcl)、[Helm KCL 插件](https://github.com/kcl-lang/helm-kcl) 或者 [KPT KCL SDK](https://github.com/kcl-lang/kpt-kcl) 直接编辑或校验资源 ++ **生态集成**:通过 [Kubectl KCL 插件](https://github.com/kcl-lang/kubectl-kcl)、[Kustomize KCL 插件](https://github.com/kcl-lang/kustomize-kcl)、[Helm KCL 插件](https://github.com/kcl-lang/helm-kcl) 、[KPT KCL SDK](https://github.com/kcl-lang/kpt-kcl) 或者 [Crossplane KCL 函数](https://github.com/kcl-lang/crossplane-kcl) 直接编辑、校验或者抽象资源 + **生产可用**:广泛应用在蚂蚁集团平台工程及自动化的生产环境实践中 ## 如何选择 -简单的答案: - -+ 如果你需要编写结构化的静态的 K-V,或使用 Kubernetes 原生的技术工具,建议选择 YAML -+ 如果你希望引入编程语言便利性以消除文本(如 YAML、JSON) 模板,有良好的可读性,或者你已是 Terraform 的用户,建议选择 HCL -+ 如果你希望引入类型功能提升稳定性,维护可扩展的配置文件,建议选择 CUE -+ 如果你希望以现代语言方式编写复杂类型和建模,维护可扩展的配置文件,原生的纯函数和策略,和生产级的性能和自动化,建议选择 KCL - -更详细的功能和场景对比参考[这里](https://kcl-lang.io/docs/user_docs/getting-started/intro)。 +详细的功能和场景对比参考[这里](https://kcl-lang.io/docs/user_docs/getting-started/intro)。 ## 安装 -从 Github releases 页面[下载](https://github.com/kcl-lang/kcl/releases),并且将 `{install-location}/kclvm/bin` 添加到您的环境变量中 - -> 有关安装的更多信息,请查看 KCL 官网的[安装指南](https://kcl-lang.io/docs/user_docs/getting-started/install/) - -## 快速开始 - -`./samples/kubernetes.k` 是一个生成 kubernetes 资源的例子 - -```python -apiVersion = "apps/v1" -kind = "Deployment" -metadata = { - name = "nginx" - labels.app = "nginx" -} -spec = { - replicas = 3 - selector.matchLabels = metadata.labels - template.metadata.labels = metadata.labels - template.spec.containers = [ - { - name = metadata.name - image = "${metadata.name}:1.14.2" - ports = [{ containerPort = 80 }] - } - ] -} -``` - -我们可以通过执行如下命令得到 YAML 输出 - -```bash -kcl ./samples/kubernetes.k -``` - -YAML 输出 - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx - labels: - app: nginx -spec: - replicas: 3 - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - name: nginx - image: nginx:1.14.2 - ports: - - containerPort: 80 -``` - -> 更多例子可以在[这里](https://github.com/kcl-lang/kcl-lang.io/tree/main/examples)找到 +有关安装的更多信息,请查看 KCL 官网的[安装指南](https://kcl-lang.io/docs/user_docs/getting-started/install/) ## 文档 @@ -137,7 +75,7 @@ spec: ## 路线规划 -参考[KCL 路线规划](https://github.com/kcl-lang/kcl/issues/29) +参考[KCL 路线规划](https://github.com/kcl-lang/kcl/issues/882) ## 社区 diff --git a/README.md b/README.md index 7c0134fd3..b4508b01c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ English | 简体中文

-Introduction | Features | What is it for | Installation | Showcase | Documentation | Contributing | Roadmap +Introduction | Features | What is it for | Installation | Documentation | Contributing | Roadmap

@@ -13,12 +13,18 @@ + +

## Introduction KCL is an open-source, constraint-based record and functional language that enhances the writing of complex configurations, including those for cloud-native scenarios. With its advanced programming language technology and practices, KCL is dedicated to promoting better modularity, scalability, and stability for configurations. It enables simpler logic writing and offers ease of automation APIs and integration with homegrown systems. +

+ +

+ ## What is it for? You can use KCL to @@ -27,102 +33,34 @@ You can use KCL to + Reduce boilerplate in configuration data with the [schema modeling](https://kcl-lang.io/docs/user_docs/guides/schema-definition). + Define schemas with [rule constraints for configuration data and validate](https://kcl-lang.io/docs/user_docs/guides/validation) them automatically. + Organize, simplify, unify and manage large configurations without side effects through [gradient automation schemes and GitOps](https://kcl-lang.io/docs/user_docs/guides/automation). -+ Manage large configurations in a scalable way with [isolated configuration blocks](https://kcl-lang.io/docs/reference/lang/tour#config-operations). ++ Manage large configurations in a scalable way for different environments with [isolated configuration blocks](https://kcl-lang.io/docs/reference/lang/tour#config-operations). + Mutating or validating Kubernetes resources with [cloud-native configuration tool plugins](https://kcl-lang.io/docs/user_docs/guides/working-with-k8s/). -+ Used as a platform engineering programming language to deliver modern applications with [Kusion Stack](https://kusionstack.io). ++ Used as a platform engineering programming language to deliver modern applications with [KusionStack](https://kusionstack.io). ## Features -+ **Easy-to-use**: Originated from high-level languages ​​such as Python and Golang, incorporating functional language features with low side-effects. ++ **Easy-to-use**: Originated from high-level languages ​​such as Python and Golang, incorporating functional language features with low side effects. + **Well-designed**: Independent spec-driven syntax, semantics, runtime and system modules design. -+ **Quick modeling**: [Schema](https://kcl-lang.io/docs/reference/lang/tour#schema)-centric configuration types and modular abstraction. ++ **Quick modeling**: [Out-of-the-box modules](https://artifacthub.io/packages/search?org=kcl&sort=relevance&page=1) and [Schema](https://kcl-lang.io/docs/reference/lang/tour#schema)-centric configuration types and modular abstraction. + **Rich capabilities**: Configuration with type, logic and policy based on [Config](https://kcl-lang.io/docs/reference/lang/tour#config-operations), [Schema](https://kcl-lang.io/docs/reference/lang/tour#schema), [Lambda](https://kcl-lang.io/docs/reference/lang/tour#function), [Rule](https://kcl-lang.io/docs/reference/lang/tour#rule). + **Stability**: Configuration stability is achieved through a [static type system](https://kcl-lang.io/docs/reference/lang/tour/#type-system), [constraints](https://kcl-lang.io/docs/reference/lang/tour/#validation), and [rules](https://kcl-lang.io/docs/reference/lang/tour#rule). + **Scalability**: High scalability is assured with an [automatic merge mechanism](https://kcl-lang.io/docs/reference/lang/tour/#-operators-1) of isolated config blocks. + **Fast automation**: Gradient automation scheme of [CRUD APIs](https://kcl-lang.io/docs/reference/lang/tour/#kcl-cli-variable-override), [multilingual SDKs](https://kcl-lang.io/docs/reference/xlang-api/overview), and [language plugin](https://github.com/kcl-lang/kcl-plugin) + **High performance**: High compile-time and runtime performance using Rust & C and [LLVM](https://llvm.org/), and support compilation to native code and [WASM](https://webassembly.org/). -+ **API affinity**: Native support for ecological API specifications such as [OpenAPI](https://github.com/kcl-lang/kcl-openapi), Kubernetes CRD, Kubernetes YAML spec. -+ **Developer-friendly**: Friendly development experiences with rich [language tools](https://kcl-lang.io/docs/tools/cli/kcl/) (Format, Lint, Test, Vet, Doc, etc.), [package manage tool](https://github.com/kcl-lang/kpm) and [IDE plugins](https://github.com/kcl-lang/vscode-kcl). ++ **API affinity**: Native support for ecological API specifications such as [OpenAPI](https://github.com/kcl-lang/kcl-openapi), Kubernetes CRD, Kubernetes Resource Model (KRM) spec. ++ **Developer-friendly**: Friendly development experiences with rich [language tools](https://kcl-lang.io/docs/tools/cli/kcl/) (Format, Lint, Test, Vet, Doc, package management tools etc.), and multiple [IDE extensions](https://kcl-lang.io/docs/tools/Ide/). + **Safety & maintainable**: Domain-oriented, no system-level functions such as native threads and IO, low noise and security risk, easy maintenance and governance. -+ **Rich multi-language SDK**: [Go](https://github.com/kcl-lang/kcl-go), [Python](https://github.com/kcl-lang/kcl-py), and[Java](https://github.com/kcl-lang/kcl-java) meet different scenarios and application use prelude. -+ **Integrations**: Mutate and validate manifests through [Kubectl KCL Plugin](https://github.com/kcl-lang/kubectl-kcl), [Kustomize KCL Plugin](https://github.com/kcl-lang/kustomize-kcl), [Helm KCL Plugin](https://github.com/kcl-lang/helm-kcl) or [KPT KCL SDK](https://github.com/kcl-lang/kpt-kcl). ++ **Rich multi-language SDK**: [Go](https://github.com/kcl-lang/kcl-go), [Python](https://github.com/kcl-lang/kcl-py), and [Java](https://github.com/kcl-lang/kcl-java) meet different scenarios and application use prelude. ++ **Integrations**: Abstract, mutate and validate manifests through [Kubectl KCL Plugin](https://github.com/kcl-lang/kubectl-kcl), [Kustomize KCL Plugin](https://github.com/kcl-lang/kustomize-kcl), [Helm KCL Plugin](https://github.com/kcl-lang/helm-kcl), [KPT KCL SDK](https://github.com/kcl-lang/kpt-kcl) or [Crossplane KCL Function](https://github.com/kcl-lang/crossplane-kcl). + **Production-ready**: Widely used in production practices of platform engineering and automation at Ant Group. ## How to choose? -The simple answer: - -+ YAML is recommended if you need to write structured static K-V or use Kubernetes' native tools. -+ HCL is recommended if you want to use programming language convenience to remove boilerplate with good human readability or if you are already a Terraform user. -+ CUE is recommended if you want to use a type system to improve stability and maintain scalable configurations. -+ KCL is recommended if you want types and modeling like a modern language, scalable configurations, in-house pure functions and rules, and production-ready performance and automation. - A detailed feature and scenario comparison is [here](https://kcl-lang.io/docs/user_docs/getting-started/intro). ## Installation -[Download](https://github.com/kcl-lang/kcl/releases) the latest release from GitHub and add `{install-location}/kclvm/bin` to the environment `PATH`. - -> For more information about installation, please check the [Installation Guide](https://kcl-lang.io/docs/user_docs/getting-started/install/) on the KCL official website. - -## Showcase - -`./samples/kubernetes.k` is an example of generating kubernetes manifests. - -```python -apiVersion = "apps/v1" -kind = "Deployment" -metadata = { - name = "nginx" - labels.app = "nginx" -} -spec = { - replicas = 3 - selector.matchLabels = metadata.labels - template.metadata.labels = metadata.labels - template.spec.containers = [ - { - name = metadata.name - image = "${metadata.name}:1.14.2" - ports = [{ containerPort = 80 }] - } - ] -} -``` - -We can execute the following command to get a YAML output. - -```bash -kcl ./samples/kubernetes.k -``` - -YAML output - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx - labels: - app: nginx -spec: - replicas: 3 - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - name: nginx - image: nginx:1.14.2 - ports: - - containerPort: 80 -``` - -> More examples can be found at [here](https://github.com/kcl-lang/kcl-lang.io/tree/main/examples). +For more information about installation, please check the [Installation Guide](https://kcl-lang.io/docs/user_docs/getting-started/install/) on the KCL official website. ## Documentation @@ -136,7 +74,7 @@ See [Developing Guide](./docs/dev_guide/1.about_this_guide.md). You can also get ## Roadmap -See [KCL Roadmap](https://github.com/kcl-lang/kcl/issues/29). +See [KCL Roadmap](https://github.com/kcl-lang/kcl/issues/882). ## Community diff --git a/VERSION b/VERSION index 79a2734bb..c18d72be3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.0 \ No newline at end of file +0.8.1 \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 000000000..a3e5a058b --- /dev/null +++ b/build.ps1 @@ -0,0 +1,14 @@ +Set-Location $PSScriptRoot +. '.\scripts\build-windows\build.ps1' +$bin_path = Join-Path $PSScriptRoot 'scripts\build-windows\_output\kclvm-windows\bin' +$env:Path += ";$bin_path" +# rust unit test +Set-Location .\kclvm +cargo test --workspace -r -- --nocapture +Set-Location $PSScriptRoot +# rust runtime test +Set-Location .\kclvm\tests\test_units +python3 -m pytest -vv +Set-Location $PSScriptRoot +# konfig test +Invoke-Expression -Command '.\test\integration\test_konfig.bat' diff --git a/build_and_test_win.bat b/build_and_test_win.bat deleted file mode 100644 index 0b85cf1e9..000000000 --- a/build_and_test_win.bat +++ /dev/null @@ -1,19 +0,0 @@ -cd %~dp0 - -call .\\scripts\\build-windows\\build.bat - -set "bin_path=%cd%\scripts\build-windows\_output\kclvm-windows\bin" -set "path=%path%;%bin_path%" - -@REM rust unit test -cd .\\kclvm -cargo test -p kclvm-* -cd %~dp0 - -@REM rust runtime test -cd .\\kclvm\\tests\\test_units -kclvm -m pytest -vv -cd %~dp0 - -@REM konfig test -call .\\test\\integration\\test_konfig.bat diff --git a/kclvm_cli/Cargo.toml b/cli/Cargo.toml similarity index 91% rename from kclvm_cli/Cargo.toml rename to cli/Cargo.toml index 54ac71dd8..305303f22 100644 --- a/kclvm_cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm_cli" -version = "0.5.0" +version = "0.8.1" edition = "2021" [[bin]] diff --git a/kclvm_cli/build.rs b/cli/build.rs similarity index 59% rename from kclvm_cli/build.rs rename to cli/build.rs index 2f89c73a8..bb7623caf 100644 --- a/kclvm_cli/build.rs +++ b/cli/build.rs @@ -1,5 +1,9 @@ fn main() { - println!("cargo:rustc-link-search=../kclvm/target/release"); + if cfg!(target_os = "windows") { + println!("cargo:rustc-link-search=..\\kclvm\\target\\release"); + } else { + println!("cargo:rustc-link-search=../kclvm/target/release"); + } println!("cargo:rustc-link-lib=dylib=kclvm_cli_cdylib"); if cfg!(target_os = "macos") { println!("cargo:rustc-link-arg=-Wl,-rpath,@loader_path"); diff --git a/kclvm_cli/src/main.rs b/cli/src/main.rs similarity index 100% rename from kclvm_cli/src/main.rs rename to cli/src/main.rs diff --git a/compiler_base/error/src/diagnostic/diagnostic_handler.rs b/compiler_base/error/src/diagnostic/diagnostic_handler.rs index 020268c9a..281f13e50 100644 --- a/compiler_base/error/src/diagnostic/diagnostic_handler.rs +++ b/compiler_base/error/src/diagnostic/diagnostic_handler.rs @@ -10,8 +10,8 @@ //! For more information about template loader, see doc in "compiler_base/error/src/diagnostic/diagnostic_message.rs". use crate::{ - diagnostic::diagnostic_message::TemplateLoader, emit_diagnostic_to_uncolored_text, - emitter::EmitResultText, Diagnostic, DiagnosticStyle, Emitter, EmitterWriter, + diagnostic::diagnostic_message::TemplateLoader, emit_diagnostic_to_uncolored_text, Diagnostic, + DiagnosticStyle, Emitter, EmitterWriter, }; use anyhow::{bail, Context, Result}; use compiler_base_span::fatal_error::FatalError; diff --git a/compiler_base/error/src/lib.rs b/compiler_base/error/src/lib.rs index 21a4ea483..baca04ed1 100644 --- a/compiler_base/error/src/lib.rs +++ b/compiler_base/error/src/lib.rs @@ -14,6 +14,7 @@ mod emitter; mod tests; pub mod errors; +pub mod unit_type; pub use diagnostic::{ components, diagnostic_handler, style::DiagnosticStyle, Component, Diagnostic, StyledBuffer, diff --git a/compiler_base/error/src/unit_type.rs b/compiler_base/error/src/unit_type.rs new file mode 100644 index 000000000..02c0195c3 --- /dev/null +++ b/compiler_base/error/src/unit_type.rs @@ -0,0 +1,31 @@ +//! This file provides some of the self-encapsulated types used in handling error messages. + +/// [`TyeWithUnit`] is a trait for types that can be converted into a string with a unit. +pub trait TypeWithUnit { + fn into_string_with_unit(self) -> String; +} + +/// [`UnitUsize`] is a [`usize`] type that can be converted into a string with a unit. +pub struct UnitUsize(pub usize, pub String); + +impl TypeWithUnit for UnitUsize { + /// [`into_string_with_unit`] converts [`UnitUsize`] into a string with a unit. + /// + /// # Examples + /// + /// ``` + /// use compiler_base_error::unit_type::{TypeWithUnit, UnitUsize}; + /// + /// let unit_usize = UnitUsize(1, "byte".to_string()); + /// assert_eq!(unit_usize.into_string_with_unit(), "1 byte"); + /// let unit_usize = UnitUsize(2, "byte".to_string()); + /// assert_eq!(unit_usize.into_string_with_unit(), "2 bytes"); + /// ``` + fn into_string_with_unit(self) -> String { + if self.0 > 1 { + format!("{} {}s", self.0, self.1) + } else { + format!("{} {}", self.0, self.1) + } + } +} diff --git a/compiler_base/parallel/src/executor/tests.rs b/compiler_base/parallel/src/executor/tests.rs index 2e4d21584..ae0fa9b6d 100644 --- a/compiler_base/parallel/src/executor/tests.rs +++ b/compiler_base/parallel/src/executor/tests.rs @@ -124,7 +124,11 @@ mod test_timeout_executor { tasks.push(MyTask { id: i }) } - let executor = TimeoutExecutor::new_with_thread_count(thread_count); + let executor = TimeoutExecutor::new_with_thread_count_and_timeout( + thread_count, + Instant::now() + Duration::from_secs(120), + ); + let mut events_collector = Arc::new(Mutex::new(EventsCollector::default())); let expected_events = diff --git a/compiler_base/parallel/src/executor/timeout.rs b/compiler_base/parallel/src/executor/timeout.rs index 8dce4d1f7..8d9bf0682 100644 --- a/compiler_base/parallel/src/executor/timeout.rs +++ b/compiler_base/parallel/src/executor/timeout.rs @@ -25,6 +25,7 @@ pub(crate) struct TimeoutSituation { pub struct TimeoutExecutor { timeout_queue: VecDeque, capacity: usize, + timeout: Option, } impl TimeoutExecutor { @@ -37,6 +38,20 @@ impl TimeoutExecutor { TimeoutExecutor { timeout_queue: VecDeque::default(), capacity: thread_count, + timeout: Some(default_deadline_60_seconds()), + } + } + + /// New a [`TimeoutExecutor`] with [`thread_count`] and [`timeout`]. + pub fn new_with_thread_count_and_timeout(thread_count: usize, timeout: Instant) -> Self { + debug_assert!( + thread_count > 0, + "At least one thread is required to execute the task." + ); + TimeoutExecutor { + timeout_queue: VecDeque::default(), + capacity: thread_count, + timeout: Some(timeout), } } @@ -98,7 +113,11 @@ impl Executor for TimeoutExecutor { let tinfo = task.info(); // Calculate the deadline. - let deadline = default_deadline_60_seconds(); + let deadline = if let Some(timeout) = self.timeout { + timeout + } else { + default_deadline_60_seconds() + }; // Notify the log that the [`Task`] is waiting to be executed. let event = TaskEvent::wait(task.info()); diff --git a/compiler_base/session/src/lib.rs b/compiler_base/session/src/lib.rs index a93f7e5c5..5f134dc75 100644 --- a/compiler_base/session/src/lib.rs +++ b/compiler_base/session/src/lib.rs @@ -171,7 +171,7 @@ impl Session { pub fn emit_stashed_diagnostics_and_abort(&self) -> Result<&Self> { self.diag_handler .abort_if_errors() - .with_context(|| "Internale Bug: Fail to display error diagnostic")?; + .with_context(|| "Internal Bug: Fail to display error diagnostic")?; Ok(self) } diff --git a/docs/design/ide_kpm_workflow.md b/docs/design/ide_kpm_workflow.md new file mode 100644 index 000000000..186811d12 --- /dev/null +++ b/docs/design/ide_kpm_workflow.md @@ -0,0 +1,70 @@ +### Research Report: + +#### Introduction: +The research report explores the workflows of popular IDEs for languages like Python, Go, and Rust, focusing on package installation, virtual environments, automatic updates, and package project management. The report also proposes integrating similar functionalities into the KCL (Configuration Language) development environment. + +#### Python (PyCharm): +1. **Package Installation**: + - Users can install packages easily through PyCharm's built-in package manager. + - Proposal: Implement a search command to fetch packages from a global repository like ArtifactHub. + +2. **Virtual Environments**: + - PyCharm supports effortless creation and activation of virtual environments. + - Proposal: Integrate virtual environment creation for KCL development to mitigate version mismatch errors. + +3. **Automatic Updates**: + - PyCharm prompts users to update installed packages. + - Proposal: Implement automatic updates for the KCL package using a similar mechanism. + +4. **Package Project Management**: + - Project-specific dependencies can be managed via a `requirements.txt` file. + - Proposal: Introduce a `kcl.mod` file to specify dependencies and provide a command (`kpm install kcl.mod`) to download them. + +#### Go Language (Golang): +1. **Package Installation**: + - IDEs like GoLand or VSCode with the Go extension seamlessly integrate with Go modules. + - Proposal: Allow fetching dependencies of KCL packages directly within the IDE. + +2. **Virtual Environments**: + - Go relies on Go modules for dependency management. + - Proposal: Although Go doesn't have traditional virtual environments, creating an isolated environment for KCL development could enhance user experience. + +3. **Automatic Updates**: + - Go modules automatically check for updates to dependencies specified in `go.mod`. + - Proposal: Enable automatic updates for KCL packages. + +4. **Package Project Management**: + - Go projects typically use a `go.mod` file to specify dependencies. + - Proposal: Introduce tools for managing dependencies in KCL projects, similar to `go mod tidy`. + +#### Rust Language: + +1. **Package Installation**: + - IDEs such as IntelliJ IDEA with the Rust plugin or Visual Studio Code with the Rust extension support Cargo, Rust's package manager. + - Developers can use Cargo commands (`cargo build`, `cargo run`, `cargo test`, etc.) directly within the IDE to manage dependencies and build their projects. + +2. **Virtual Environments**: + - Rust projects utilize `Cargo.toml` files to specify dependencies and project configurations. + - IDEs provide tools to create and manage virtual environments using Cargo, enabling developers to isolate project dependencies effectively. + +3. **Automatic Updates**: + - Cargo also automatically checks for updates to dependencies specified in the `Cargo.toml` file. + +4. **Package Project Management**: + - Rust projects include a `Cargo.toml` file at the project root to declare dependencies and their versions. + + - Features like dependency resolution, semantic versioning support, and conflict resolution are commonly integrated into IDEs to streamline package management in Rust projects. + + + +### User Stories: + +1. **As a developer, I want to be able to search for and install packages easily from a global repository to simplify the process of adding dependencies to my KCL projects.** + +2. **As a developer, I want to create and manage virtual environments for KCL development to isolate project dependencies and avoid version mismatch errors.** + +3. **As a developer, I want the KCL package to be automatically updated when a new version is available to ensure that I'm using the latest version with bug fixes and improvements.** + +4. **As a developer, I want to fetch dependencies of KCL packages directly within my IDE, similar to GoLand's integration with Go modules, to simplify the process of adding dependencies and improve productivity.** + +5. **As a developer, I want tools for managing dependencies in KCL projects, similar to Go's `go mod tidy`, to ensure consistency and correctness of dependencies.** diff --git a/docs/dev_guide/1.about_this_guide.md b/docs/dev_guide/1.about_this_guide.md index e69a484ed..0e5cfc375 100644 --- a/docs/dev_guide/1.about_this_guide.md +++ b/docs/dev_guide/1.about_this_guide.md @@ -1,6 +1,6 @@ # About this Guide -This guide is intended to help document how `KCL` (the KCL compiler) works, and to help new contributors get involved in KCLVM development. +This guide is intended to help document how `KCL` (the KCL compiler) works, and to help new contributors get involved in KCL development. This guide consists of **4** parts: diff --git a/docs/dev_guide/2.quick_start.md b/docs/dev_guide/2.quick_start.md index e62f566a3..2e7fb81a8 100644 --- a/docs/dev_guide/2.quick_start.md +++ b/docs/dev_guide/2.quick_start.md @@ -42,7 +42,7 @@ Using a docker image is our recommended way, of course, you can also configure y #### macOS and OS X - `git` -- `Rust 1.60+` +- `Rust 1.76+` - `LLVM 12` - `Python 3.7+` (Only for integration tests). @@ -62,7 +62,7 @@ export PATH=/bin:$PATH #### Linux - `git` -- `Rust 1.60+` +- `Rust 1.76+` - `Python3 Building Dependencies` - `LLVM 12` @@ -105,7 +105,7 @@ ln -sf /usr/bin/wasm-ld-12 /usr/bin/wasm-ld #### Windows - `git` -- `Rust 1.60+` +- `Rust 1.76+` - `LLVM 12` - `Python 3.7+` (Only for integration tests). @@ -135,7 +135,7 @@ make build In the top level of the `kcl-lang/kcl` repo and run: ```sh -.\build_and_test_win.bat +.\build.ps1 ``` ### Testing diff --git a/icons/KCL128x128.png b/icons/KCL128x128.png deleted file mode 100644 index 2e1660d7f..000000000 Binary files a/icons/KCL128x128.png and /dev/null differ diff --git a/icons/KCL128x128.svg b/icons/KCL128x128.svg deleted file mode 100644 index ded49cd57..000000000 --- a/icons/KCL128x128.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - background - - - - Layer 1 - K - - \ No newline at end of file diff --git a/icons/KCL16x16.png b/icons/KCL16x16.png deleted file mode 100644 index e84bab49d..000000000 Binary files a/icons/KCL16x16.png and /dev/null differ diff --git a/icons/KCL16x16.svg b/icons/KCL16x16.svg deleted file mode 100644 index 761f6496f..000000000 --- a/icons/KCL16x16.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - background - - - - - - - Layer 1 - K - - \ No newline at end of file diff --git a/icons/KCL40x40.png b/icons/KCL40x40.png deleted file mode 100644 index 7fa6866c3..000000000 Binary files a/icons/KCL40x40.png and /dev/null differ diff --git a/icons/KCL40x40.svg b/icons/KCL40x40.svg deleted file mode 100644 index 390bb86ae..000000000 --- a/icons/KCL40x40.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - background - - - - Layer 1 - K - - \ No newline at end of file diff --git a/internal/scripts/cli/kcl b/internal/scripts/cli/kcl deleted file mode 100755 index 86b4daab4..000000000 --- a/internal/scripts/cli/kcl +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# kclvm_cli path -install_dir=$(cd `dirname $0`/..; pwd) -export PYTHONPATH=$install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$install_dir/bin -kclvm_cli_bin=$install_dir/bin/kclvm_cli -# Only for v0.4.x, all CLIs will be unified after v0.5.x -case $1 in - "version" | "--version" | "-v" | "-V") - $kclvm_cli_bin version - ;; - *) $kclvm_cli_bin run "$@" - ;; -esac diff --git a/internal/scripts/cli/kcl-doc b/internal/scripts/cli/kcl-doc deleted file mode 100755 index 1f71e77c2..000000000 --- a/internal/scripts/cli/kcl-doc +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# python3 path -python3_bin=`which python3` -kclvm_install_dir=$(cd `dirname $0`/..; pwd) -pip_install_done_file="$kclvm_install_dir/lib/site-packages/kclvm.requirements.done.txt" - -# check python3 -if [ -z "$python3_bin" ]; then - echo "python3 not found!" - exit 1 -fi - -# once: pip install -if [ ! -f $pip_install_done_file ]; then - # check python3 version - $python3_bin -c "import sys; sys.exit(0) if sys.version_info>=(3,7,3) else (print('please install python 3.7.3+') or sys.exit(1))" - # kclvm pip install all libs - $python3_bin -m pip install -U kclvm --user - echo 'done' > $pip_install_done_file -fi - -export PYTHONPATH=$kclvm_install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$kclvm_install_dir/bin -$python3_bin -m kclvm.tools.docs "$@" diff --git a/internal/scripts/cli/kcl-fmt b/internal/scripts/cli/kcl-fmt deleted file mode 100755 index d3ba1fc5d..000000000 --- a/internal/scripts/cli/kcl-fmt +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# kclvm_cli path -install_dir=$(cd `dirname $0`/..; pwd) -export PYTHONPATH=$install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$install_dir/bin -kclvm_cli_bin=$install_dir/bin/kclvm_cli -$kclvm_cli_bin fmt "$@" diff --git a/internal/scripts/cli/kcl-lint b/internal/scripts/cli/kcl-lint deleted file mode 100755 index 467fd4a76..000000000 --- a/internal/scripts/cli/kcl-lint +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# kclvm_cli path -install_dir=$(cd `dirname $0`/..; pwd) -export PYTHONPATH=$install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$install_dir/bin -kclvm_cli_bin=$install_dir/bin/kclvm_cli -$kclvm_cli_bin lint "$@" diff --git a/internal/scripts/cli/kcl-plugin b/internal/scripts/cli/kcl-plugin deleted file mode 100755 index 990927ac9..000000000 --- a/internal/scripts/cli/kcl-plugin +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# python3 path -python3_bin=`which python3` -kclvm_install_dir=$(cd `dirname $0`/..; pwd) -pip_install_done_file="$kclvm_install_dir/lib/site-packages/kclvm.requirements.done.txt" - -# check python3 -if [ -z "$python3_bin" ]; then - echo "python3 not found!" - exit 1 -fi - -# once: pip install -if [ ! -f $pip_install_done_file ]; then - # check python3 version - $python3_bin -c "import sys; sys.exit(0) if sys.version_info>=(3,7,3) else (print('please install python 3.7.3+') or sys.exit(1))" - # kclvm pip install all libs - $python3_bin -m pip install -U kclvm --user - echo 'done' > $pip_install_done_file -fi - -export PYTHONPATH=$kclvm_install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$kclvm_install_dir/bin -$python3_bin -m kclvm.tools.plugin "$@" - diff --git a/internal/scripts/cli/kcl-test b/internal/scripts/cli/kcl-test deleted file mode 100755 index 07f708482..000000000 --- a/internal/scripts/cli/kcl-test +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -kcl_go_path=$(cd `dirname $0`; pwd)/kcl-go -if [[ ! -f $kcl_go_path ]]; then - echo "kcl-go not found, please check the installation at https://github.com/kcl-lang/kcl-go" - exit 1 -fi -export PYTHONPATH='' -$kcl_go_path test "$@" diff --git a/internal/scripts/cli/kcl-vet b/internal/scripts/cli/kcl-vet deleted file mode 100755 index a74e0497f..000000000 --- a/internal/scripts/cli/kcl-vet +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -# kclvm_cli path -install_dir=$(cd `dirname $0`/..; pwd) -export PYTHONPATH=$install_dir/lib/site-packages -export KCLVM_CLI_BIN_PATH=$install_dir/bin -kclvm_cli_bin=$install_dir/bin/kclvm_cli -$kclvm_cli_bin vet "$@" diff --git a/internal/scripts/cli/kclvm b/internal/scripts/cli/kclvm deleted file mode 100755 index 453a6bdbe..000000000 --- a/internal/scripts/cli/kclvm +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# Stop on error. -set -e - -kclvm_install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$kclvm_install_dir/bin -export PYTHONPATH=$kclvm_install_dir/lib/site-packages -python3 "$@" diff --git a/internal/scripts/python-plugin/build-cpython.sh b/internal/scripts/python-plugin/build-cpython.sh deleted file mode 100755 index 83ef00235..000000000 --- a/internal/scripts/python-plugin/build-cpython.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash - -# Stop on error. -set -e - -topdir=$PWD -# Environment -if [ -f "/etc/os-release" ]; then - source /etc/os-release - os=$ID -else - os=$(uname) -fi - -prepare_dirs () { - cpython_build_dir="$topdir/_build/build/$os/cpython" - mkdir -p "$cpython_build_dir" - cpython_install_dir="$topdir/_build/python_dist/$os/cpython" - mkdir -p "$cpython_install_dir" -} - -# Switch configuration options. -config_option="Default" -if [ "$os" != "" ]; then - config_option=$os -fi - -# python version -py_ver_major="3" -py_ver_minor="7" -py_ver_micro="6" - -for config in "$config_option" -do - case $config in - "Default" | "centos") - config_envs="LANG=C.UTF-8" - config_options="--enable-optimizations --with-ssl" - echo "$REPLY: The configuration is $config: config_envs=$config_envs config_options=$config_options" - break - ;; - "Darwin") - if [ "$sslpath" == "" ]; then - sslpath=$(brew --prefix openssl@1.1) - fi - - py_ver_major="3" - py_ver_minor="9" - py_ver_micro="12" - - config_envs="LANG=C.UTF-8" - config_options="--enable-optimizations --with-openssl=$sslpath --with-ssl-default-suites=python" - echo "$REPLY: The configuration is $config: config_envs=$config_envs config_options=$config_options" - break - ;; - "ubuntu" | "debian" | "Ubuntu" |"Debian" | "Static-Debian" | "Cood1-Debian" | "Cood1Shared-Debian") - config_envs="CFLAGS=-Wno-coverage-mismatch" - config_options="--enable-optimizations --with-ssl" - echo "$REPLY: The configuration is $config: config_envs=$config_envs config_options=$config_options" - break - ;; - *) echo "Invalid config option $REPLY:$config" - exit 1 - break - ;; - esac -done - -# py_ver_str="$(python3 -c 'import os; print(os.path.basename(os.path.dirname(os.__file__)))')" -py_ver_str="${py_ver_major}.${py_ver_minor}.${py_ver_micro}" - -# wget python -mkdir -p $topdir/_build/3rdparty -wget -P $topdir/_build/3rdparty "https://www.python.org/ftp/python/${py_ver_str}/Python-${py_ver_str}.tgz" -tar zxvf $topdir/_build/3rdparty/Python-${py_ver_str}.tgz -C $topdir/_build/3rdparty - -prepare_dirs -prefix_option="--prefix=$cpython_install_dir" -cpython_source_dir="$topdir/_build/3rdparty/Python-${py_ver_str}" - -# Perform the configuration/make/make install process. -set -x -cd $cpython_build_dir -eval $config_envs $cpython_source_dir/configure $prefix_option $config_options "--enable-shared" -eval $config_envs $cpython_source_dir/configure $prefix_option $config_options -# The make -j command may fail on some OS. -# make -j "$(nproc)" -make -j8 build_all -make -j8 altinstall -set +x - -# Print the summary. -echo "================ Summary ================" -echo " CPython is built into $cpython_build_dir" diff --git a/internal/scripts/python-plugin/build-kcl.sh b/internal/scripts/python-plugin/build-kcl.sh deleted file mode 100755 index 685e3e89d..000000000 --- a/internal/scripts/python-plugin/build-kcl.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env bash - -# Stop on error. -set -e - -topdir=$PWD -# Environment -if [ -f "/etc/os-release" ]; then - source /etc/os-release - os=$ID -else - os=$(uname) -fi - -prepare_dirs () { - cpython_build_dir="$topdir/_build/python_dist/$os/cpython" - kclvm_packages_dir="$topdir/_build/packages" - kcl_install_dir="$topdir/_build/python_dist/$os/kclvm" - mkdir -p "$kcl_install_dir" - mkdir -p "$kclvm_packages_dir" -} - -prepare_dirs - -# python exe name -py_exe_name="python3.7" -if [ -d "${cpython_build_dir}/lib/python3.9" ]; then - py_exe_name="python3.9" -fi - -# py_lib_basename: python3.x -py_lib_basename="python3.7" -if [ -d "${cpython_build_dir}/lib/python3.9" ]; then - py_lib_basename="python3.9" -fi - -# Perform the build process. -set -x - -# Copy files from CPython. -cd $kcl_install_dir -mkdir -p bin -mkdir -p lib -cp $cpython_build_dir/bin/${py_exe_name} $kcl_install_dir/bin/kclvm -cp -r $cpython_build_dir/lib/${py_lib_basename} $kcl_install_dir/lib/ - -# Darwin dylib -if [ -e $cpython_build_dir/lib/lib${py_lib_basename}.dylib ]; then - touch $kcl_install_dir/lib/lib${py_lib_basename}.dylib - rm $kcl_install_dir/lib/lib${py_lib_basename}.dylib - mv $cpython_build_dir/lib/lib${py_lib_basename}.dylib $kcl_install_dir/lib/lib${py_lib_basename}.dylib -fi -# Linux so -if [ -e $cpython_build_dir/lib/lib${py_lib_basename}m.so.1.0 ]; then - touch $kcl_install_dir/lib/lib${py_lib_basename}.so - rm $kcl_install_dir/lib/lib${py_lib_basename}.so - mv $cpython_build_dir/lib/lib${py_lib_basename}m.so.1.0 $kcl_install_dir/lib/lib${py_lib_basename}.so -fi -# Windows dll -if [ -e $cpython_build_dir/lib/lib${py_lib_basename}.dll ]; then - touch $kcl_install_dir/lib/lib${py_lib_basename}.dll - rm $kcl_install_dir/lib/lib${py_lib_basename}.dll - mv $cpython_build_dir/lib/lib${py_lib_basename}.dll $kcl_install_dir/lib/lib${py_lib_basename}.dll -fi -cp -r $cpython_build_dir/include $kcl_install_dir/ - -# Copy KCL Scripts. -scripts_dir="$topdir/internal/scripts/python-plugin/cli" -cp "$scripts_dir/kcl" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-plugin" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-doc" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-test" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-lint" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-fmt" $kcl_install_dir/bin/ -cp "$scripts_dir/kcl-vet" $kcl_install_dir/bin/ -chmod +x $kcl_install_dir/bin/kcl -chmod +x $kcl_install_dir/bin/kcl-plugin -chmod +x $kcl_install_dir/bin/kcl-doc -chmod +x $kcl_install_dir/bin/kcl-test -chmod +x $kcl_install_dir/bin/kcl-lint -chmod +x $kcl_install_dir/bin/kcl-fmt -chmod +x $kcl_install_dir/bin/kcl-vet - -if [ -d $kcl_install_dir/lib/${py_lib_basename}/kclvm ]; then - rm -rf $kcl_install_dir/lib/${py_lib_basename}/kclvm -fi - -# Get site-packages. -$kcl_install_dir/bin/kclvm -m pip install --upgrade -U kclvm - -# Install plugins -cp -rf $topdir/plugins $kcl_install_dir/ - -set +x - -# build kcl - -cd $topdir/kclvm -cargo build --release - -# Switch dll file extension according to os. -dll_extension="so" -case $os in - "Default" | "default" | "centos" | "ubuntu" | "debian" | "Ubuntu" |"Debian" | "Static-Debian" | "Cood1-Debian" | "Cood1Shared-Debian") - dll_extension="so" - ;; - "Darwin" | "darwin" | "ios" | "macos") - dll_extension="dylib" - ;; - *) dll_extension="dll" - ;; -esac - -# Copy libkclvm_cli lib - -if [ -e $topdir/kclvm/target/release/libkclvm_cli_cdylib.$dll_extension ]; then - touch $kcl_install_dir/bin/libkclvm_cli_cdylib.$dll_extension - rm $kcl_install_dir/bin/libkclvm_cli_cdylib.$dll_extension - cp $topdir/kclvm/target/release/libkclvm_cli_cdylib.$dll_extension $kcl_install_dir/bin/libkclvm_cli_cdylib.$dll_extension -fi - -# build kcl LSP server - -cd $topdir/kclvm/tools/src/LSP -cargo build --release - -touch $kcl_install_dir/bin/kcl-language-server -rm $kcl_install_dir/bin/kcl-language-server -cp $topdir/kclvm/target/release/kcl-language-server $kcl_install_dir/bin/kcl-language-server - - -cd $topdir/kclvm_cli -cargo build --release - -touch $kcl_install_dir/bin/kclvm_cli -rm $kcl_install_dir/bin/kclvm_cli -cp ./target/release/kclvm_cli $kcl_install_dir/bin/kclvm_cli - - -# Copy kcl C API header -cd $topdir/kclvm/runtime -cp src/_kclvm.h $kcl_install_dir/include/_kclvm.h - -# build kcl plugin python module -cd $topdir/kclvm/plugin -cp ./kclvm_plugin.py $kcl_install_dir/lib/site-packages/ -cp ./kclvm_runtime.py $kcl_install_dir/lib/site-packages/ - -cd $topdir -# Print the summary. -echo "================ Summary ================" -echo " KCLVM is updated into $kcl_install_dir" diff --git a/internal/scripts/python-plugin/cli/kcl b/internal/scripts/python-plugin/cli/kcl deleted file mode 100755 index 5d7457a2a..000000000 --- a/internal/scripts/python-plugin/cli/kcl +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-doc b/internal/scripts/python-plugin/cli/kcl-doc deleted file mode 100755 index eb3f2983d..000000000 --- a/internal/scripts/python-plugin/cli/kcl-doc +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm.tools.docs "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-fmt b/internal/scripts/python-plugin/cli/kcl-fmt deleted file mode 100755 index 0c5b353dd..000000000 --- a/internal/scripts/python-plugin/cli/kcl-fmt +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm.tools.format "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-lint b/internal/scripts/python-plugin/cli/kcl-lint deleted file mode 100755 index fd060ef27..000000000 --- a/internal/scripts/python-plugin/cli/kcl-lint +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm.tools.lint.lint "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-plugin b/internal/scripts/python-plugin/cli/kcl-plugin deleted file mode 100755 index edf9330f7..000000000 --- a/internal/scripts/python-plugin/cli/kcl-plugin +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm.tools.plugin "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-test b/internal/scripts/python-plugin/cli/kcl-test deleted file mode 100755 index 212e6c951..000000000 --- a/internal/scripts/python-plugin/cli/kcl-test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -kcl_go_path=$(cd `dirname $0`; pwd)/kcl-go -if [[ ! -f $kcl_go_path ]]; then - echo "kcl-go not found, please check the installation" - exit 1 -fi -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kcl_go_path test "$@" diff --git a/internal/scripts/python-plugin/cli/kcl-vet b/internal/scripts/python-plugin/cli/kcl-vet deleted file mode 100755 index 32ae6d6e9..000000000 --- a/internal/scripts/python-plugin/cli/kcl-vet +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -kclvm_path=$(cd `dirname $0`; pwd)/kclvm -install_dir=$(cd `dirname $0`/..; pwd) -export KCLVM_CLI_BIN_PATH=$install_dir/bin -export PATHONPATH='' -$kclvm_path -m kclvm.tools.validation "$@" diff --git a/internal/scripts/python-plugin/release.sh b/internal/scripts/python-plugin/release.sh deleted file mode 100755 index f21fdb777..000000000 --- a/internal/scripts/python-plugin/release.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -topdir=$PWD -# Environment -if [ -f "/etc/os-release" ]; then - source /etc/os-release - os=$ID -else - os=$(uname) -fi - -release_file="kclvm-$os-latest.tar.gz" -release_path="$topdir/_build" -package_dir="$topdir/_build/python_dist/$os" -install_dir="kclvm" - -cd $package_dir -tar -czvf $release_file $install_dir - -mv $package_dir/$release_file $release_path/$release_file - -# Print the summary. -echo "================ Summary ================" -echo " $release_path/$release_file has been created" diff --git a/internal/spec/gpyrpc/gpyrpc.proto b/internal/spec/gpyrpc/gpyrpc.proto deleted file mode 100644 index b36ee9dcc..000000000 --- a/internal/spec/gpyrpc/gpyrpc.proto +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2023 The KCL Authors. All rights reserved. -// -// This file defines the request parameters and return structure of the KCLVM RPC server. -// We can use the following command to start a KCLVM RPC server. - -syntax = "proto3"; - -package gpyrpc; - -import "google/protobuf/any.proto"; -import "google/protobuf/descriptor.proto"; - -// ---------------------------------------------------------------------------- - -// kcl main.k -E pkg_name=pkg_path -message CmdExternalPkgSpec { - string pkg_name = 1; - string pkg_path = 2; -} - -// kcl main.k -D name=value -message CmdArgSpec { - string name = 1; - string value = 2; // TODO: any? -} - -// kcl main.k -O pkgpath:path.to.field=field_value -message CmdOverrideSpec { - string pkgpath = 1; - string field_path = 2; - string field_value = 3; - string action = 4; -} - -// ---------------------------------------------------------------------------- -// gpyrpc request/response/error types -// ---------------------------------------------------------------------------- - -message RestResponse { - google.protobuf.Any result = 1; - string error = 2; - KclError kcl_err = 3; -} - -message KclError { - string ewcode = 1; // See kclvm/kcl/error/kcl_err_msg.py - string name = 2; - string msg = 3; - repeated KclErrorInfo error_infos = 4; -} - -message KclErrorInfo { - string err_level = 1; - string arg_msg = 2; - string filename = 3; - string src_code = 4; - string line_no = 5; - string col_no = 6; -} - -// ---------------------------------------------------------------------------- -// service requset/response -// ---------------------------------------------------------------------------- - -// gpyrpc.BuiltinService -service BuiltinService { - rpc Ping(Ping_Args) returns(Ping_Result); - rpc ListMethod(ListMethod_Args) returns(ListMethod_Result); -} - -// gpyrpc.KclvmService -service KclvmService { - rpc Ping(Ping_Args) returns(Ping_Result); - - rpc ExecProgram(ExecProgram_Args) returns(ExecProgram_Result); - - rpc FormatCode(FormatCode_Args) returns(FormatCode_Result); - rpc FormatPath(FormatPath_Args) returns(FormatPath_Result); - rpc LintPath(LintPath_Args) returns(LintPath_Result); - rpc OverrideFile(OverrideFile_Args) returns (OverrideFile_Result); - - rpc GetSchemaType(GetSchemaType_Args) returns(GetSchemaType_Result); - rpc GetSchemaTypeMapping(GetSchemaTypeMapping_Args) returns(GetSchemaTypeMapping_Result); - rpc ValidateCode(ValidateCode_Args) returns(ValidateCode_Result); - - rpc ListDepFiles(ListDepFiles_Args) returns(ListDepFiles_Result); - rpc LoadSettingsFiles(LoadSettingsFiles_Args) returns(LoadSettingsFiles_Result); -} - -message Ping_Args { - string value = 1; -} -message Ping_Result { - string value = 1; -} - -message ListMethod_Args { - // empty -} -message ListMethod_Result { - repeated string method_name_list = 1; -} - -message ParseFile_AST_Args { - string filename = 1; - string source_code = 2; -} -message ParseFile_AST_Result { - string ast_json = 1; // json value - KclError kcl_err = 2; -} - -message ParseProgram_AST_Args { - repeated string k_filename_list = 1; -} -message ParseProgram_AST_Result { - string ast_json = 1; // json value - KclError kcl_err = 2; -} - -message ExecProgram_Args { - string work_dir = 1; - - repeated string k_filename_list = 2; - repeated string k_code_list = 3; - - repeated CmdArgSpec args = 4; - repeated CmdOverrideSpec overrides = 5; - - bool disable_yaml_result = 6; - - bool print_override_ast = 7; - - // -r --strict-range-check - bool strict_range_check = 8; - - // -n --disable-none - bool disable_none = 9; - // -v --verbose - int32 verbose = 10; - - // -d --debug - int32 debug = 11; - - // yaml/json: sort keys - bool sort_keys = 12; - // include schema type path in JSON/YAML result - bool include_schema_type_path = 13; - - // -E --external : external packages path - repeated CmdExternalPkgSpec external_pkgs = 14; -} -message ExecProgram_Result { - string json_result = 1; - string yaml_result = 2; - - string escaped_time = 101; -} - -message ResetPlugin_Args { - string plugin_root = 1; -} -message ResetPlugin_Result { - // empty -} - -message FormatCode_Args { - string source = 1; -} - -message FormatCode_Result { - bytes formatted = 1; -} - -message FormatPath_Args { - string path = 1; -} - -message FormatPath_Result { - repeated string changed_paths = 1; -} - -message LintPath_Args { - repeated string paths = 1; -} - -message LintPath_Result { - repeated string results = 1; -} - -message OverrideFile_Args { - string file = 1; - repeated string specs = 2; - repeated string import_paths = 3; -} - -message OverrideFile_Result { - bool result = 1; -} - -message GetSchemaType_Args { - string file = 1; - string code = 2; - string schema_name = 3; -} -message GetSchemaType_Result { - repeated KclType schema_type_list = 1; -} - -message GetSchemaTypeMapping_Args { - string file = 1; - string code = 2; - string schema_name = 3; -} -message GetSchemaTypeMapping_Result { - map schema_type_mapping = 1; -} - -message ValidateCode_Args { - string data = 1; - string code = 2; - string schema = 3; - string attribute_name = 4; - string format = 5; -} - -message ValidateCode_Result { - bool success = 1; - string err_message = 2; -} - -message Position { - int64 line = 1; - int64 column = 2; - string filename = 3; -} - -message ListDepFiles_Args { - string work_dir = 1; - bool use_abs_path = 2; - bool include_all = 3; - bool use_fast_parser = 4; -} - -message ListDepFiles_Result { - string pkgroot = 1; - string pkgpath = 2; - repeated string files = 3; -} - -// --------------------------------------------------------------------------------- -// LoadSettingsFiles API -// Input work dir and setting files and return the merged kcl singleton config. -// --------------------------------------------------------------------------------- - -message LoadSettingsFiles_Args { - string work_dir = 1; - repeated string files = 2; -} - -message LoadSettingsFiles_Result { - CliConfig kcl_cli_configs = 1; - repeated KeyValuePair kcl_options = 2; -} - -message CliConfig { - repeated string files = 1; - string output = 2; - repeated string overrides = 3; - repeated string path_selector = 4; - bool strict_range_check = 5; - bool disable_none = 6; - int64 verbose = 7; - bool debug = 8; - bool sort_keys = 9; -} - -message KeyValuePair { - string key = 1; - string value = 2; -} - -// ---------------------------------------------------------------------------- -// JSON Schema Lit -// ---------------------------------------------------------------------------- - -message KclType { - string type = 1; // schema, dict, list, str, int, float, bool, null, type_string - repeated KclType union_types = 2 ; // union types - string default = 3; // default value - - string schema_name = 4; // schema name - string schema_doc = 5; // schema doc - map properties = 6; // schema properties - repeated string required = 7; // required schema properties, [property_name1, property_name2] - - KclType key = 8; // dict key type - KclType item = 9; // dict/list item type - - int32 line = 10; - - repeated Decorator decorators = 11; // schema decorators -} - -message Decorator { - string name = 1; - repeated string arguments = 2; - map keywords = 3; -} - -// ---------------------------------------------------------------------------- -// END -// ---------------------------------------------------------------------------- diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index dc29b7958..e49a11260 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -46,6 +46,12 @@ dependencies = [ "log", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -55,17 +61,11 @@ dependencies = [ "libc", ] -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "annotate-snippets" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b9d411ecbaf79885c6df4d75fff75858d5995ff25385657a28af47e82f9c36" +checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" dependencies = [ "unicode-width", "yansi-term", @@ -80,23 +80,37 @@ dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", - "anstyle-wincon", + "anstyle-wincon 1.0.1", "colorchoice", "is-terminal", "utf8parse", ] +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon 3.0.2", + "colorchoice", + "utf8parse", +] + [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -120,20 +134,30 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" dependencies = [ "backtrace", ] [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-stream" @@ -154,7 +178,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -176,9 +200,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -222,6 +246,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitmaps" version = "2.1.0" @@ -231,13 +261,25 @@ dependencies = [ "typenum", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -246,7 +288,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -257,32 +308,41 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "bumpalo" -version = "3.12.2" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] -name = "bytes" -version = "1.4.0" +name = "byte-tools" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] -name = "cast" -version = "0.3.0" +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -298,13 +358,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "serde", "time 0.1.45", @@ -318,91 +378,31 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23170228b96236b5a7299057ac284a321457700bc8c41a4476052f0f4ba5349d" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", "stacker", ] -[[package]] -name = "ciborium" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" - -[[package]] -name = "ciborium-ll" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap 0.11.0", - "unicode-width", -] - [[package]] name = "clap" -version = "3.2.25" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "bitflags", - "clap_lex 0.2.4", - "indexmap", - "textwrap 0.16.0", -] - -[[package]] -name = "clap" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.3.0" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ - "anstream", + "anstream 0.3.2", "anstyle", - "bitflags", - "clap_lex 0.5.0", + "clap_lex", "strsim", ] -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "clap_lex" version = "0.5.0" @@ -417,9 +417,7 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "compiler_base_error" -version = "0.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42fb2dab6f1cffab069d1b841bb11ecb4e32c5582bea35dc4d575bfa20d5517c" +version = "0.0.10" dependencies = [ "anyhow", "compiler_base_macros", @@ -462,7 +460,7 @@ name = "compiler_base_session" version = "0.0.13" dependencies = [ "anyhow", - "compiler_base_error 0.0.10", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_base_span 0.0.1", ] @@ -482,18 +480,6 @@ dependencies = [ "rustc_span", ] -[[package]] -name = "console" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "windows-sys 0.42.0", -] - [[package]] name = "const_fn" version = "0.4.9" @@ -508,85 +494,13 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap 2.34.0", - "criterion-plot 0.4.5", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap 3.2.25", - "criterion-plot 0.5.0", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -610,9 +524,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -623,9 +537,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -636,62 +550,21 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] -[[package]] -name = "csv" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ctor" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b" -dependencies = [ - "quote", - "syn 2.0.16", -] - [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" dependencies = [ "cfg-if 1.0.0", - "hashbrown", + "hashbrown 0.14.3", "lock_api", "once_cell", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -700,20 +573,29 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common", @@ -754,20 +636,14 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] -[[package]] -name = "dissimilar" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e" - [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "ena" @@ -778,12 +654,6 @@ dependencies = [ "log", ] -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "enquote" version = "1.1.0" @@ -793,24 +663,40 @@ dependencies = [ "thiserror", ] +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" dependencies = [ + "anstream 0.6.13", + "anstyle", + "env_filter", "humantime", - "is-terminal", "log", - "regex", - "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" dependencies = [ "serde", ] @@ -836,16 +722,6 @@ dependencies = [ "libc", ] -[[package]] -name = "expect-test" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3" -dependencies = [ - "dissimilar", - "once_cell", -] - [[package]] name = "fancy-regex" version = "0.7.1" @@ -858,11 +734,20 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + +[[package]] +name = "filetime" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ - "instant", + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", ] [[package]] @@ -892,7 +777,7 @@ dependencies = [ "intl-memoizer", "intl_pluralrules", "rustc-hash", - "self_cell", + "self_cell 0.10.3", "smallvec", "unic-langid", ] @@ -917,13 +802,22 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "fslock" version = "0.2.1" @@ -940,12 +834,6 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures" version = "0.3.28" @@ -1002,7 +890,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -1036,10 +924,22 @@ dependencies = [ ] [[package]] -name = "gcc" -version = "0.3.55" +name = "generational-arena" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "generic-array" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] [[package]] name = "generic-array" @@ -1053,31 +953,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "ghost" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77ac7b51b8e6313251737fcef4b1c01a2ea102bde68415b62c0ee9268fec357" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glob" @@ -1085,12 +974,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - [[package]] name = "hashbrown" version = "0.12.3" @@ -1100,6 +983,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.3.3" @@ -1126,18 +1015,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humantime" @@ -1147,9 +1027,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1170,9 +1050,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1185,7 +1065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" dependencies = [ "bitmaps", - "rand_core 0.6.4", + "rand_core", "rand_xoshiro", "sized-chunks", "typenum", @@ -1199,14 +1079,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "rustc-rayon 0.5.0", ] +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "inkwell" version = "0.2.0" -source = "git+https://github.com/TheDan64/inkwell?branch=master#41d335bccac4b1c2554a81aa7024e2b6018e6e48" +source = "git+https://github.com/TheDan64/inkwell?branch=master#4030f764f1c889f36429ac02ef32e04fcfa8ce33" dependencies = [ "either", "inkwell_internals", @@ -1219,24 +1109,31 @@ dependencies = [ [[package]] name = "inkwell_internals" version = "0.8.0" -source = "git+https://github.com/TheDan64/inkwell?branch=master#41d335bccac4b1c2554a81aa7024e2b6018e6e48" +source = "git+https://github.com/TheDan64/inkwell?branch=master#4030f764f1c889f36429ac02ef32e04fcfa8ce33" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] -name = "insta" -version = "1.29.0" +name = "inotify" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a28d25139df397cbca21408bb742cf6837e04cdbebf1b07b760caf971d6a972" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" dependencies = [ - "console", - "lazy_static", - "linked-hash-map", - "similar", - "yaml-rust", + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", ] [[package]] @@ -1269,33 +1166,17 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.5" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7741301a6d6a9b28ce77c0fb77a4eb116b6bc8f3bef09923f7743d059c4157d3" -dependencies = [ - "ctor 0.2.0", - "ghost", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] +checksum = "a53088c87cf71c9d4f3372a2cb9eea1e7b8a0b1bf8b7f7d23fe5b76dbb07e63b" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", + "hermit-abi 0.3.2", "rustix", "windows-sys 0.48.0", ] @@ -1311,9 +1192,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -1324,15 +1205,31 @@ dependencies = [ "libc", ] +[[package]] +name = "jod-thread" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" + [[package]] name = "js-sys" -version = "0.3.62" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-spanned-value" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb343fa4e3b1b22b344937deedac88da995abf139c2232cbeaa436c38380a210" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "jsonrpc-core" version = "18.0.0" @@ -1363,30 +1260,37 @@ dependencies = [ [[package]] name = "kcl-language-server" -version = "0.1.0" +version = "0.8.1" dependencies = [ "anyhow", "chrono", "chumsky", + "clap", "compiler_base_session", "crossbeam-channel", "dashmap", "env_logger", "im-rc", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-config", "kclvm-driver", "kclvm-error", "kclvm-parser", + "kclvm-query", "kclvm-sema", + "kclvm-span", "kclvm-tools", "kclvm-utils", + "kclvm-version", "log", "lsp-server", "lsp-types", + "maplit", "parking_lot 0.12.1", + "proc_macro_crate", "ra_ap_vfs", + "ra_ap_vfs-notify", "ropey", "rustc-hash", "rustc_lexer", @@ -1400,7 +1304,7 @@ dependencies = [ [[package]] name = "kclvm" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", "cc", @@ -1408,7 +1312,7 @@ dependencies = [ "compiler_base_session", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", "kclvm-api", "kclvm-ast", "kclvm-cmd", @@ -1416,6 +1320,7 @@ dependencies = [ "kclvm-config", "kclvm-driver", "kclvm-error", + "kclvm-loader", "kclvm-parser", "kclvm-query", "kclvm-runner", @@ -1425,6 +1330,7 @@ dependencies = [ "kclvm-version", "libc", "libloading", + "maplit", "serde", "serde_json", "walkdir", @@ -1432,24 +1338,26 @@ dependencies = [ [[package]] name = "kclvm-api" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", - "criterion 0.4.0", "futures", - "indexmap", + "indexmap 1.9.3", "jsonrpc-stdio-server", + "kcl-language-server", "kclvm-ast", "kclvm-ast-pretty", "kclvm-config", "kclvm-driver", "kclvm-error", + "kclvm-loader", "kclvm-parser", "kclvm-query", "kclvm-runner", "kclvm-runtime", "kclvm-sema", "kclvm-tools", + "maplit", "once_cell", "prost", "prost-build", @@ -1460,43 +1368,43 @@ dependencies = [ "protoc-bin-vendored", "serde", "serde_json", - "serde_yaml 0.9.21", + "serde_yaml", "tempfile", "tokio", ] [[package]] name = "kclvm-ast" -version = "0.5.0" +version = "0.8.1" dependencies = [ "compiler_base_span 0.0.2", "kclvm-error", - "kclvm-parser", "kclvm-span", "serde", "serde_json", + "thread_local", + "uuid", ] [[package]] name = "kclvm-ast-pretty" -version = "0.5.0" +version = "0.8.1" dependencies = [ "compiler_base_macros", "compiler_base_session", "fancy-regex", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-error", - "kclvm-parser", "pretty_assertions", ] [[package]] name = "kclvm-cmd" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", - "clap 4.3.0", + "clap", "compiler_base_session", "kclvm-api", "kclvm-config", @@ -1511,13 +1419,13 @@ dependencies = [ [[package]] name = "kclvm-compiler" -version = "0.5.0" +version = "0.8.1" dependencies = [ "ahash", "bit-set", - "bitflags", + "bitflags 1.3.2", "fancy-regex", - "indexmap", + "indexmap 1.9.3", "inkwell", "kclvm-ast", "kclvm-error", @@ -1531,7 +1439,7 @@ dependencies = [ [[package]] name = "kclvm-config" -version = "0.5.0" +version = "0.8.1" dependencies = [ "ahash", "anyhow", @@ -1539,24 +1447,26 @@ dependencies = [ "dirs", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-utils", "kclvm-version", + "md-5 0.8.0", "pathdiff", + "pcre2", "ron", - "rust-crypto", "serde", "serde_json", - "serde_yaml 0.8.26", + "serde_yaml", "toml", ] [[package]] name = "kclvm-driver" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", + "glob", "kclvm-ast", "kclvm-config", "kclvm-parser", @@ -1569,35 +1479,47 @@ dependencies = [ [[package]] name = "kclvm-error" -version = "0.5.0" +version = "0.8.1" dependencies = [ "annotate-snippets", "anyhow", "atty", - "compiler_base_error 0.0.10", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_base_macros", "compiler_base_session", "compiler_base_span 0.0.2", - "indexmap", + "indexmap 1.9.3", "kclvm-runtime", "kclvm-span", + "serde_json", "termize", "tracing", ] [[package]] name = "kclvm-lexer" -version = "0.5.0" +version = "0.8.1" dependencies = [ - "expect-test", "kclvm-error", "rustc_lexer", "unic-emoji-char", ] +[[package]] +name = "kclvm-loader" +version = "0.8.1" +dependencies = [ + "anyhow", + "indexmap 1.9.3", + "kclvm-ast", + "kclvm-error", + "kclvm-parser", + "kclvm-sema", +] + [[package]] name = "kclvm-macros" -version = "0.5.0" +version = "0.8.1" dependencies = [ "proc-macro2", "quote", @@ -1607,28 +1529,27 @@ dependencies = [ [[package]] name = "kclvm-parser" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", "bstr", "compiler_base_error 0.0.10", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_base_macros", "compiler_base_session", "compiler_base_span 0.0.2", "either", "enquote", - "expect-test", - "indexmap", - "insta", + "indexmap 1.9.3", "kclvm-ast", "kclvm-config", "kclvm-error", "kclvm-lexer", - "kclvm-runtime", "kclvm-sema", "kclvm-span", "kclvm-utils", "num-bigint", + "petgraph", "regex", "rustc_lexer", "serde", @@ -1639,33 +1560,32 @@ dependencies = [ [[package]] name = "kclvm-query" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", "compiler_base_macros", "compiler_base_session", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-ast-pretty", "kclvm-error", "kclvm-parser", "kclvm-sema", - "pretty_assertions", + "maplit", ] [[package]] name = "kclvm-runner" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", "cc", "chrono", "compiler_base_macros", "compiler_base_session", - "criterion 0.3.6", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-compiler", "kclvm-config", @@ -1684,19 +1604,21 @@ dependencies = [ "serde_json", "tempfile", "threadpool", + "uuid", "walkdir", ] [[package]] name = "kclvm-runtime" -version = "0.5.0" +version = "0.8.1" dependencies = [ "ahash", "base64", "bstr", "chrono", "fancy-regex", - "indexmap", + "glob", + "indexmap 1.9.3", "itertools", "kclvm_runtime_internal_macros", "libc", @@ -1706,44 +1628,51 @@ dependencies = [ "regex", "serde", "serde_json", - "serde_yaml 0.8.26", + "serde_yaml", "sha1", "sha2 0.9.9", "unic-ucd-bidi", "unic-ucd-category", "unicode-casing", + "uuid", ] [[package]] name = "kclvm-sema" -version = "0.5.0" +version = "0.8.1" dependencies = [ "ahash", "anyhow", "bit-set", - "bitflags", - "compiler_base_error 0.0.8", + "bitflags 1.3.2", + "compiler_base_error 0.0.10", "compiler_base_macros", "compiler_base_session", "compiler_base_span 0.0.2", - "criterion 0.3.6", "fancy-regex", - "indexmap", + "generational-arena", + "indexmap 1.9.3", "kclvm-ast", + "kclvm-ast-pretty", "kclvm-error", - "kclvm-parser", "kclvm-runtime", "kclvm-span", + "kclvm-utils", + "lazy_static", "once_cell", + "pcre2", "petgraph", "phf", "regex", + "serde", + "serde_json", + "suggestions", "unicode_names2", ] [[package]] name = "kclvm-span" -version = "0.5.0" +version = "0.8.1" dependencies = [ "compiler_base_span 0.0.2", "kclvm-macros", @@ -1753,13 +1682,14 @@ dependencies = [ [[package]] name = "kclvm-tools" -version = "0.5.0" +version = "0.8.1" dependencies = [ "anyhow", "compiler_base_session", - "criterion 0.3.6", + "compiler_base_span 0.0.1", "fancy-regex", - "indexmap", + "indexmap 1.9.3", + "json-spanned-value", "kclvm-ast", "kclvm-ast-pretty", "kclvm-config", @@ -1770,22 +1700,26 @@ dependencies = [ "kclvm-runner", "kclvm-runtime", "kclvm-sema", + "kclvm-utils", + "located_yaml", "once_cell", - "pretty_assertions", "regex", "rustc_lexer", "serde_json", - "serde_yaml 0.9.21", + "serde_yaml", "walkdir", ] [[package]] name = "kclvm-utils" -version = "0.5.0" +version = "0.8.1" +dependencies = [ + "anyhow", +] [[package]] name = "kclvm-version" -version = "0.5.0" +version = "0.8.1" dependencies = [ "vergen", ] @@ -1799,6 +1733,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1807,9 +1761,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -1823,21 +1777,25 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.6" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" +dependencies = [ + "serde", + "serde_test", +] [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "llvm-sys" -version = "120.2.6" +version = "120.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909fd0ded1d3becfa3d52581b33602d87160d63da6a3844a86a51b0c93e8460c" +checksum = "624f2692f436769c7eb85a13eeca3f6fb9705a4b2bd0473ac9577c90f19e21ef" dependencies = [ "cc", "lazy_static", @@ -1846,11 +1804,22 @@ dependencies = [ "semver 0.11.0", ] +[[package]] +name = "located_yaml" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bc68ee6f87a1be7fdba1dcfd854528371aa84a8390279b5d7a99d5da82add76" +dependencies = [ + "linked-hash-map", + "serde", + "yaml-rust", +] + [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1858,12 +1827,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" @@ -1883,26 +1849,43 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" dependencies = [ - "bitflags", + "bitflags 1.3.2", "serde", "serde_json", "serde_repr", "url", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "matches" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "md-5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + [[package]] name = "md-5" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -1928,32 +1911,32 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1971,6 +1954,24 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "notify" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -1994,43 +1995,58 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.2", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ - "hermit-abi 0.2.6", "libc", ] [[package]] name = "object" -version = "0.30.3" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opaque-debug" @@ -2044,21 +2060,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -2077,7 +2078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -2096,15 +2097,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.1", ] [[package]] @@ -2113,17 +2114,40 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +[[package]] +name = "pcre2" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486aca7e74edb8cab09a48d461177f450a5cca3b55e61d139f7552190e2bbcf5" +dependencies = [ + "libc", + "log", + "pcre2-sys", + "thread_local", +] + +[[package]] +name = "pcre2-sys" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae234f441970dbd52d4e29bee70f3b56ca83040081cb2b55b7df772b16e0b06e" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "0d2d1d55045829d65aad9d389139882ad623b33b904e7c9f1b10c5b8927298e5" dependencies = [ "thiserror", "ucd-trie", @@ -2136,7 +2160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -2157,7 +2181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d43f3220d96e0080cc9ea234978ccd80d904eafb17be31bb0f76daaea6493082" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand", ] [[package]] @@ -2185,9 +2209,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -2196,32 +2220,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "plotters" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.4" +name = "pkg-config" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" - -[[package]] -name = "plotters-svg" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" -dependencies = [ - "plotters-backend", -] +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -2231,13 +2233,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor 0.1.26", "diff", - "output_vt100", "yansi", ] @@ -2259,13 +2259,22 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] +[[package]] +name = "proc_macro_crate" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "prost" version = "0.11.9" @@ -2422,9 +2431,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2454,33 +2463,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cd60adecd0947e1dd41a3077713381aa0cdcba6dc8777300d7d5b83b9fbe84" dependencies = [ "fst", - "indexmap", + "indexmap 1.9.3", "ra_ap_paths", "ra_ap_stdx", "rustc-hash", ] [[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -dependencies = [ - "libc", - "rand 0.4.6", -] - -[[package]] -name = "rand" -version = "0.4.6" +name = "ra_ap_vfs-notify" +version = "0.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +checksum = "a680f2dbd796844ebeaa2a4d01ae209f412ddc2981f6512ab8bc9b471156e6cd" dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", + "crossbeam-channel", + "jod-thread", + "notify", + "ra_ap_paths", + "ra_ap_vfs", + "tracing", + "walkdir", ] [[package]] @@ -2491,7 +2492,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2501,24 +2502,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.6.4" @@ -2534,38 +2520,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", + "rand_core", ] [[package]] @@ -2574,7 +2529,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2583,7 +2538,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2599,12 +2554,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", + "regex-automata 0.3.3", "regex-syntax", ] @@ -2614,11 +2570,22 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "ron" @@ -2627,7 +2594,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" dependencies = [ "base64", - "bitflags", + "bitflags 1.3.2", "serde", ] @@ -2641,19 +2608,6 @@ dependencies = [ "str_indices", ] -[[package]] -name = "rust-crypto" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -dependencies = [ - "gcc", - "libc", - "rand 0.3.23", - "rustc-serialize", - "time 0.1.45", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2711,12 +2665,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - [[package]] name = "rustc_data_structures" version = "0.0.1" @@ -2724,10 +2672,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44a5f9188372885b2cafd1e0297755679e3fc451a6eccabba5ffd9b261d4c1e" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "cfg-if 0.1.10", "ena", - "indexmap", + "indexmap 1.9.3", "jobserver", "libc", "memmap2", @@ -2768,11 +2716,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee78969130992735ace193e2c463da2bddd275e90e648871198312a7aed7baf" dependencies = [ "cfg-if 0.1.10", - "md-5", + "md-5 0.10.5", "rustc_data_structures", "scoped-tls", "sha-1", - "sha2 0.10.6", + "sha2 0.10.7", "tracing", "unicode-width", ] @@ -2792,18 +2740,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.17", + "semver 1.0.18", ] [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ - "bitflags", + "bitflags 2.3.3", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys 0.48.0", @@ -2811,15 +2758,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "salsa" @@ -2828,7 +2775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403" dependencies = [ "crossbeam-utils", - "indexmap", + "indexmap 1.9.3", "lock_api", "log", "oorandom", @@ -2867,15 +2814,24 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "self_cell" -version = "0.10.2" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.2", +] + +[[package]] +name = "self_cell" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" [[package]] name = "semver" @@ -2897,9 +2853,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "semver-parser" @@ -2918,32 +2874,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.163" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -2959,34 +2905,31 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "e168eaaf71e8f9bd6037feb05190485708e019f4fd87d161b3c0a0d37daf85e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] -name = "serde_yaml" -version = "0.8.26" +name = "serde_test" +version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab" dependencies = [ - "indexmap", - "ryu", "serde", - "yaml-rust", ] [[package]] name = "serde_yaml" -version = "0.9.21" +version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ - "indexmap", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -3001,7 +2944,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3029,18 +2972,18 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.0", ] [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3052,12 +2995,6 @@ dependencies = [ "libc", ] -[[package]] -name = "similar" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" - [[package]] name = "siphasher" version = "0.3.10" @@ -3085,9 +3022,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -3188,6 +3125,15 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "suggestions" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5441c382482e49aaac2c3ea9cbcd24290531246e879ee94af5dfc4b144f11e80" +dependencies = [ + "strsim", +] + [[package]] name = "syn" version = "1.0.109" @@ -3201,9 +3147,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -3224,15 +3170,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -3254,39 +3200,34 @@ dependencies = [ "winapi", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", ] [[package]] @@ -3326,14 +3267,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" dependencies = [ "itoa", + "libc", + "num_threads", "serde", "time-core", - "time-macros 0.2.9", + "time-macros 0.2.10", ] [[package]] @@ -3354,9 +3297,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" dependencies = [ "time-core", ] @@ -3383,16 +3326,6 @@ dependencies = [ "displaydoc", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -3410,11 +3343,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -3435,7 +3369,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] @@ -3487,11 +3421,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3499,20 +3432,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -3534,9 +3467,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "typetag" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6898cc6f6a32698cc3e14d5632a14d2b23ed9f7b11e6b8e05ce685990acc22" +checksum = "aec6850cc671cd0cfb3ab285465e48a3b927d9de155051c35797446b32f9169f" dependencies = [ "erased-serde", "inventory", @@ -3547,20 +3480,20 @@ dependencies = [ [[package]] name = "typetag-impl" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c3e1c30cedd24fc597f7d37a721efdbdc2b1acae012c1ef1218f4c7c2c0f3e7" +checksum = "30c49a6815b4f8379c36f06618bc1b80ca77aaf8a3fd4d8549dca6fdb016000f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", ] [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unic-char-property" @@ -3683,9 +3616,9 @@ checksum = "623f59e6af2a98bdafeb93fa277ac8e1e40440973001ca15cf4ae1541cd16d56" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -3722,15 +3655,15 @@ checksum = "87d6678d7916394abad0d4b19df4d3802e1fd84abd7d701f39b75ee71b9e8cf1" [[package]] name = "unsafe-libyaml" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "url" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -3744,16 +3677,26 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom", + "serde", +] + [[package]] name = "vergen" -version = "8.1.3" +version = "8.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e03272e388fb78fc79481a493424f78d77be1d55f21bcd314b5a6716e195afe" +checksum = "bbc5ad0d9d26b2c49a5ab7da76c3e79d3ee37e7821799f8223fcb8f2f391a2e7" dependencies = [ "anyhow", "rustc_version 0.4.0", "rustversion", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -3786,9 +3729,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.85" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3796,24 +3739,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.85" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.85" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3821,32 +3764,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.85" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.85" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb" - -[[package]] -name = "web-sys" -version = "0.3.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721" -dependencies = [ - "js-sys", - "wasm-bindgen", -] +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "which" @@ -3896,7 +3829,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -3929,7 +3862,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -3949,9 +3891,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -3962,6 +3904,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3974,6 +3931,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -3986,6 +3949,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -3998,6 +3967,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -4010,6 +3985,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -4022,6 +4003,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -4034,6 +4021,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -4046,6 +4039,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/kclvm/Cargo.toml b/kclvm/Cargo.toml index d72ad8e66..a0869a753 100644 --- a/kclvm/Cargo.toml +++ b/kclvm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -26,6 +26,7 @@ indexmap = "1.0" fslock = "0.2.1" libloading = "0.7.3" chrono = "0.4.19" +maplit = "1.0.2" anyhow = { version = "1.0.70", features = ["backtrace"] } compiler_base_session = {path = "../compiler_base/session"} @@ -36,6 +37,7 @@ kclvm-runner = {path = "./runner"} kclvm-parser = {path = "./parser"} kclvm-compiler = {path = "./compiler"} kclvm-config = {path = "./config"} +kclvm-loader = {path = "./loader"} kclvm-runtime = {path = "./runtime"} kclvm-sema = {path = "./sema"} kclvm-tools = {path = "./tools"} @@ -49,29 +51,3 @@ rpath = true panic = "unwind" opt-level = "z" # Optimize for size. lto = true - -[workspace] -members = [ - "third-party/prost-wkt", - "third-party/prost-wkt/wkt-build", - "third-party/prost-wkt/wkt-types", - "api", - "cmd", - "ast", - "ast_pretty", - "compiler", - "config", - "error", - "lexer", - "macros", - "parser", - "runner", - "runtime", - "sema", - "span", - "tools", - "version", - "query", - "utils", - "tools/src/LSP" -] diff --git a/kclvm/README.md b/kclvm/README.md index 5f6594fd6..bfee41bd5 100644 --- a/kclvm/README.md +++ b/kclvm/README.md @@ -43,9 +43,8 @@ You can choose any IDE you like for development, but we recommend a combination ## Notes -1. If you encounter problems compiling KCLVM and using LLVM 12 on Apple M1, you can refer to the [documentation](./docs/m1-mac-setup.md) -2. If you wanna start over, you `MUST` clean up all cached building files, such as `LLVM build files`, `kclvm/target`, etc. -3. If your updating-cargo-index is extremely slow, setup `~/.cargo/config` file. +1. If you wanna start over, you `MUST` clean up all cached building files, such as `LLVM build files`, `kclvm/target`, etc. +2. If your updating-cargo-index is extremely slow, setup `~/.cargo/config` file. ```toml [source.crates-io] diff --git a/kclvm/api/Cargo.toml b/kclvm/api/Cargo.toml index 80cd16c3d..3285dc255 100644 --- a/kclvm/api/Cargo.toml +++ b/kclvm/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-api" -version = "0.5.0" +version = "0.8.1" edition = "2021" [dependencies] @@ -8,11 +8,11 @@ tokio = {version = "1.25.0", features = ["full"] } futures = "0.3.28" jsonrpc-stdio-server = "18.0.0" tempfile = "3.5.0" - +maplit = "1.0.2" prost = "0.11.8" prost-types = "0.11.8" serde_json = "1.0" -serde_yaml = "0.9.2" +serde_yaml = "0.9.32" anyhow = "1.0.70" serde = { version = "1", features = ["derive"] } indexmap = "1.0" @@ -26,12 +26,14 @@ kclvm-config = {path = "../config"} kclvm-driver = {path = "../driver"} kclvm-error = {path = "../error"} kclvm-parser = {path = "../parser"} +kclvm-loader = {path = "../loader"} kclvm-sema = {path = "../sema"} kclvm-ast = {path = "../ast"} kclvm-ast-pretty = {path = "../ast_pretty"} kclvm-runtime = {path = "../runtime"} kclvm-tools = {path = "../tools" } kclvm-query = {path = "../query"} +kcl-language-server = {path = "../tools/src/LSP"} [dev-dependencies] criterion = "0.4.0" diff --git a/kclvm/api/build.rs b/kclvm/api/build.rs index 3477bd43c..617c1b9ae 100644 --- a/kclvm/api/build.rs +++ b/kclvm/api/build.rs @@ -2,7 +2,7 @@ use std::{env, path::PathBuf}; use prost_wkt_build::{FileDescriptorSet, Message}; -/// According to the file KCLVM/internal/kclvm_py/spec/gpyrpc/gpyrpc.proto, automatically generate +/// According to the file kclvm/spec/gpyrpc/gpyrpc.proto, automatically generate /// the corresponding rust source file to the directory src/model fn main() { std::env::set_var( @@ -21,10 +21,7 @@ fn main() { .extern_path(".google.protobuf.Timestamp", "::prost_wkt_types::Timestamp") .extern_path(".google.protobuf.Value", "::prost_wkt_types::Value") .file_descriptor_set_path(&descriptor_file) - .compile_protos( - &["../../internal/spec/gpyrpc/gpyrpc.proto"], - &["../../internal/spec/gpyrpc/"], - ) + .compile_protos(&["../spec/gpyrpc/gpyrpc.proto"], &["../spec/gpyrpc/"]) .expect("Running prost build failed."); let descriptor_bytes = std::fs::read(descriptor_file).unwrap(); diff --git a/kclvm/api/src/capi_test.rs b/kclvm/api/src/capi_test.rs index cccc1b51a..f8f7bdff5 100644 --- a/kclvm/api/src/capi_test.rs +++ b/kclvm/api/src/capi_test.rs @@ -6,8 +6,10 @@ use serde::de::DeserializeOwned; use std::default::Default; use std::ffi::{CStr, CString}; use std::fs; -use std::path::Path; +use std::os::raw::c_char; +use std::path::{Path, PathBuf}; use std::sync::Mutex; + const TEST_DATA_PATH: &str = "./src/testdata"; static TEST_MUTEX: Lazy> = Lazy::new(|| Mutex::new(0i32)); @@ -17,7 +19,7 @@ fn test_c_api_call_exec_program() { "KclvmService.ExecProgram", "exec-program.json", "exec-program.response.json", - |res| res.escaped_time = "0".to_owned(), + |_| {}, ); } @@ -27,7 +29,37 @@ fn test_c_api_call_exec_program_with_external_pkg() { "KclvmService.ExecProgram", "exec-program-with-external-pkg.json", "exec-program-with-external-pkg.response.json", - |res| res.escaped_time = "0".to_owned(), + |_| {}, + ); +} + +#[test] +fn test_c_api_call_exec_program_with_include_schema_type_path() { + test_c_api::( + "KclvmService.ExecProgram", + "exec-program-with-include-schema-type-path.json", + "exec-program-with-include-schema-type-path.response.json", + |_| {}, + ); +} + +#[test] +fn test_c_api_call_exec_program_with_path_selector() { + test_c_api::( + "KclvmService.ExecProgram", + "exec-program-with-path-selector.json", + "exec-program-with-path-selector.response.json", + |_| {}, + ); +} + +#[test] +fn test_c_api_call_exec_program_with_print() { + test_c_api::( + "KclvmService.ExecProgram", + "exec-program-with-print.json", + "exec-program-with-print.response.json", + |_| {}, ); } @@ -40,6 +72,34 @@ fn test_c_api_call_override_file() { ); } +#[test] +fn test_c_api_get_full_schema_type() { + test_c_api::( + "KclvmService.GetFullSchemaType", + "get-full-schema-type.json", + "get-full-schema-type.response.json", + |r| { + for s_ty in &mut r.schema_type_list { + s_ty.filename = s_ty.filename.replace('/', "").replace('\\', "") + } + }, + ); +} + +#[test] +fn test_c_api_get_all_full_schema_types() { + test_c_api::( + "KclvmService.GetFullSchemaType", + "get-all-full-schema-types.json", + "get-all-full-schema-types.response.json", + |r| { + for s_ty in &mut r.schema_type_list { + s_ty.filename = s_ty.filename.replace('/', "").replace('\\', "") + } + }, + ); +} + #[test] fn test_c_api_get_schema_type_mapping() { test_c_api_without_wrapper::( @@ -76,6 +136,15 @@ fn test_c_api_lint_path() { ); } +#[test] +fn test_c_api_call_exec_program_with_compile_only() { + test_c_api_paniced::( + "KclvmService.ExecProgram", + "exec-program-with-compile-only.json", + "exec-program-with-compile-only.response.panic", + ); +} + #[test] fn test_c_api_validate_code() { test_c_api_without_wrapper::( @@ -85,6 +154,15 @@ fn test_c_api_validate_code() { ); } +#[test] +fn test_c_api_validate_code_file() { + test_c_api_without_wrapper::( + "KclvmService.ValidateCode", + "validate-code-file.json", + "validate-code-file.response.json", + ); +} + #[test] fn test_c_api_load_settings_files() { test_c_api_without_wrapper::( @@ -94,6 +172,60 @@ fn test_c_api_load_settings_files() { ); } +#[test] +fn test_c_api_rename() { + // before test, load template from .bak + let path = Path::new(TEST_DATA_PATH).join("rename").join("main.k"); + let backup_path = path.with_extension("bak"); + let content = fs::read_to_string(backup_path.clone()).unwrap(); + fs::write(path.clone(), content).unwrap(); + + test_c_api::( + "KclvmService.Rename", + "rename.json", + "rename.response.json", + |r| { + r.changed_files = r + .changed_files + .iter() + .map(|f| { + PathBuf::from(f) + .canonicalize() + .unwrap() + .display() + .to_string() + }) + .collect(); + }, + ); + + // after test, restore template from .bak + fs::remove_file(path.clone()).unwrap(); +} + +#[test] +fn test_c_api_rename_code() { + test_c_api_without_wrapper::( + "KclvmService.RenameCode", + "rename-code.json", + "rename-code.response.json", + ); +} + +#[test] +fn test_c_api_testing() { + test_c_api::( + "KclvmService.Test", + "test.json", + "test.response.json", + |r| { + for i in &mut r.info { + i.duration = 0; + } + }, + ); +} + fn test_c_api_without_wrapper(svc_name: &str, input: &str, output: &str) where A: Message + DeserializeOwned, @@ -105,7 +237,7 @@ where fn test_c_api(svc_name: &str, input: &str, output: &str, wrapper: F) where A: Message + DeserializeOwned, - R: Message + Default + PartialEq + DeserializeOwned + serde::Serialize, + R: Message + Default + PartialEq + DeserializeOwned + serde::Serialize + ?Sized, F: Fn(&mut R), { let _test_lock = TEST_MUTEX.lock().unwrap(); @@ -118,10 +250,12 @@ where CString::from_vec_unchecked(serde_json::from_str::(&input).unwrap().encode_to_vec()) }; let call = CString::new(svc_name).unwrap(); - let result_ptr = kclvm_service_call(serv, call.as_ptr(), args.as_ptr()) as *mut i8; + let result_ptr = kclvm_service_call(serv, call.as_ptr(), args.as_ptr()); let result = unsafe { CStr::from_ptr(result_ptr) }; let mut result = R::decode(result.to_bytes()).unwrap(); + let result_json = serde_json::to_string(&result).unwrap(); + let except_result_path = Path::new(TEST_DATA_PATH).join(output); let except_result_json = fs::read_to_string(&except_result_path).unwrap_or_else(|_| { panic!( @@ -132,9 +266,52 @@ where let mut except_result = serde_json::from_str::(&except_result_json).unwrap(); wrapper(&mut result); wrapper(&mut except_result); - assert_eq!(result, except_result); + assert_eq!(result, except_result, "\nresult json is {result_json}"); unsafe { kclvm_service_delete(serv); - kclvm_service_free_string(result_ptr); + kclvm_service_free_string(result_ptr as *mut c_char); + } +} + +fn test_c_api_paniced(svc_name: &str, input: &str, output: &str) +where + A: Message + DeserializeOwned, +{ + let _test_lock = TEST_MUTEX.lock().unwrap(); + let serv = kclvm_service_new(0); + + let input_path = Path::new(TEST_DATA_PATH).join(input); + let input = fs::read_to_string(&input_path) + .unwrap_or_else(|_| panic!("Something went wrong reading {}", input_path.display())); + let args = unsafe { + CString::from_vec_unchecked(serde_json::from_str::(&input).unwrap().encode_to_vec()) + }; + let call = CString::new(svc_name).unwrap(); + let prev_hook = std::panic::take_hook(); + // disable print panic info + std::panic::set_hook(Box::new(|_info| {})); + let result = + std::panic::catch_unwind(|| kclvm_service_call(serv, call.as_ptr(), args.as_ptr())); + std::panic::set_hook(prev_hook); + match result { + Ok(result_ptr) => { + let result = unsafe { CStr::from_ptr(result_ptr) }; + let except_result_path = Path::new(TEST_DATA_PATH).join(output); + let except_result_panic_msg = + fs::read_to_string(&except_result_path).unwrap_or_else(|_| { + panic!( + "Something went wrong reading {}", + except_result_path.display() + ) + }); + assert!(result.to_string_lossy().contains(&except_result_panic_msg)); + unsafe { + kclvm_service_delete(serv); + kclvm_service_free_string(result_ptr as *mut c_char); + } + } + Err(_) => { + panic!("unreachable code") + } } } diff --git a/kclvm/api/src/service/capi.rs b/kclvm/api/src/service/capi.rs index 2942099b8..bc00812e2 100644 --- a/kclvm/api/src/service/capi.rs +++ b/kclvm/api/src/service/capi.rs @@ -2,7 +2,6 @@ use prost::Message; use crate::gpyrpc::*; use crate::service::service_impl::KclvmServiceImpl; -use kclvm_runtime::utils::*; use std::ffi::CString; use std::os::raw::c_char; @@ -21,7 +20,11 @@ pub extern "C" fn kclvm_service_new(plugin_agent: u64) -> *mut kclvm_service { /// Delete KclvmService #[no_mangle] pub unsafe extern "C" fn kclvm_service_delete(serv: *mut kclvm_service) { - free_mut_ptr(serv); + if !serv.is_null() { + unsafe { + drop(Box::from_raw(serv)); + } + } } /// # Safety @@ -31,13 +34,15 @@ pub unsafe extern "C" fn kclvm_service_delete(serv: *mut kclvm_service) { #[no_mangle] pub unsafe extern "C" fn kclvm_service_free_string(res: *mut c_char) { if !res.is_null() { - unsafe { CString::from_raw(res) }; + unsafe { + let _ = CString::from_raw(res); + }; } } macro_rules! call { ($serv:expr, $args:expr, $arg_name:ident, $serv_name:ident) => {{ - let serv_ref = unsafe { mut_ptr_as_ref($serv) }; + let serv_ref = unsafe { &mut *$serv }; let args = unsafe { std::ffi::CStr::from_ptr($args) }.to_bytes(); let args = $arg_name::decode(args).unwrap(); let res = serv_ref.$serv_name(&args); @@ -62,7 +67,7 @@ macro_rules! call { /// /// `args`: [*const c_char] /// Arguments of the call serialized as protobuf byte sequence, -/// refer to internal/spec/gpyrpc/gpyrpc.proto for the specific definitions of arguments +/// refer to kclvm/spec/gpyrpc/gpyrpc.proto for the specific definitions of arguments /// /// # Returns /// @@ -75,7 +80,7 @@ pub extern "C" fn kclvm_service_call( args: *const c_char, ) -> *const c_char { let result = std::panic::catch_unwind(|| { - let call = c2str(call); + let call = unsafe { std::ffi::CStr::from_ptr(call) }.to_str().unwrap(); let call = kclvm_get_service_fn_ptr_by_name(call); if call == 0 { panic!("null fn ptr"); @@ -85,7 +90,6 @@ pub extern "C" fn kclvm_service_call( unsafe { (*call)(serv, args) } }); match result { - //todo uniform error handling Ok(result) => result, Err(panic_err) => { let err_message = kclvm_error::err_to_str(panic_err); @@ -93,7 +97,7 @@ pub extern "C" fn kclvm_service_call( let c_string = std::ffi::CString::new(format!("ERROR:{}", err_message.as_str())) .expect("CString::new failed"); let ptr = c_string.into_raw(); - ptr as *const i8 + ptr as *const c_char } } } @@ -101,15 +105,24 @@ pub extern "C" fn kclvm_service_call( pub(crate) fn kclvm_get_service_fn_ptr_by_name(name: &str) -> u64 { match name { "KclvmService.Ping" => ping as *const () as u64, + "KclvmService.ParseFile" => parse_file as *const () as u64, + "KclvmService.ParseProgram" => parse_program as *const () as u64, + "KclvmService.LoadPackage" => load_package as *const () as u64, "KclvmService.ExecProgram" => exec_program as *const () as u64, + "KclvmService.BuildProgram" => build_program as *const () as u64, + "KclvmService.ExecArtifact" => exec_artifact as *const () as u64, "KclvmService.OverrideFile" => override_file as *const () as u64, "KclvmService.GetSchemaType" => get_schema_type as *const () as u64, + "KclvmService.GetFullSchemaType" => get_full_schema_type as *const () as u64, "KclvmService.GetSchemaTypeMapping" => get_schema_type_mapping as *const () as u64, "KclvmService.FormatCode" => format_code as *const () as u64, "KclvmService.FormatPath" => format_path as *const () as u64, "KclvmService.LintPath" => lint_path as *const () as u64, "KclvmService.ValidateCode" => validate_code as *const () as u64, "KclvmService.LoadSettingsFiles" => load_settings_files as *const () as u64, + "KclvmService.Rename" => rename as *const () as u64, + "KclvmService.RenameCode" => rename_code as *const () as u64, + "KclvmService.Test" => test as *const () as u64, _ => panic!("unknown method name : {name}"), } } @@ -120,6 +133,67 @@ pub(crate) fn ping(serv: *mut kclvm_service, args: *const c_char) -> *const c_ch call!(serv, args, PingArgs, ping) } +/// parse_file provides users with the ability to parse kcl single file +/// +/// # Parameters +/// +/// `serv`: [*mut kclvm_service] +/// The pointer of &\[[KclvmServiceImpl]] +/// +/// +/// `args`: [*const c_char] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// # Returns +/// +/// result: [*const c_char] +/// Result of the call serialized as protobuf byte sequence +pub(crate) fn parse_file(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, ParseFileArgs, parse_file) +} + +/// parse_program provides users with the ability to parse kcl program +/// +/// # Parameters +/// +/// `serv`: [*mut kclvm_service] +/// The pointer of &\[[KclvmServiceImpl]] +/// +/// +/// `args`: [*const c_char] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// # Returns +/// +/// result: [*const c_char] +/// Result of the call serialized as protobuf byte sequence +pub(crate) fn parse_program(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, ParseProgramArgs, parse_program) +} + +/// load_package provides users with the ability to parse kcl program and sematic model +/// information including symbols, types, definitions, etc, +/// +/// # Parameters +/// +/// `serv`: [*mut kclvm_service] +/// The pointer of &\[[KclvmServiceImpl]] +/// +/// +/// `args`: [*const c_char] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// # Returns +/// +/// result: [*const c_char] +/// Result of the call serialized as protobuf byte sequence +pub(crate) fn load_package(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, LoadPackageArgs, load_package) +} + /// exec_program provides users with the ability to execute KCL code /// /// # Parameters @@ -129,7 +203,7 @@ pub(crate) fn ping(serv: *mut kclvm_service, args: *const c_char) -> *const c_ch /// /// /// `args`: [*const c_char] -/// the items and compile parameters selected by the user in the KCLVM CLI +/// the items and compile parameters selected by the user in the KCL CLI /// serialized as protobuf byte sequence /// /// # Returns @@ -140,6 +214,46 @@ pub(crate) fn exec_program(serv: *mut kclvm_service, args: *const c_char) -> *co call!(serv, args, ExecProgramArgs, exec_program) } +/// build_program provides users with the ability to build the KCL program to an artifact. +/// +/// # Parameters +/// +/// `serv`: [*mut kclvm_service] +/// The pointer of &\[[KclvmServiceImpl]] +/// +/// +/// `args`: [*const c_char] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// # Returns +/// +/// result: [*const c_char] +/// Result of the call serialized as protobuf byte sequence +pub(crate) fn build_program(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, BuildProgramArgs, build_program) +} + +/// build_program provides users with the ability to execute the KCL artifact. +/// +/// # Parameters +/// +/// `serv`: [*mut kclvm_service] +/// The pointer of &\[[KclvmServiceImpl]] +/// +/// +/// `args`: [*const c_char] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// # Returns +/// +/// result: [*const c_char] +/// Result of the call serialized as protobuf byte sequence +pub(crate) fn exec_artifact(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, ExecArtifactArgs, exec_artifact) +} + /// override_file enable users override existing KCL file with specific KCl code /// /// # Parameters @@ -149,7 +263,7 @@ pub(crate) fn exec_program(serv: *mut kclvm_service, args: *const c_char) -> *co /// /// /// `args`: [*const c_char] -/// kcl file , override specs and import paths selected by the user in the KCLVM CLI +/// kcl file , override specs and import paths selected by the user in the KCL CLI /// serialized as protobuf byte sequence /// /// # Returns @@ -172,6 +286,18 @@ pub(crate) fn get_schema_type(serv: *mut kclvm_service, args: *const c_char) -> call!(serv, args, GetSchemaTypeArgs, get_schema_type) } +/// Get full schema types from a kcl file or code. +/// +/// # Parameters +/// `exec_args`: [Option] +/// the items and compile parameters selected by the user in the KCL CLI +/// serialized as protobuf byte sequence +/// +/// `schema_name`: [Option<&str>]. The schema name, when the schema name is empty, all schemas are returned. +pub(crate) fn get_full_schema_type(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, GetFullSchemaTypeArgs, get_full_schema_type) +} + /// Get schema types from a kcl file or code. /// /// # Parameters @@ -220,3 +346,20 @@ pub(crate) fn validate_code(serv: *mut kclvm_service, args: *const c_char) -> *c pub(crate) fn load_settings_files(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { call!(serv, args, LoadSettingsFilesArgs, load_settings_files) } + +/// Service for renaming all the occurrences of the target symbol in the files. This API will rewrite files if they contain symbols to be renamed. +/// return the file paths got changed. +pub(crate) fn rename(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, RenameArgs, rename) +} + +/// Service for renaming all the occurrences of the target symbol in the code. This API won't rewrite files but return the modified code if any code has been changed. +/// return the changed code. +pub(crate) fn rename_code(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, RenameCodeArgs, rename_code) +} + +/// Service for the testing tool. +pub(crate) fn test(serv: *mut kclvm_service, args: *const c_char) -> *const c_char { + call!(serv, args, TestArgs, test) +} diff --git a/kclvm/api/src/service/into.rs b/kclvm/api/src/service/into.rs index 789b1d12e..721243ff4 100644 --- a/kclvm/api/src/service/into.rs +++ b/kclvm/api/src/service/into.rs @@ -1,11 +1,38 @@ -use crate::gpyrpc::{CliConfig, KeyValuePair, LoadSettingsFilesResult}; +use crate::gpyrpc::{ + CliConfig, Error, KeyValuePair, LoadSettingsFilesResult, Message, Position, Scope, ScopeIndex, + Symbol, SymbolIndex, +}; +use crate::service::ty::kcl_ty_to_pb_ty; use kclvm_config::settings::SettingsFile; +use kclvm_error::Diagnostic; +use kclvm_loader::{ScopeInfo, SymbolInfo}; +use kclvm_sema::core::{scope::ScopeRef, symbol::SymbolRef}; pub(crate) trait IntoLoadSettingsFiles { /// Convert self into the LoadSettingsFiles structure. fn into_load_settings_files(self, files: &[String]) -> LoadSettingsFilesResult; } +pub(crate) trait IntoError { + fn into_error(self) -> Error; +} + +pub(crate) trait IntoSymbolIndex { + fn into_symbol_index(self) -> SymbolIndex; +} + +pub(crate) trait IntoSymbol { + fn into_symbol(self) -> Symbol; +} + +pub(crate) trait IntoScope { + fn into_scope(self) -> Scope; +} + +pub(crate) trait IntoScopeIndex { + fn into_scope_index(self) -> ScopeIndex; +} + impl IntoLoadSettingsFiles for SettingsFile { fn into_load_settings_files(self, files: &[String]) -> LoadSettingsFilesResult { LoadSettingsFilesResult { @@ -19,6 +46,8 @@ impl IntoLoadSettingsFiles for SettingsFile { verbose: config.verbose.unwrap_or_default() as i64, debug: config.debug.unwrap_or_default(), sort_keys: config.sort_keys.unwrap_or_default(), + show_hidden: config.show_hidden.unwrap_or_default(), + include_schema_type_path: config.include_schema_type_path.unwrap_or_default(), }), kcl_options: match self.kcl_options { Some(opts) => opts @@ -33,3 +62,76 @@ impl IntoLoadSettingsFiles for SettingsFile { } } } + +impl IntoError for Diagnostic { + fn into_error(self) -> Error { + Error { + level: self.level.to_string(), + code: format!( + "{:?}", + self.code.unwrap_or(kclvm_error::DiagnosticId::Error( + kclvm_error::ErrorKind::InvalidSyntax, + )) + ), + messages: self + .messages + .iter() + .map(|m| Message { + msg: m.message.clone(), + pos: Some(Position { + filename: m.range.0.filename.clone(), + line: m.range.0.line as i64, + column: m.range.0.column.unwrap_or_default() as i64, + }), + }) + .collect(), + } + } +} + +impl IntoSymbolIndex for SymbolRef { + fn into_symbol_index(self) -> SymbolIndex { + let (index, generation) = self.get_id().into_raw_parts(); + SymbolIndex { + i: index as u64, + g: generation, + kind: format!("{:?}", self.get_kind()), + } + } +} + +impl IntoScopeIndex for ScopeRef { + fn into_scope_index(self) -> ScopeIndex { + let (index, generation) = self.get_id().into_raw_parts(); + ScopeIndex { + i: index as u64, + g: generation, + kind: format!("{:?}", self.get_kind()), + } + } +} + +impl IntoSymbol for SymbolInfo { + fn into_symbol(self) -> Symbol { + Symbol { + ty: Some(kcl_ty_to_pb_ty(&self.ty)), + name: self.name, + owner: self.owner.map(|o| o.into_symbol_index()), + def: self.def.map(|d| d.into_symbol_index()), + attrs: self.attrs.iter().map(|a| a.into_symbol_index()).collect(), + is_global: self.is_global, + } + } +} + +impl IntoScope for ScopeInfo { + fn into_scope(self) -> Scope { + Scope { + kind: format!("{:?}", self.kind), + parent: self.parent.map(|o| o.into_scope_index()), + owner: self.owner.map(|o| o.into_symbol_index()), + children: self.children.iter().map(|a| a.into_scope_index()).collect(), + defs: self.defs.iter().map(|a| a.into_symbol_index()).collect(), + } + } +} diff --git a/kclvm/api/src/service/jsonrpc.rs b/kclvm/api/src/service/jsonrpc.rs index 8bff4756f..61dcba77d 100644 --- a/kclvm/api/src/service/jsonrpc.rs +++ b/kclvm/api/src/service/jsonrpc.rs @@ -67,6 +67,30 @@ fn register_kclvm_service(io: &mut IoHandler) { }; futures::future::ready(catch!(kclvm_service_impl, args, ping)) }); + io.add_method("KclvmService.ParseFile", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: ParseFileArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, parse_file)) + }); + io.add_method("KclvmService.ParseProgram", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: ParseProgramArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, parse_program)) + }); + io.add_method("KclvmService.LoadPackage", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: LoadPackageArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, load_package)) + }); io.add_method("KclvmService.ExecProgram", |params: Params| { let kclvm_service_impl = KclvmServiceImpl::default(); let args: ExecProgramArgs = match params.parse() { @@ -75,6 +99,22 @@ fn register_kclvm_service(io: &mut IoHandler) { }; futures::future::ready(catch!(kclvm_service_impl, args, exec_program)) }); + io.add_method("KclvmService.BuildProgram", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: BuildProgramArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, build_program)) + }); + io.add_method("KclvmService.ExecArtifact", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: ExecArtifactArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, exec_artifact)) + }); io.add_method("KclvmService.OverrideFile", |params: Params| { let kclvm_service_impl = KclvmServiceImpl::default(); let args: OverrideFileArgs = match params.parse() { @@ -91,6 +131,14 @@ fn register_kclvm_service(io: &mut IoHandler) { }; futures::future::ready(catch!(kclvm_service_impl, args, get_schema_type)) }); + io.add_method("KclvmService.GetFullSchemaType", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: GetFullSchemaTypeArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, get_full_schema_type)) + }); io.add_method("KclvmService.GetSchemaTypeMapping", |params: Params| { let kclvm_service_impl = KclvmServiceImpl::default(); let args: GetSchemaTypeMappingArgs = match params.parse() { @@ -139,6 +187,30 @@ fn register_kclvm_service(io: &mut IoHandler) { }; futures::future::ready(catch!(kclvm_service_impl, args, load_settings_files)) }); + io.add_method("KclvmService.Rename", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: RenameArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, rename)) + }); + io.add_method("KclvmService.RenameCode", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: RenameCodeArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, rename_code)) + }); + io.add_method("KclvmService.Test", |params: Params| { + let kclvm_service_impl = KclvmServiceImpl::default(); + let args: TestArgs = match params.parse() { + Ok(val) => val, + Err(err) => return futures::future::ready(Err(err)), + }; + futures::future::ready(catch!(kclvm_service_impl, args, test)) + }); } fn register_builtin_service(io: &mut IoHandler) { @@ -151,14 +223,23 @@ fn register_builtin_service(io: &mut IoHandler) { let result = ListMethodResult { method_name_list: vec![ "KclvmService.Ping".to_owned(), + "KclvmService.ParseFile".to_owned(), + "KclvmService.ParseProgram".to_owned(), "KclvmService.ExecProgram".to_owned(), + "KclvmService.BuildProgram".to_owned(), + "KclvmService.ExecArtifact".to_owned(), "KclvmService.OverrideFile".to_owned(), + "KclvmService.GetSchemaType".to_owned(), + "KclvmService.GetFullSchemaType".to_owned(), "KclvmService.GetSchemaTypeMapping".to_owned(), "KclvmService.FormatCode".to_owned(), "KclvmService.FormatPath".to_owned(), "KclvmService.LintPath".to_owned(), "KclvmService.ValidateCode".to_owned(), "KclvmService.LoadSettingsFiles".to_owned(), + "KclvmService.Rename".to_owned(), + "KclvmService.RenameCode".to_owned(), + "KclvmService.Test".to_owned(), "BuiltinService.Ping".to_owned(), "BuiltinService.PingListMethod".to_owned(), ], diff --git a/kclvm/api/src/service/service_impl.rs b/kclvm/api/src/service/service_impl.rs index a9071bee6..484c5c299 100644 --- a/kclvm/api/src/service/service_impl.rs +++ b/kclvm/api/src/service/service_impl.rs @@ -1,27 +1,39 @@ use std::collections::HashMap; use std::io::Write; +use std::path::PathBuf; use std::string::String; -use std::sync::Arc; use crate::gpyrpc::*; use anyhow::anyhow; +use kcl_language_server::rename; use kclvm_config::settings::build_settings_pathbuf; use kclvm_driver::canonicalize_input_files; -use kclvm_parser::ParseSession; +use kclvm_loader::{load_packages, LoadPackageOptions}; +use kclvm_parser::load_program; +use kclvm_parser::parse_file; +use kclvm_parser::KCLModuleCache; +use kclvm_parser::LoadProgramOptions; +use kclvm_parser::ParseSessionRef; use kclvm_query::get_schema_type; use kclvm_query::override_file; -use kclvm_runner::exec_program; +use kclvm_query::query::get_full_schema_type; +use kclvm_query::query::CompilationOptions; +use kclvm_query::GetSchemaOption; +use kclvm_runner::{build_program, exec_artifact, exec_program}; +use kclvm_sema::resolver::Options; use kclvm_tools::format::{format, format_source, FormatOptions}; use kclvm_tools::lint::lint_files; +use kclvm_tools::testing; +use kclvm_tools::testing::TestRun; use kclvm_tools::vet::validator::validate; use kclvm_tools::vet::validator::LoaderKind; use kclvm_tools::vet::validator::ValidateOption; use tempfile::NamedTempFile; -use super::into::IntoLoadSettingsFiles; +use super::into::*; use super::ty::kcl_schema_ty_to_pb_ty; -use super::util::transform_str_para; +use super::util::{transform_exec_para, transform_str_para}; /// Specific implementation of calling service #[derive(Debug, Clone, Default)] @@ -52,6 +64,195 @@ impl KclvmServiceImpl { }) } + /// Parse KCL program with entry files. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// // File case + /// let serv = KclvmServiceImpl::default(); + /// let args = &ParseProgramArgs { + /// paths: vec![Path::new(".").join("src").join("testdata").join("test.k").canonicalize().unwrap().display().to_string()], + /// ..Default::default() + /// }; + /// let result = serv.parse_program(args).unwrap(); + /// assert_eq!(result.errors.len(), 0); + /// assert_eq!(result.paths.len(), 1); + /// ``` + pub fn parse_program(&self, args: &ParseProgramArgs) -> anyhow::Result { + let sess = ParseSessionRef::default(); + let mut package_maps = HashMap::new(); + for p in &args.external_pkgs { + package_maps.insert(p.pkg_name.to_string(), p.pkg_path.to_string()); + } + let paths: Vec<&str> = args.paths.iter().map(|p| p.as_str()).collect(); + let result = load_program( + sess, + &paths, + Some(LoadProgramOptions { + k_code_list: args.sources.clone(), + package_maps, + load_plugins: true, + ..Default::default() + }), + Some(KCLModuleCache::default()), + )?; + let ast_json = serde_json::to_string(&result.program)?; + + Ok(ParseProgramResult { + ast_json, + paths: result + .paths + .iter() + .map(|p| p.to_str().unwrap().to_string()) + .collect(), + errors: result.errors.into_iter().map(|e| e.into_error()).collect(), + }) + } + + /// Parse KCL single file to Module AST JSON string with import + /// dependencies and parse errors. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// // File case + /// let serv = KclvmServiceImpl::default(); + /// let args = &ParseFileArgs { + /// path: Path::new(".").join("src").join("testdata").join("parse").join("main.k").canonicalize().unwrap().display().to_string(), + /// ..Default::default() + /// }; + /// let result = serv.parse_file(args).unwrap(); + /// assert_eq!(result.errors.len(), 0); + /// assert_eq!(result.deps.len(), 2); + /// ``` + pub fn parse_file(&self, args: &ParseFileArgs) -> anyhow::Result { + let result = parse_file(&args.path, transform_str_para(&args.source))?; + let ast_json = serde_json::to_string(&result.module)?; + + Ok(ParseFileResult { + ast_json, + deps: result + .deps + .iter() + .map(|p| p.to_str().unwrap().to_string()) + .collect(), + errors: result.errors.into_iter().map(|e| e.into_error()).collect(), + }) + } + + /// load_package provides users with the ability to parse kcl program and sematic model + /// information including symbols, types, definitions, etc. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// + /// let serv = KclvmServiceImpl::default(); + /// let args = &LoadPackageArgs { + /// parse_args: Some(ParseProgramArgs { + /// paths: vec![Path::new(".").join("src").join("testdata").join("parse").join("main.k").canonicalize().unwrap().display().to_string()], + /// ..Default::default() + /// }), + /// resolve_ast: true, + /// ..Default::default() + /// }; + /// let result = serv.load_package(args).unwrap(); + /// assert_eq!(result.paths.len(), 3); + /// assert_eq!(result.parse_errors.len(), 0); + /// assert_eq!(result.type_errors.len(), 0); + /// assert_eq!(result.symbols.len(), 12); + /// assert_eq!(result.scopes.len(), 3); + /// assert_eq!(result.node_symbol_map.len(), 165); + /// assert_eq!(result.symbol_node_map.len(), 165); + /// assert_eq!(result.fully_qualified_name_map.len(), 173); + /// assert_eq!(result.pkg_scope_map.len(), 3); + /// ``` + pub fn load_package(&self, args: &LoadPackageArgs) -> anyhow::Result { + let mut package_maps = HashMap::new(); + let parse_args = args.parse_args.clone().unwrap_or_default(); + for p in &parse_args.external_pkgs { + package_maps.insert(p.pkg_name.to_string(), p.pkg_path.to_string()); + } + let packages = load_packages(&LoadPackageOptions { + paths: parse_args.paths, + load_opts: Some(LoadProgramOptions { + k_code_list: parse_args.sources.clone(), + package_maps, + load_plugins: true, + ..Default::default() + }), + resolve_ast: args.resolve_ast, + load_builtin: args.load_builtin, + })?; + if args.with_ast_index { + // Thread local options + kclvm_ast::ast::set_should_serialize_id(true); + } + let program_json = serde_json::to_string(&packages.program)?; + let mut node_symbol_map = HashMap::new(); + let mut symbol_node_map = HashMap::new(); + let mut fully_qualified_name_map = HashMap::new(); + let mut pkg_scope_map = HashMap::new(); + let mut symbols = HashMap::new(); + let mut scopes = HashMap::new(); + // Build sematic mappings + for (k, s) in packages.node_symbol_map { + node_symbol_map.insert(k.id.to_string(), s.into_symbol_index()); + } + for (s, k) in packages.symbol_node_map { + let symbol_index_string = serde_json::to_string(&s)?; + symbol_node_map.insert(symbol_index_string, k.id.to_string()); + } + for (s, k) in packages.fully_qualified_name_map { + fully_qualified_name_map.insert(s, k.into_symbol_index()); + } + for (k, s) in packages.pkg_scope_map { + pkg_scope_map.insert(k, s.into_scope_index()); + } + for (k, s) in packages.symbols { + let symbol_index_string = serde_json::to_string(&k)?; + symbols.insert(symbol_index_string, s.into_symbol()); + } + for (k, s) in packages.scopes { + let scope_index_string = serde_json::to_string(&k)?; + scopes.insert(scope_index_string, s.into_scope()); + } + Ok(LoadPackageResult { + program: program_json, + paths: packages + .paths + .iter() + .map(|p| p.to_str().unwrap().to_string()) + .collect(), + node_symbol_map, + symbol_node_map, + fully_qualified_name_map, + pkg_scope_map, + symbols, + scopes, + parse_errors: packages + .parse_errors + .into_iter() + .map(|e| e.into_error()) + .collect(), + type_errors: packages + .type_errors + .into_iter() + .map(|e| e.into_error()) + .collect(), + }) + } + /// Execute KCL file with args. **Note that it is not thread safe.** /// /// # Examples @@ -85,29 +286,97 @@ impl KclvmServiceImpl { /// ..Default::default() /// }; /// let error = serv.exec_program(args).unwrap_err(); - /// assert!(error.contains("Cannot find the kcl file"), "{error}"); + /// assert!(error.to_string().contains("Cannot find the kcl file"), "{error}"); /// /// let args = &ExecProgramArgs { /// k_filename_list: vec![], /// ..Default::default() /// }; /// let error = serv.exec_program(args).unwrap_err(); - /// assert!(error.contains("No input KCL files or paths"), "{error}"); + /// assert!(error.to_string().contains("No input KCL files or paths"), "{error}"); /// ``` - pub fn exec_program(&self, args: &ExecProgramArgs) -> Result { + pub fn exec_program(&self, args: &ExecProgramArgs) -> anyhow::Result { // transform args to json - let args_json = serde_json::to_string(args).unwrap(); + let exec_args = transform_exec_para(&Some(args.clone()), self.plugin_agent)?; + let sess = ParseSessionRef::default(); + let result = exec_program(sess, &exec_args)?; - let sess = Arc::new(ParseSession::default()); - let result = exec_program( - sess, - &kclvm_runner::ExecProgramArgs::from_str(args_json.as_str()), + Ok(ExecProgramResult { + json_result: result.json_result, + yaml_result: result.yaml_result, + log_message: result.log_message, + err_message: result.err_message, + }) + } + + /// Build the KCL program to an artifact. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// // File case + /// let serv = KclvmServiceImpl::default(); + /// let exec_args = ExecProgramArgs { + /// work_dir: Path::new(".").join("src").join("testdata").canonicalize().unwrap().display().to_string(), + /// k_filename_list: vec!["test.k".to_string()], + /// ..Default::default() + /// }; + /// let artifact = serv.build_program(&BuildProgramArgs { + /// exec_args: Some(exec_args), + /// output: "".to_string(), + /// }).unwrap(); + /// assert!(!artifact.path.is_empty()); + /// ``` + pub fn build_program(&self, args: &BuildProgramArgs) -> anyhow::Result { + let exec_args = transform_exec_para(&args.exec_args, self.plugin_agent)?; + let artifact = build_program( + ParseSessionRef::default(), + &exec_args, + transform_str_para(&args.output), )?; + Ok(BuildProgramResult { + path: artifact.get_path().to_string(), + }) + } + /// Execute the KCL artifact with args. **Note that it is not thread safe.** + /// + /// # Examples + /// + /// ```no_run + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// // File case + /// let serv = KclvmServiceImpl::default(); + /// let exec_args = ExecProgramArgs { + /// work_dir: Path::new(".").join("src").join("testdata").canonicalize().unwrap().display().to_string(), + /// k_filename_list: vec!["test.k".to_string()], + /// ..Default::default() + /// }; + /// let artifact = serv.build_program(&BuildProgramArgs { + /// exec_args: Some(exec_args.clone()), + /// output: "./lib".to_string(), + /// }).unwrap(); + /// assert!(!artifact.path.is_empty()); + /// let exec_result = serv.exec_artifact(&ExecArtifactArgs { + /// exec_args: Some(exec_args), + /// path: artifact.path, + /// }).unwrap(); + /// assert_eq!(exec_result.err_message, ""); + /// assert_eq!(exec_result.yaml_result, "alice:\n age: 18"); + /// ``` + pub fn exec_artifact(&self, args: &ExecArtifactArgs) -> anyhow::Result { + let exec_args = transform_exec_para(&args.exec_args, self.plugin_agent)?; + let result = exec_artifact(&args.path, &exec_args)?; Ok(ExecProgramResult { json_result: result.json_result, yaml_result: result.yaml_result, - escaped_time: result.escaped_time, + log_message: result.log_message, + err_message: result.err_message, }) } @@ -197,6 +466,63 @@ impl KclvmServiceImpl { }) } + /// Service for getting the full schema type list. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// use std::path::Path; + /// + /// let serv = KclvmServiceImpl::default(); + /// let work_dir_parent = Path::new(".").join("src").join("testdata").join("get_schema_ty"); + /// let args = ExecProgramArgs { + /// work_dir: work_dir_parent.join("aaa").canonicalize().unwrap().display().to_string(), + /// k_filename_list: vec![ + /// work_dir_parent.join("aaa").join("main.k").canonicalize().unwrap().display().to_string() + /// ], + /// external_pkgs: vec![ + /// CmdExternalPkgSpec{ + /// pkg_name:"bbb".to_string(), + /// pkg_path: work_dir_parent.join("bbb").canonicalize().unwrap().display().to_string() + /// } + /// ], + /// ..Default::default() + /// }; + /// + /// let result = serv.get_full_schema_type(&GetFullSchemaTypeArgs { + /// exec_args: Some(args), + /// schema_name: "a".to_string() + /// }).unwrap(); + /// assert_eq!(result.schema_type_list.len(), 1); + /// ``` + pub fn get_full_schema_type( + &self, + args: &GetFullSchemaTypeArgs, + ) -> anyhow::Result { + let mut type_list = Vec::new(); + let exec_args = transform_exec_para(&args.exec_args, self.plugin_agent)?; + for (_k, schema_ty) in get_full_schema_type( + Some(&args.schema_name), + CompilationOptions { + k_files: exec_args.clone().k_filename_list, + loader_opts: Some(exec_args.get_load_program_options()), + resolve_opts: Options { + resolve_val: true, + ..Default::default() + }, + get_schema_opts: GetSchemaOption::default(), + }, + )? { + type_list.push(kcl_schema_ty_to_pb_ty(&schema_ty)); + } + + Ok(GetSchemaTypeResult { + schema_type_list: type_list, + }) + } + /// Service for getting the schema mapping. /// /// # Examples @@ -278,7 +604,15 @@ impl KclvmServiceImpl { /// assert_eq!(result.formatted, source.as_bytes().to_vec()); /// ``` pub fn format_code(&self, args: &FormatCodeArgs) -> anyhow::Result { - let (formatted, _) = format_source(&args.source)?; + let (formatted, _) = format_source( + "", + &args.source, + &FormatOptions { + is_stdout: false, + recursively: false, + omit_errors: true, + }, + )?; Ok(FormatCodeResult { formatted: formatted.as_bytes().to_vec(), }) @@ -313,7 +647,7 @@ impl KclvmServiceImpl { &FormatOptions { recursively, is_stdout: false, - ..Default::default() + omit_errors: true, }, )?; Ok(FormatPathResult { changed_paths }) @@ -391,9 +725,14 @@ impl KclvmServiceImpl { /// ``` pub fn validate_code(&self, args: &ValidateCodeArgs) -> anyhow::Result { let mut file = NamedTempFile::new()?; - // Write some test data to the first handle. - file.write_all(args.data.as_bytes())?; - let file_path = file.path().to_string_lossy().to_string(); + let file_path = if args.datafile.is_empty() { + // Write some test data to the first handle. + file.write_all(args.data.as_bytes())?; + file.path().to_string_lossy().to_string() + } else { + args.datafile.clone() + }; + let (success, err_message) = match validate(ValidateOption::new( transform_str_para(&args.schema), args.attribute_name.clone(), @@ -403,11 +742,11 @@ impl KclvmServiceImpl { "json" => LoaderKind::JSON, _ => LoaderKind::JSON, }, - None, + transform_str_para(&args.file), transform_str_para(&args.code), )) { Ok(success) => (success, "".to_string()), - Err(err) => (false, err), + Err(err) => (false, err.to_string()), }; Ok(ValidateCodeResult { success, @@ -452,4 +791,132 @@ impl KclvmServiceImpl { .clone() .into_load_settings_files(&files)) } + + /// Service for renaming all the occurrences of the target symbol in the files. This API will rewrite files if they contain symbols to be renamed. + /// return the file paths got changed. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// # use std::path::PathBuf; + /// # use std::fs; + /// # + /// # let serv = KclvmServiceImpl::default(); + /// # // before test, load template from .bak + /// # let path = PathBuf::from(".").join("src").join("testdata").join("rename_doc").join("main.k"); + /// # let backup_path = path.with_extension("bak"); + /// # let content = fs::read_to_string(backup_path.clone()).unwrap(); + /// # fs::write(path.clone(), content).unwrap(); + /// + /// let result = serv.rename(&RenameArgs { + /// package_root: "./src/testdata/rename_doc".to_string(), + /// symbol_path: "a".to_string(), + /// file_paths: vec!["./src/testdata/rename_doc/main.k".to_string()], + /// new_name: "a2".to_string(), + /// }).unwrap(); + /// assert_eq!(result.changed_files.len(), 1); + /// + /// # // after test, restore template from .bak + /// # fs::remove_file(path.clone()).unwrap(); + /// ``` + pub fn rename(&self, args: &RenameArgs) -> anyhow::Result { + let pkg_root = PathBuf::from(args.package_root.clone()) + .canonicalize()? + .display() + .to_string(); + let symbol_path = args.symbol_path.clone(); + let mut file_paths = vec![]; + for path in args.file_paths.iter() { + file_paths.push(PathBuf::from(path).canonicalize()?.display().to_string()); + } + let new_name = args.new_name.clone(); + Ok(RenameResult { + changed_files: rename::rename_symbol_on_file( + &pkg_root, + &symbol_path, + &file_paths, + new_name, + )?, + }) + } + + /// Service for renaming all the occurrences of the target symbol and rename them. This API won't rewrite files but return the modified code if any code has been changed. + /// return the changed code. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// + /// let serv = KclvmServiceImpl::default(); + /// let result = serv.rename_code(&RenameCodeArgs { + /// package_root: "/mock/path".to_string(), + /// symbol_path: "a".to_string(), + /// source_codes: vec![("/mock/path/main.k".to_string(), "a = 1\nb = a".to_string())].into_iter().collect(), + /// new_name: "a2".to_string(), + /// }).unwrap(); + /// assert_eq!(result.changed_codes.len(), 1); + /// assert_eq!(result.changed_codes.get("/mock/path/main.k").unwrap(), "a2 = 1\nb = a2"); + /// ``` + pub fn rename_code(&self, args: &RenameCodeArgs) -> anyhow::Result { + Ok(RenameCodeResult { + changed_codes: rename::rename_symbol_on_code( + &args.package_root, + &args.symbol_path, + args.source_codes.clone(), + args.new_name.clone(), + )?, + }) + } + + /// Service for the testing tool. + /// + /// # Examples + /// + /// ``` + /// use kclvm_api::service::service_impl::KclvmServiceImpl; + /// use kclvm_api::gpyrpc::*; + /// + /// let serv = KclvmServiceImpl::default(); + /// let result = serv.test(&TestArgs { + /// pkg_list: vec!["./src/testdata/testing/module/...".to_string()], + /// ..TestArgs::default() + /// }).unwrap(); + /// assert_eq!(result.info.len(), 2); + /// // Passed case + /// assert!(result.info[0].error.is_empty()); + /// // Failed case + /// assert!(result.info[1].error.is_empty()); + /// ``` + pub fn test(&self, args: &TestArgs) -> anyhow::Result { + let mut result = TestResult::default(); + let exec_args = transform_exec_para(&args.exec_args, self.plugin_agent)?; + let opts = testing::TestOptions { + exec_args, + run_regexp: args.run_regexp.clone(), + fail_fast: args.fail_fast, + }; + for pkg in &args.pkg_list { + let suites = testing::load_test_suites(pkg, &opts)?; + for suite in &suites { + let suite_result = suite.run(&opts)?; + for (name, info) in &suite_result.info { + result.info.push(TestCaseInfo { + name: name.clone(), + error: info + .error + .as_ref() + .map(|e| e.to_string()) + .unwrap_or_default(), + duration: info.duration.as_micros() as u64, + log_message: info.log_message.clone(), + }) + } + } + } + Ok(result) + } } diff --git a/kclvm/api/src/service/ty.rs b/kclvm/api/src/service/ty.rs index 9c4d75cc0..51a8a7b29 100644 --- a/kclvm/api/src/service/ty.rs +++ b/kclvm/api/src/service/ty.rs @@ -1,7 +1,6 @@ -use crate::gpyrpc::{Decorator, KclType}; +use crate::gpyrpc::{Decorator, Example, KclType}; use indexmap::IndexSet; -use kclvm_runtime::SCHEMA_SETTINGS_ATTR_NAME; -use kclvm_sema::ty::{SchemaType, Type}; +use kclvm_sema::ty::{DictType, SchemaType, Type}; use std::collections::HashMap; /// Convert the kcl sematic type to the kcl protobuf type. @@ -12,7 +11,7 @@ pub(crate) fn kcl_ty_to_pb_ty(ty: &Type) -> KclType { item: Some(Box::new(kcl_ty_to_pb_ty(item_ty))), ..Default::default() }, - kclvm_sema::ty::TypeKind::Dict(key_ty, val_ty) => KclType { + kclvm_sema::ty::TypeKind::Dict(DictType { key_ty, val_ty, .. }) => KclType { r#type: "dict".to_string(), key: Some(Box::new(kcl_ty_to_pb_ty(key_ty))), item: Some(Box::new(kcl_ty_to_pb_ty(val_ty))), @@ -37,6 +36,7 @@ pub(crate) fn kcl_schema_ty_to_pb_ty(schema_ty: &SchemaType) -> KclType { r#type: "schema".to_string(), schema_name: schema_ty.name.clone(), schema_doc: schema_ty.doc.clone(), + examples: get_schema_ty_examples(schema_ty), properties: get_schema_ty_attributes(schema_ty, &mut 1), required: get_schema_ty_required_attributes(schema_ty), decorators: schema_ty @@ -44,13 +44,30 @@ pub(crate) fn kcl_schema_ty_to_pb_ty(schema_ty: &SchemaType) -> KclType { .iter() .map(|d| Decorator { name: d.name.clone(), - ..Default::default() + arguments: d.arguments.clone(), + keywords: d.keywords.clone(), }) .collect(), + filename: schema_ty.filename.clone(), + pkg_path: schema_ty.pkgpath.clone(), + description: schema_ty.doc.clone(), ..Default::default() } } +fn get_schema_ty_examples(schema_ty: &SchemaType) -> HashMap { + let mut examples = HashMap::new(); + for (key, example) in &schema_ty.examples { + let exa = Example { + summary: example.summary.clone(), + description: example.description.clone(), + value: example.value.clone(), + }; + examples.insert(key.clone(), exa); + } + examples +} + fn get_schema_ty_attributes(schema_ty: &SchemaType, line: &mut i32) -> HashMap { let mut base_type_mapping = if let Some(base) = &schema_ty.base { get_schema_ty_attributes(base, line) @@ -59,12 +76,21 @@ fn get_schema_ty_attributes(schema_ty: &SchemaType, line: &mut i32) -> HashMap Vec { Vec::new() }; let mut attr_set = IndexSet::new(); - for (key, _) in &schema_ty.attrs { - if key != SCHEMA_SETTINGS_ATTR_NAME { + for (key, attr) in &schema_ty.attrs { + if !attr.is_optional { attr_set.insert(key.to_string()); } } diff --git a/kclvm/api/src/service/util.rs b/kclvm/api/src/service/util.rs index 7b3c3c1fd..f74b5fa1f 100644 --- a/kclvm/api/src/service/util.rs +++ b/kclvm/api/src/service/util.rs @@ -1,3 +1,5 @@ +use crate::gpyrpc::ExecProgramArgs; + /// Transform the str with zero value into [`Option`] #[inline] pub(crate) fn transform_str_para(para: &str) -> Option { @@ -7,3 +9,19 @@ pub(crate) fn transform_str_para(para: &str) -> Option { Some(para.to_string()) } } + +#[inline] +pub(crate) fn transform_exec_para( + exec_args: &Option, + plugin_agent: u64, +) -> anyhow::Result { + let mut args = match exec_args { + Some(exec_args) => { + let args_json = serde_json::to_string(exec_args)?; + kclvm_runner::ExecProgramArgs::from_str(args_json.as_str()) + } + None => kclvm_runner::ExecProgramArgs::default(), + }; + args.plugin_agent = plugin_agent; + Ok(args) +} diff --git a/kclvm/api/src/testdata/compile_recursive/kcl1/main.k b/kclvm/api/src/testdata/compile_recursive/kcl1/main.k new file mode 100644 index 000000000..23d3c668c --- /dev/null +++ b/kclvm/api/src/testdata/compile_recursive/kcl1/main.k @@ -0,0 +1 @@ +k1 = 'Hello k1!' \ No newline at end of file diff --git a/kclvm/api/src/testdata/compile_recursive/kcl2/main.k b/kclvm/api/src/testdata/compile_recursive/kcl2/main.k new file mode 100644 index 000000000..0cc5f31c5 --- /dev/null +++ b/kclvm/api/src/testdata/compile_recursive/kcl2/main.k @@ -0,0 +1 @@ +k2 = 'Hello k2!' \ No newline at end of file diff --git a/kclvm/api/src/testdata/compile_recursive/main.k b/kclvm/api/src/testdata/compile_recursive/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/api/src/testdata/compile_recursive/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/api/src/testdata/exec-program-with-compile-only.json b/kclvm/api/src/testdata/exec-program-with-compile-only.json new file mode 100644 index 000000000..4e6096eee --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-compile-only.json @@ -0,0 +1,17 @@ +{ + "work_dir" : "./src/testdata", + "k_filename_list":[ + "test-lint-import.k" + ], + "compile_only": true, + "external_pkgs": [ + { + "pkg_name": "external", + "pkg_path": "./src/testdata_external/external" + }, + { + "pkg_name": "external_1", + "pkg_path": "./src/testdata_external/external_1" + } + ] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/exec-program-with-compile-only.response.panic b/kclvm/api/src/testdata/exec-program-with-compile-only.response.panic new file mode 100644 index 000000000..86405eaf4 --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-compile-only.response.panic @@ -0,0 +1 @@ +Module 'external' imported but unused \ No newline at end of file diff --git a/kclvm/api/src/testdata/exec-program-with-external-pkg.response.json b/kclvm/api/src/testdata/exec-program-with-external-pkg.response.json index 9c722a984..a4183d7d1 100644 --- a/kclvm/api/src/testdata/exec-program-with-external-pkg.response.json +++ b/kclvm/api/src/testdata/exec-program-with-external-pkg.response.json @@ -1,5 +1,5 @@ { - "json_result": "[{\"a\": \"Hello External World!\", \"a1\": \"Hello External_1 World!\"}]", + "json_result": "{\"a\": \"Hello External World!\", \"a1\": \"Hello External_1 World!\"}", "yaml_result": "a: Hello External World!\na1: Hello External_1 World!", "escaped_time": "0.002061128616333008" } diff --git a/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.json b/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.json new file mode 100644 index 000000000..6c42c2fc8 --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.json @@ -0,0 +1,8 @@ + +{ + "work_dir" : "./src/testdata", + "k_filename_list":[ + "test.k" + ], + "include_schema_type_path": true +} diff --git a/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.response.json b/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.response.json new file mode 100644 index 000000000..aece90375 --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-include-schema-type-path.response.json @@ -0,0 +1,4 @@ +{ + "json_result": "{\"alice\": {\"age\": 18, \"_type\": \"__main__.Person\"}}", + "yaml_result": "alice:\n age: 18\n _type: __main__.Person" +} diff --git a/kclvm/api/src/testdata/exec-program-with-path-selector.json b/kclvm/api/src/testdata/exec-program-with-path-selector.json new file mode 100644 index 000000000..3a3b473af --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-path-selector.json @@ -0,0 +1,9 @@ +{ + "work_dir" : "./src/testdata", + "k_filename_list": [ + "test.k" + ], + "path_selector": [ + "alice" + ] +} diff --git a/kclvm/api/src/testdata/exec-program-with-path-selector.response.json b/kclvm/api/src/testdata/exec-program-with-path-selector.response.json new file mode 100644 index 000000000..20f0c8003 --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-path-selector.response.json @@ -0,0 +1,4 @@ +{ + "json_result": "{\"age\": 18}", + "yaml_result": "age: 18" +} diff --git a/kclvm/api/src/testdata/exec-program-with-print.json b/kclvm/api/src/testdata/exec-program-with-print.json new file mode 100644 index 000000000..55459c183 --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-print.json @@ -0,0 +1,6 @@ +{ + "work_dir" : "./src/testdata", + "k_filename_list":[ + "hello_with_print.k" + ] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/exec-program-with-print.response.json b/kclvm/api/src/testdata/exec-program-with-print.response.json new file mode 100644 index 000000000..bf88fa06c --- /dev/null +++ b/kclvm/api/src/testdata/exec-program-with-print.response.json @@ -0,0 +1,6 @@ +{ + "json_result": "{\"a\": 1}", + "yaml_result": "a: 1", + "log_message": "Hello world\n", + "err_message": "" +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/exec-program.response.json b/kclvm/api/src/testdata/exec-program.response.json index a9f325961..b45c912fe 100644 --- a/kclvm/api/src/testdata/exec-program.response.json +++ b/kclvm/api/src/testdata/exec-program.response.json @@ -1,5 +1,5 @@ { - "json_result": "[{\"a\": 1}]", + "json_result": "{\"a\": 1}", "yaml_result": "a: 1", "escaped_time": "0.002061128616333008" } \ No newline at end of file diff --git a/kclvm/api/src/testdata/get-all-full-schema-types.json b/kclvm/api/src/testdata/get-all-full-schema-types.json new file mode 100644 index 000000000..6625ecbe0 --- /dev/null +++ b/kclvm/api/src/testdata/get-all-full-schema-types.json @@ -0,0 +1,19 @@ +{ + "exec_args": { + "work_dir" : "./src/testdata/get_schema_ty/aaa", + "k_filename_list":[ + "./src/testdata/get_schema_ty/aaa/main.k" + ], + "external_pkgs": [ + { + "pkg_name": "bbb", + "pkg_path": "./src/testdata/get_schema_ty/bbb" + }, + { + "pkg_name": "ccc", + "pkg_path": "./src/testdata/get_schema_ty/ccc" + } + ] + }, + "schema_name": "" +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/get-all-full-schema-types.response.json b/kclvm/api/src/testdata/get-all-full-schema-types.response.json new file mode 100644 index 000000000..65bb1836a --- /dev/null +++ b/kclvm/api/src/testdata/get-all-full-schema-types.response.json @@ -0,0 +1,78 @@ +{ + "schema_type_list": [ + { + "type": "schema", + "union_types": [], + "default": "", + "schema_name": "B", + "schema_doc": "", + "properties": { + "name": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "key": null, + "item": null, + "line": 1, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + } + }, + "required": [ + "name" + ], + "key": null, + "item": null, + "line": 0, + "decorators": [], + "filename": "./src/testdata/get_schema_ty/bbb/main.k", + "pkg_path": "bbb", + "description": "", + "examples": {} + }, + { + "type": "schema", + "union_types": [], + "default": "", + "schema_name": "C", + "schema_doc": "", + "properties": { + "name": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "key": null, + "item": null, + "line": 1, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + } + }, + "required": [ + "name" + ], + "key": null, + "item": null, + "line": 0, + "decorators": [], + "filename": "./src/testdata/get_schema_ty/ccc/main.k", + "pkg_path": "ccc", + "description": "", + "examples": {} + } + ] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/get-full-schema-type.json b/kclvm/api/src/testdata/get-full-schema-type.json new file mode 100644 index 000000000..176db0716 --- /dev/null +++ b/kclvm/api/src/testdata/get-full-schema-type.json @@ -0,0 +1,15 @@ +{ + "exec_args": { + "work_dir" : "./src/testdata/get_schema_ty/aaa", + "k_filename_list":[ + "./src/testdata/get_schema_ty/aaa/main.k" + ], + "external_pkgs": [ + { + "pkg_name": "bbb", + "pkg_path": "./src/testdata/get_schema_ty/bbb" + } + ] + }, + "schema_name": "a" +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/get-full-schema-type.response.json b/kclvm/api/src/testdata/get-full-schema-type.response.json new file mode 100644 index 000000000..1ae7ebc41 --- /dev/null +++ b/kclvm/api/src/testdata/get-full-schema-type.response.json @@ -0,0 +1,41 @@ +{ + "schema_type_list": [ + { + "type": "schema", + "union_types": [], + "default": "", + "schema_name": "B", + "schema_doc": "", + "properties": { + "name": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "key": null, + "item": null, + "line": 1, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + } + }, + "required": [ + "name" + ], + "key": null, + "item": null, + "line": 0, + "decorators": [], + "filename": "./src/testdata/get_schema_ty/bbb/main.k", + "pkg_path": "bbb", + "description": "", + "examples": {} + } + ] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/get-schema-type-mapping.json b/kclvm/api/src/testdata/get-schema-type-mapping.json index 292725a0b..b4ccfbeea 100644 --- a/kclvm/api/src/testdata/get-schema-type-mapping.json +++ b/kclvm/api/src/testdata/get-schema-type-mapping.json @@ -1,4 +1,4 @@ { "file": "schema.k", - "code": "schema Person:\n name: str\n age: int\n\nperson = Person {\n name = \"Alice\"\n age = 18\n}\n" + "code": "@info(name=\"ServerSchema\")\nschema Server:\n \"\"\"Server is the common user interface for long-running\n services adopting the best practice of Kubernetes.\n\n Attributes\n ----------\n workloadType: str, default is \"Deployment\", required\n Use this attribute to specify which kind of long-running service you want.\n Valid values: Deployment, CafeDeployment.\n See also: kusion_models/core/v1/workload_metadata.k.\n name: str, required\n A Server-level attribute.\n The name of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n labels: {str:str}, optional\n A Server-level attribute.\n The labels of the long-running service.\n See also: kusion_models/core/v1/metadata.k.\n\n Examples\n --------\n myCustomApp = AppConfiguration {\n name = \"componentName\"\n }\n \"\"\"\n workloadType: str = \"Deployment\"\n @info(\"name\", key=\"value\")\n name: str\n labels?: {str:str}\n useCustomizeLables: True | False\n containers: [Container]\n\nschema Container:\n \"\"\"Container is the common user interface for long-running services.\n\n Attributes\n ----------\n name: str, required\n The name of the long-running container.\n \"\"\"\n name: str\n" } diff --git a/kclvm/api/src/testdata/get-schema-type-mapping.response.json b/kclvm/api/src/testdata/get-schema-type-mapping.response.json index 98ce27d8c..5a9b8b6e9 100644 --- a/kclvm/api/src/testdata/get-schema-type-mapping.response.json +++ b/kclvm/api/src/testdata/get-schema-type-mapping.response.json @@ -1,22 +1,59 @@ { "schema_type_mapping": { - "person": { + "Server": { "type": "schema", "union_types": [], "default": "", - "schema_name": "Person", - "schema_doc": "", + "schema_name": "Server", + "schema_doc": "Server is the common user interface for long-running services adopting the best practice of Kubernetes.", "properties": { - "age": { - "type": "int", + "containers": { + "type": "list", "union_types": [], "default": "", "schema_name": "", "schema_doc": "", "properties": {}, "required": [], - "line": 2, - "decorators": [] + "item": { + "type": "schema", + "union_types": [], + "default": "", + "schema_name": "Container", + "schema_doc": "Container is the common user interface for long-running services.", + "properties": { + "name": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 1, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "The name of the long-running container.", + "examples": {} + } + }, + "required": [ + "name" + ], + "line": 0, + "decorators": [], + "filename": "schema.k", + "pkg_path": "__main__", + "description": "Container is the common user interface for long-running services.", + "examples": {} + }, + "line": 5, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} }, "name": { "type": "str", @@ -26,23 +63,163 @@ "schema_doc": "", "properties": {}, "required": [], + "line": 2, + "decorators": [ + { + "name": "info", + "arguments": [ + "\"name\"" + ], + "keywords": { + "key": "\"value\"" + } + } + ], + "filename": "", + "pkg_path": "", + "description": "A Server-level attribute.\nThe name of the long-running service.\nSee also: kusion_models/core/v1/metadata.k.", + "examples": {} + }, + "workloadType": { + "type": "str", + "union_types": [], + "default": "\"Deployment\"", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], "line": 1, - "decorators": [] + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "Use this attribute to specify which kind of long-running service you want.\nValid values: Deployment, CafeDeployment.\nSee also: kusion_models/core/v1/workload_metadata.k.", + "examples": {} + }, + "labels": { + "type": "dict", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "key": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 0, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + }, + "item": { + "type": "str", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 0, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + }, + "line": 3, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "A Server-level attribute.\nThe labels of the long-running service.\nSee also: kusion_models/core/v1/metadata.k.", + "examples": {} + }, + "useCustomizeLables": { + "type": "union", + "union_types": [ + { + "type": "bool(True)", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 0, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + }, + { + "type": "bool(False)", + "union_types": [], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 0, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} + } + ], + "default": "", + "schema_name": "", + "schema_doc": "", + "properties": {}, + "required": [], + "line": 4, + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "", + "examples": {} } }, "required": [ + "workloadType", "name", - "age" + "useCustomizeLables", + "containers" ], "line": 0, - "decorators": [] + "decorators": [ + { + "name": "info", + "arguments": [], + "keywords": { + "name": "\"ServerSchema\"" + } + } + ], + "filename": "schema.k", + "pkg_path": "__main__", + "description": "Server is the common user interface for long-running services adopting the best practice of Kubernetes.", + "examples": { + "Default example": { + "summary": "", + "description": "", + "value": "myCustomApp = AppConfiguration {\n name = \"componentName\"\n}" + } + } }, - "Person": { + "Container": { "type": "schema", "union_types": [], "default": "", - "schema_name": "Person", - "schema_doc": "", + "schema_name": "Container", + "schema_doc": "Container is the common user interface for long-running services.", "properties": { "name": { "type": "str", @@ -53,26 +230,22 @@ "properties": {}, "required": [], "line": 1, - "decorators": [] - }, - "age": { - "type": "int", - "union_types": [], - "default": "", - "schema_name": "", - "schema_doc": "", - "properties": {}, - "required": [], - "line": 2, - "decorators": [] + "decorators": [], + "filename": "", + "pkg_path": "", + "description": "The name of the long-running container.", + "examples": {} } }, "required": [ - "name", - "age" + "name" ], "line": 0, - "decorators": [] + "decorators": [], + "filename": "schema.k", + "pkg_path": "__main__", + "description": "Container is the common user interface for long-running services.", + "examples": {} } } } \ No newline at end of file diff --git a/kclvm/api/src/testdata/get_schema_ty/aaa/kcl.mod b/kclvm/api/src/testdata/get_schema_ty/aaa/kcl.mod new file mode 100644 index 000000000..1e29d9eb2 --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/aaa/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "aaa" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/api/src/testdata/get_schema_ty/aaa/main.k b/kclvm/api/src/testdata/get_schema_ty/aaa/main.k new file mode 100644 index 000000000..bba48edf6 --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/aaa/main.k @@ -0,0 +1,10 @@ +import bbb as b +import ccc as c + +a = b.B { + name: "b instance in a" +} + +a_c = c.C { + name: "c instance in a" +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/get_schema_ty/bbb/kcl.mod b/kclvm/api/src/testdata/get_schema_ty/bbb/kcl.mod new file mode 100644 index 000000000..e9ea10a52 --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/bbb/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "bbb" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/api/src/testdata/get_schema_ty/bbb/main.k b/kclvm/api/src/testdata/get_schema_ty/bbb/main.k new file mode 100644 index 000000000..21dad4f9e --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/bbb/main.k @@ -0,0 +1,2 @@ +schema B: + name: str \ No newline at end of file diff --git a/kclvm/api/src/testdata/get_schema_ty/ccc/kcl.mod b/kclvm/api/src/testdata/get_schema_ty/ccc/kcl.mod new file mode 100644 index 000000000..9a762a4fa --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/ccc/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "ccc" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/api/src/testdata/get_schema_ty/ccc/main.k b/kclvm/api/src/testdata/get_schema_ty/ccc/main.k new file mode 100644 index 000000000..463ff966a --- /dev/null +++ b/kclvm/api/src/testdata/get_schema_ty/ccc/main.k @@ -0,0 +1,2 @@ +schema C: + name: str \ No newline at end of file diff --git a/kclvm/api/src/testdata/hello_with_print.k b/kclvm/api/src/testdata/hello_with_print.k new file mode 100644 index 000000000..5c0f43e6d --- /dev/null +++ b/kclvm/api/src/testdata/hello_with_print.k @@ -0,0 +1,2 @@ +print("Hello world") +a = 1 diff --git a/kclvm/api/src/testdata/parse/kcl.mod b/kclvm/api/src/testdata/parse/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/api/src/testdata/parse/main.k b/kclvm/api/src/testdata/parse/main.k new file mode 100644 index 000000000..1f0792f7b --- /dev/null +++ b/kclvm/api/src/testdata/parse/main.k @@ -0,0 +1,5 @@ +import pkg1 +import pkg2 + +a1 = pkg1.a +a2 = pkg2.a diff --git a/kclvm/api/src/testdata/parse/pkg1/pkg.k b/kclvm/api/src/testdata/parse/pkg1/pkg.k new file mode 100644 index 000000000..1337a530c --- /dev/null +++ b/kclvm/api/src/testdata/parse/pkg1/pkg.k @@ -0,0 +1 @@ +a = 1 diff --git a/kclvm/api/src/testdata/parse/pkg2/pkg.k b/kclvm/api/src/testdata/parse/pkg2/pkg.k new file mode 100644 index 000000000..1337a530c --- /dev/null +++ b/kclvm/api/src/testdata/parse/pkg2/pkg.k @@ -0,0 +1 @@ +a = 1 diff --git a/kclvm/api/src/testdata/rename-code.json b/kclvm/api/src/testdata/rename-code.json new file mode 100644 index 000000000..effad17c9 --- /dev/null +++ b/kclvm/api/src/testdata/rename-code.json @@ -0,0 +1,6 @@ +{ + "package_root": "/mock/path", + "source_codes": {"/mock/path/main.k": "a = 1\nb = a"}, + "symbol_path": "a", + "new_name": "a2" +} diff --git a/kclvm/api/src/testdata/rename-code.response.json b/kclvm/api/src/testdata/rename-code.response.json new file mode 100644 index 000000000..d71f32d5c --- /dev/null +++ b/kclvm/api/src/testdata/rename-code.response.json @@ -0,0 +1,3 @@ +{ + "changed_codes": {"/mock/path/main.k": "a2 = 1\nb = a2"} +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/rename.json b/kclvm/api/src/testdata/rename.json new file mode 100644 index 000000000..38f0cbb86 --- /dev/null +++ b/kclvm/api/src/testdata/rename.json @@ -0,0 +1,6 @@ +{ + "package_root": "./src/testdata/rename/", + "file_paths": ["./src/testdata/rename/main.k"], + "symbol_path": "a", + "new_name": "a2" +} diff --git a/kclvm/api/src/testdata/rename.response.json b/kclvm/api/src/testdata/rename.response.json new file mode 100644 index 000000000..c171a4b0b --- /dev/null +++ b/kclvm/api/src/testdata/rename.response.json @@ -0,0 +1,3 @@ +{ + "changed_files": ["./src/testdata/rename/main.k"] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/rename/main.bak b/kclvm/api/src/testdata/rename/main.bak new file mode 100644 index 000000000..3a0fa5834 --- /dev/null +++ b/kclvm/api/src/testdata/rename/main.bak @@ -0,0 +1,2 @@ +a = 1 +b = a \ No newline at end of file diff --git a/kclvm/api/src/testdata/rename_doc/main.bak b/kclvm/api/src/testdata/rename_doc/main.bak new file mode 100644 index 000000000..3a0fa5834 --- /dev/null +++ b/kclvm/api/src/testdata/rename_doc/main.bak @@ -0,0 +1,2 @@ +a = 1 +b = a \ No newline at end of file diff --git a/kclvm/api/src/testdata/test-lint-import.k b/kclvm/api/src/testdata/test-lint-import.k new file mode 100644 index 000000000..c452e62cd --- /dev/null +++ b/kclvm/api/src/testdata/test-lint-import.k @@ -0,0 +1,4 @@ +import external as ext +import external_1 as ext_1 + +a1 = ext_1.a \ No newline at end of file diff --git a/kclvm/api/src/testdata/test-validate.json b/kclvm/api/src/testdata/test-validate.json new file mode 100644 index 000000000..cafe9fd3c --- /dev/null +++ b/kclvm/api/src/testdata/test-validate.json @@ -0,0 +1,10 @@ +{ + "foo": "ThehFoo", + "bar": 2, + "fooList": [ + "a", + "b" + ], + "color": "Red", + "id": 100 +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/test.json b/kclvm/api/src/testdata/test.json new file mode 100644 index 000000000..8ab1bd206 --- /dev/null +++ b/kclvm/api/src/testdata/test.json @@ -0,0 +1,3 @@ +{ + "pkg_list": ["./src/testdata/testing/module/..."] +} diff --git a/kclvm/api/src/testdata/test.response.json b/kclvm/api/src/testdata/test.response.json new file mode 100644 index 000000000..969db3e7f --- /dev/null +++ b/kclvm/api/src/testdata/test.response.json @@ -0,0 +1,14 @@ +{ + "info": [ + { + "name": "test_func_0", + "error": "", + "log_message": "" + }, + { + "name": "test_func_1", + "error": "", + "log_message": "" + } + ] +} \ No newline at end of file diff --git a/kclvm/api/src/testdata/testing/module/kcl.mod b/kclvm/api/src/testdata/testing/module/kcl.mod new file mode 100644 index 000000000..35d888aa7 --- /dev/null +++ b/kclvm/api/src/testdata/testing/module/kcl.mod @@ -0,0 +1,3 @@ +[package] +name = "test_data" + diff --git a/kclvm/api/src/testdata/testing/module/pkg/func.k b/kclvm/api/src/testdata/testing/module/pkg/func.k new file mode 100644 index 000000000..26df9cf5a --- /dev/null +++ b/kclvm/api/src/testdata/testing/module/pkg/func.k @@ -0,0 +1,3 @@ +func = lambda x { + x +} diff --git a/kclvm/api/src/testdata/testing/module/pkg/func_test.k b/kclvm/api/src/testdata/testing/module/pkg/func_test.k new file mode 100644 index 000000000..b02295046 --- /dev/null +++ b/kclvm/api/src/testdata/testing/module/pkg/func_test.k @@ -0,0 +1,7 @@ +test_func_0 = lambda { + assert func("a") == "a" +} + +test_func_1 = lambda { + assert func("b") == "b" +} diff --git a/kclvm/api/src/testdata/validate-code-file.json b/kclvm/api/src/testdata/validate-code-file.json new file mode 100644 index 000000000..5f94a5836 --- /dev/null +++ b/kclvm/api/src/testdata/validate-code-file.json @@ -0,0 +1,4 @@ +{ + "code": "import regex\n\nschema Sample:\n foo: str\n bar: int\n fooList: [str]\n color: \"Red\" | \"Yellow\" | \"Blue\"\n id?: int\n \n check:\n bar >= 0\n bar < 100\n len(fooList) > 0\n len(fooList) < 100\n regex.match(foo, \"^The.*Foo$\")\n bar in range(100)\n bar in [2, 4, 6, 8]\n bar % 2 == 0\n abs(id) > 10 if id is not None\n", + "datafile": "./src/testdata/test-validate.json" +} diff --git a/kclvm/api/src/testdata/validate-code-file.response.json b/kclvm/api/src/testdata/validate-code-file.response.json new file mode 100644 index 000000000..9fadf3dd6 --- /dev/null +++ b/kclvm/api/src/testdata/validate-code-file.response.json @@ -0,0 +1,4 @@ +{ + "success": true, + "err_message": "" +} \ No newline at end of file diff --git a/kclvm/ast/Cargo.toml b/kclvm/ast/Cargo.toml index d5d2342af..02cfdd63e 100644 --- a/kclvm/ast/Cargo.toml +++ b/kclvm/ast/Cargo.toml @@ -1,17 +1,19 @@ [package] name = "kclvm-ast" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -compiler_base_span = {path = "../../compiler_base/span", version = "0.0.2"} +uuid = { version = "1.4.1", features = ["v4"] } +compiler_base_span = { path = "../../compiler_base/span", version = "0.0.2" } serde = { version = "1", features = ["derive"] } serde_json = "1.0" -kclvm-span = {path = "../span"} -kclvm-error = {path = "../error"} +kclvm-span = { path = "../span" } +kclvm-error = { path = "../error" } +thread_local = "1.1.7" [dev-dependencies] -kclvm-parser = {path = "../parser"} +kclvm-parser = { path = "../parser" } diff --git a/kclvm/ast/src/ast.rs b/kclvm/ast/src/ast.rs index 67de11e41..d877efaf2 100644 --- a/kclvm/ast/src/ast.rs +++ b/kclvm/ast/src/ast.rs @@ -31,18 +31,23 @@ //! :note: When the definition of any AST node is modified or the AST node //! is added/deleted, it is necessary to modify the corresponding processing //! in the compiler and regenerate the walker code. -//! :copyright: Copyright 2020 The KCL Authors. All rights reserved. -//! -//! todo: remove type_str fields after python frontend removed. +//! :copyright: Copyright The KCL Authors. All rights reserved. -use serde::{Deserialize, Serialize}; +use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer}; use std::collections::HashMap; use compiler_base_span::{Loc, Span}; +use std::fmt::Debug; +use uuid; use super::token; use crate::{node_ref, pos::ContainsPos}; -use kclvm_error::Position; +use kclvm_error::{diagnostic::Range, Position}; +use std::cell::RefCell; + +thread_local! { + static SHOULD_SERIALIZE_ID: RefCell = RefCell::new(false); +} /// PosTuple denotes the tuple `(filename, line, column, end_line, end_column)`. pub type PosTuple = (String, u64, u64, u64, u64); @@ -56,33 +61,61 @@ impl From for Pos { } } -impl Into for Pos { - fn into(self) -> PosTuple { - (self.0, self.1, self.2, self.3, self.4) +impl From for PosTuple { + fn from(val: Pos) -> Self { + (val.0, val.1, val.2, val.3, val.4) } } -impl Into<(Position, Position)> for Pos { - fn into(self) -> (Position, Position) { +impl From for Range { + fn from(val: Pos) -> Self { ( Position { - filename: self.0.clone(), - line: self.1, - column: Some(self.2), + filename: val.0.clone(), + line: val.1, + column: Some(val.2), }, Position { - filename: self.0, - line: self.3, - column: Some(self.4), + filename: val.0, + line: val.3, + column: Some(val.4), }, ) } } +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub struct AstIndex(uuid::Uuid); + +impl Serialize for AstIndex { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl Default for AstIndex { + fn default() -> Self { + Self(uuid::Uuid::new_v4()) + } +} + +impl ToString for AstIndex { + fn to_string(&self) -> String { + self.0.to_string() + } +} + /// Node is the file, line and column number information /// that all AST nodes need to contain. -#[derive(Serialize, Deserialize, Debug, Clone)] +/// In fact, column and end_column are the counts of character, +/// For example, `\t` is counted as 1 character, so it is recorded as 1 here, but generally col is 4. +#[derive(Deserialize, Clone, PartialEq)] pub struct Node { + #[serde(serialize_with = "serialize_id", skip_deserializing, default)] + pub id: AstIndex, pub node: T, pub filename: String, pub line: u64, @@ -91,6 +124,46 @@ pub struct Node { pub end_column: u64, } +impl Serialize for Node { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let should_serialize_id = SHOULD_SERIALIZE_ID.with(|f| *f.borrow()); + let mut state = + serializer.serialize_struct("Node", if should_serialize_id { 7 } else { 6 })?; + if should_serialize_id { + state.serialize_field("id", &self.id)?; + } + state.serialize_field("node", &self.node)?; + state.serialize_field("filename", &self.filename)?; + state.serialize_field("line", &self.line)?; + state.serialize_field("column", &self.column)?; + state.serialize_field("end_line", &self.end_line)?; + state.serialize_field("end_column", &self.end_column)?; + state.end() + } +} + +pub fn set_should_serialize_id(value: bool) { + SHOULD_SERIALIZE_ID.with(|f| { + *f.borrow_mut() = value; + }); +} + +impl Debug for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Node") + .field("node", &self.node) + .field("filename", &self.filename) + .field("line", &self.line) + .field("column", &self.column) + .field("end_line", &self.end_line) + .field("end_column", &self.end_column) + .finish() + } +} + impl Node { pub fn new( node: T, @@ -101,6 +174,7 @@ impl Node { end_column: u64, ) -> Self { Self { + id: AstIndex::default(), node, filename, line, @@ -112,6 +186,7 @@ impl Node { pub fn dummy_node(node: T) -> Self { Self { + id: AstIndex::default(), node, filename: "".to_string(), line: 1, @@ -123,6 +198,7 @@ impl Node { pub fn node(node: T, (lo, hi): (Loc, Loc)) -> Self { Self { + id: AstIndex::default(), node, filename: format!("{}", lo.file.name.prefer_remapped()), line: lo.line as u64, @@ -132,8 +208,21 @@ impl Node { } } + pub fn node_with_pos_and_id(node: T, pos: PosTuple, id: AstIndex) -> Self { + Self { + id, + node, + filename: pos.0.clone(), + line: pos.1, + column: pos.2, + end_line: pos.3, + end_column: pos.4, + } + } + pub fn node_with_pos(node: T, pos: PosTuple) -> Self { Self { + id: AstIndex::default(), node, filename: pos.0.clone(), line: pos.1, @@ -163,7 +252,7 @@ impl Node { } /// Spanned is the span information that all AST nodes need to contain. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Spanned { pub node: T, #[serde(skip)] @@ -176,6 +265,7 @@ impl TryInto> for Node { fn try_into(self) -> Result, Self::Error> { match self.node { Expr::Identifier(ident) => Ok(Node { + id: self.id, node: ident, filename: self.filename, line: self.line, @@ -192,6 +282,7 @@ impl Node { /// Into a missing identifier. pub fn into_missing_identifier(&self) -> Node { Node { + id: self.id.clone(), node: Identifier { names: vec![], pkgpath: String::new(), @@ -212,6 +303,7 @@ impl TryInto> for Node { fn try_into(self) -> Result, Self::Error> { match self.node { Expr::Schema(schema_expr) => Ok(Node { + id: self.id, node: schema_expr, filename: self.filename, line: self.line, @@ -229,21 +321,21 @@ impl TryInto> for Node { pub type NodeRef = Box>; /// KCL command line argument spec, e.g. `kcl main.k -E pkg_name=pkg_path` -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CmdExternalPkgSpec { pub pkg_name: String, pub pkg_path: String, } /// KCL command line argument spec, e.g. `kcl main.k -D name=value` -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CmdArgSpec { pub name: String, pub value: String, } /// KCL command line override spec, e.g. `kcl main.k -O pkgpath:path.to.field=field_value` -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct OverrideSpec { pub pkgpath: String, pub field_path: String, @@ -251,18 +343,25 @@ pub struct OverrideSpec { pub action: OverrideAction, } -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum OverrideAction { Delete, #[serde(other)] CreateOrUpdate, } +/// KCL API symbol selector Spec, eg: `pkgpath:path.to.field` +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct SymbolSelectorSpec { + pub pkg_root: String, + pub pkgpath: String, + pub field_path: String, +} + /// Program is the AST collection of all files of the running KCL program. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] pub struct Program { pub root: String, - pub main: String, pub pkgs: HashMap>, } @@ -274,6 +373,13 @@ impl Program { None => vec![], } } + /// Get the first module in the main package. + pub fn get_main_package_first_module(&self) -> Option<&Module> { + match self.pkgs.get(crate::MAIN_PKG) { + Some(modules) => modules.first(), + None => None, + } + } /// Get stmt on position pub fn pos_to_stmt(&self, pos: &Position) -> Option> { for (_, v) in &self.pkgs { @@ -288,11 +394,11 @@ impl Program { } /// Module is an abstract syntax tree for a single KCL file. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] pub struct Module { pub filename: String, pub pkg: String, - pub doc: String, + pub doc: Option>, pub name: String, pub body: Vec>, pub comments: Vec>, @@ -307,7 +413,7 @@ impl Module { stmts.push(node_ref!(schema_stmt.clone(), stmt.pos())); } } - return stmts; + stmts } /// Get stmt on position @@ -326,7 +432,8 @@ impl Module { */ /// A statement -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type")] pub enum Stmt { TypeAlias(TypeAliasStmt), Expr(ExprStmt), @@ -345,7 +452,7 @@ pub enum Stmt { /// ```kcl /// type StrOrInt = str | int /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct TypeAliasStmt { pub type_name: NodeRef, pub type_value: NodeRef, @@ -358,7 +465,7 @@ pub struct TypeAliasStmt { /// 1 /// """A long string""" /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ExprStmt { pub exprs: Vec>, } @@ -367,7 +474,7 @@ pub struct ExprStmt { /// ```kcl /// data: ASchema {} /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct UnificationStmt { pub target: NodeRef, pub value: NodeRef, @@ -377,12 +484,10 @@ pub struct UnificationStmt { /// ```kcl /// a: int = 1 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct AssignStmt { pub targets: Vec>, pub value: NodeRef, - pub type_annotation: Option>, - pub ty: Option>, } @@ -390,7 +495,7 @@ pub struct AssignStmt { /// ```kcl /// a += 1 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct AugAssignStmt { pub target: NodeRef, pub value: NodeRef, @@ -401,7 +506,7 @@ pub struct AugAssignStmt { /// ```kcl /// assert True if condition, "Assert failed message" /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct AssertStmt { pub test: NodeRef, pub if_cond: Option>, @@ -418,7 +523,7 @@ pub struct AssertStmt { /// else: /// c = 3 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct IfStmt { pub body: Vec>, pub cond: NodeRef, @@ -429,13 +534,13 @@ pub struct IfStmt { /// ```kcl /// import pkg as pkg_alias /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ImportStmt { /// `path` is the import path, if 'import a.b.c' in kcl, `path` is a.b.c - pub path: String, + pub path: Node, pub rawpath: String, pub name: String, - pub asname: Option, + pub asname: Option>, /// `pkg_name` means the name of the package that the current import statement indexs to. /// /// 1. If the current import statement indexs to the kcl plugins, kcl builtin methods or the internal kcl packages, @@ -462,9 +567,9 @@ pub struct ImportStmt { /// protocol ProtocolExample: /// attr: int /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct SchemaStmt { - pub doc: String, + pub doc: Option>, pub name: NodeRef, pub parent_name: Option>, pub for_host_name: Option>, @@ -492,7 +597,7 @@ impl SchemaStmt { attr_list.push(( unification_stmt.target.line, unification_stmt.target.column, - unification_stmt.target.node.names[0].to_string(), + unification_stmt.target.node.names[0].node.to_string(), )); } Stmt::Assign(assign_stmt) => { @@ -501,7 +606,7 @@ impl SchemaStmt { attr_list.push(( target.line, target.column, - target.node.names[0].to_string(), + target.node.names[0].node.to_string(), )); } } @@ -511,7 +616,7 @@ impl SchemaStmt { attr_list.push(( aug_assign_stmt.target.line, aug_assign_stmt.target.column, - aug_assign_stmt.target.node.names[0].to_string(), + aug_assign_stmt.target.node.names[0].node.to_string(), )); } } @@ -551,14 +656,12 @@ impl SchemaStmt { /// schema SchemaIndexSignatureExample: /// [str]: int /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct SchemaIndexSignature { pub key_name: Option, - pub key_type: NodeRef, - pub value_type: NodeRef, pub value: Option>, pub any_other: bool, - + pub key_ty: NodeRef, pub value_ty: NodeRef, } @@ -568,12 +671,11 @@ pub struct SchemaIndexSignature { /// x: int /// y: str /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct SchemaAttr { pub doc: String, pub name: NodeRef, - pub type_str: NodeRef, - pub op: Option, + pub op: Option, pub value: Option>, pub is_optional: bool, pub decorators: Vec>, @@ -587,9 +689,9 @@ pub struct SchemaAttr { /// a > 1 /// b < 0 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct RuleStmt { - pub doc: String, + pub doc: Option>, pub name: NodeRef, pub parent_rules: Vec>, pub decorators: Vec>, @@ -599,7 +701,8 @@ pub struct RuleStmt { } /// A expression -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type")] pub enum Expr { Identifier(Identifier), Unary(UnaryExpr), @@ -633,6 +736,43 @@ pub enum Expr { Missing(MissingExpr), } +impl Expr { + pub fn get_expr_name(&self) -> String { + match self { + Expr::Identifier(_) => "IdentifierExpression", + Expr::Unary(_) => "UnaryExpression", + Expr::Binary(_) => "BinaryExpression", + Expr::If(_) => "IfExpression", + Expr::Selector(_) => "SelectorExpression", + Expr::Call(_) => "CallExpression", + Expr::Paren(_) => "ParenExpression", + Expr::Quant(_) => "QuantExpression", + Expr::List(_) => "ListExpression", + Expr::ListIfItem(_) => "ListIfItemExpression", + Expr::ListComp(_) => "ListCompExpression", + Expr::Starred(_) => "StarredExpression", + Expr::DictComp(_) => "DictCompExpression", + Expr::ConfigIfEntry(_) => "ConfigIfEntryExpression", + Expr::CompClause(_) => "CompClauseExpression", + Expr::Schema(_) => "SchemaExpression", + Expr::Config(_) => "ConfigExpression", + Expr::Check(_) => "CheckExpression", + Expr::Lambda(_) => "LambdaExpression", + Expr::Subscript(_) => "SubscriptExpression", + Expr::Keyword(_) => "KeywordExpression", + Expr::Arguments(_) => "ArgumentsExpression", + Expr::Compare(_) => "CompareExpression", + Expr::NumberLit(_) => "NumberLitExpression", + Expr::StringLit(_) => "StringLitExpression", + Expr::NameConstantLit(_) => "NameConstantLitExpression", + Expr::JoinedString(_) => "JoinedStringExpression", + Expr::FormattedValue(_) => "FormattedValueExpression", + Expr::Missing(_) => "MissingExpression", + } + .to_string() + } +} + /// Identifier, e.g. /// ```kcl /// a @@ -640,16 +780,23 @@ pub enum Expr { /// _c /// pkg.a /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Identifier { - pub names: Vec, + pub names: Vec>, pub pkgpath: String, pub ctx: ExprContext, } impl Identifier { pub fn get_name(&self) -> String { - self.names.join(".") + self.get_names().join(".") + } + + pub fn get_names(&self) -> Vec { + self.names + .iter() + .map(|node| node.node.clone()) + .collect::>() } } @@ -660,7 +807,7 @@ impl Identifier { /// ~3 /// not True /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct UnaryExpr { pub op: UnaryOp, pub operand: NodeRef, @@ -673,10 +820,10 @@ pub struct UnaryExpr { /// 5 / 2 /// a is None /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct BinaryExpr { pub left: NodeRef, - pub op: BinOrCmpOp, + pub op: BinOp, pub right: NodeRef, } @@ -684,7 +831,7 @@ pub struct BinaryExpr { /// ```kcl /// 1 if condition else 2 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct IfExpr { pub body: NodeRef, pub cond: NodeRef, @@ -696,7 +843,7 @@ pub struct IfExpr { /// x.y /// x?.y /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct SelectorExpr { pub value: NodeRef, pub attr: NodeRef, @@ -710,7 +857,7 @@ pub struct SelectorExpr { /// func2(1) /// func3(x=2) /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CallExpr { pub func: NodeRef, pub args: Vec>, @@ -721,19 +868,19 @@ pub struct CallExpr { /// ```kcl /// 1 + (2 - 3) /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ParenExpr { pub expr: NodeRef, } -/// QuantExpr, e.g. +/// QuantExpr, in { } e.g. /// ```kcl /// all x in collection {x > 0} /// any y in collection {y < 0} /// map x in collection {x + 1} /// filter x in collection {x > 1} /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct QuantExpr { pub target: NodeRef, pub variables: Vec>, @@ -743,7 +890,7 @@ pub struct QuantExpr { pub ctx: ExprContext, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum QuantOperation { All, Any, @@ -768,7 +915,7 @@ impl From for String { /// ```kcl /// [1, 2, 3] /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ListExpr { pub elts: Vec>, pub ctx: ExprContext, @@ -778,13 +925,14 @@ pub struct ListExpr { /// ```kcl /// [1, if condition: 2, 3] /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ListIfItemExpr { pub if_cond: NodeRef, pub exprs: Vec>, pub orelse: Option>, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum CompType { List, Dict, @@ -794,7 +942,7 @@ pub enum CompType { /// ```kcl /// [x ** 2 for x in [1, 2, 3]] /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ListComp { pub elt: NodeRef, pub generators: Vec>, @@ -804,7 +952,7 @@ pub struct ListComp { /// ```kcl /// [1, 2, *[3, 4]] /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct StarredExpr { pub value: NodeRef, pub ctx: ExprContext, @@ -814,7 +962,7 @@ pub struct StarredExpr { /// ```kcl /// {k: v + 1 for k, v in {k1 = 1, k2 = 2}} /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct DictComp { pub entry: ConfigEntry, pub generators: Vec>, @@ -828,7 +976,7 @@ pub struct DictComp { /// k2 = 2 /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ConfigIfEntryExpr { pub if_cond: NodeRef, pub items: Vec>, @@ -839,7 +987,7 @@ pub struct ConfigIfEntryExpr { /// ```kcl /// i, a in [1, 2, 3] if i > 1 and a > 1 /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CompClause { pub targets: Vec>, pub iter: NodeRef, @@ -853,7 +1001,7 @@ pub struct CompClause { /// attr2 = 2 /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct SchemaExpr { pub name: NodeRef, pub args: Vec>, @@ -868,12 +1016,12 @@ pub struct SchemaExpr { /// attr2 = 2 /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ConfigExpr { pub items: Vec>, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum ConfigEntryOperation { Union, Override, @@ -906,7 +1054,7 @@ impl ConfigEntryOperation { /// c += [0] /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ConfigEntry { pub key: Option>, pub value: NodeRef, @@ -918,7 +1066,7 @@ pub struct ConfigEntry { /// ```kcl /// len(attr) > 3 if attr, "Check failed message" /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct CheckExpr { pub test: NodeRef, pub if_cond: Option>, @@ -932,12 +1080,10 @@ pub struct CheckExpr { /// z + y /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct LambdaExpr { pub args: Option>, - pub return_type_str: Option, pub body: Vec>, - pub return_ty: Option>, } @@ -947,7 +1093,7 @@ pub struct LambdaExpr { /// b["k"] /// c?[1] /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Subscript { pub value: NodeRef, pub index: Option>, @@ -962,7 +1108,7 @@ pub struct Subscript { /// ```kcl /// arg=value /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Keyword { pub arg: NodeRef, pub value: Option>, @@ -974,13 +1120,10 @@ pub struct Keyword { /// x + y /// } /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Arguments { pub args: Vec>, pub defaults: Vec>>, - pub type_annotation_list: Vec>>, - - #[serde(default)] pub ty_list: Vec>>, } @@ -990,6 +1133,18 @@ impl Arguments { .as_ref() .map_or(Type::Any, |ty| ty.node.clone()) } + + pub fn get_arg_type_node(&self, i: usize) -> Option<&Node> { + if let Some(ty) = self.ty_list.get(i) { + if let Some(ty) = ty { + Some(ty.as_ref()) + } else { + None + } + } else { + None + } + } } /// Compare, e.g. @@ -998,7 +1153,7 @@ impl Arguments { /// b is not None /// c != d /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Compare { pub left: NodeRef, pub ops: Vec, @@ -1012,7 +1167,8 @@ pub struct Compare { /// "string literal" /// """long string literal""" /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type")] pub enum Literal { Number(NumberLit), String(StringLit), @@ -1020,7 +1176,7 @@ pub enum Literal { } #[allow(non_camel_case_types)] -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum NumberBinarySuffix { n, u, @@ -1075,7 +1231,8 @@ impl NumberBinarySuffix { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type", content = "value")] pub enum NumberLitValue { Int(i64), Float(f64), @@ -1087,7 +1244,7 @@ pub enum NumberLitValue { /// 1K /// 1Mi /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct NumberLit { pub binary_suffix: Option, pub value: NumberLitValue, @@ -1098,7 +1255,7 @@ pub struct NumberLit { /// "string literal" /// """long string literal""" /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct StringLit { pub is_long_string: bool, pub raw_value: String, @@ -1125,7 +1282,7 @@ impl TryFrom for StringLit { /// None /// Undefined /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum NameConstant { True, False, @@ -1166,13 +1323,13 @@ impl TryFrom for NameConstant { } } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct NameConstantLit { pub value: NameConstant, } /// JoinedString, e.g. abc in the string interpolation "${var1} abc ${var2}" -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct JoinedString { pub is_long_string: bool, pub values: Vec>, @@ -1180,7 +1337,7 @@ pub struct JoinedString { } /// FormattedValue, e.g. var1 and var2 in the string interpolation "${var1} abc ${var2}" -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct FormattedValue { pub is_long_string: bool, pub value: NodeRef, @@ -1188,14 +1345,14 @@ pub struct FormattedValue { } /// MissingExpr placeholder for error recovery. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct MissingExpr; /// Comment, e.g. /// ```kcl /// # This is a comment /// ``` -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Comment { pub text: String, } @@ -1205,7 +1362,7 @@ pub struct Comment { */ /// BinOp is the set of all binary operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum BinOp { /// The `+` operator (addition) Add, @@ -1282,7 +1439,7 @@ impl BinOp { } /// BinOp is the set of all argument operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum AugOp { // The `=` operator (assign) Assign, @@ -1355,7 +1512,7 @@ impl TryInto for AugOp { } /// UnaryOp is the set of all unary operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum UnaryOp { /// The `+` operator for positive UAdd, @@ -1379,7 +1536,7 @@ impl UnaryOp { } /// CmpOp is the set of all comparison operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum CmpOp { /// The `==` operator (equality) Eq, @@ -1440,30 +1597,25 @@ impl CmpOp { } /// BinOrCmpOp is the set of all binary and comparison operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type")] pub enum BinOrCmpOp { Bin(BinOp), Cmp(CmpOp), } -/// BinOrAugOp is the set of all binary and argument operators in KCL. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum BinOrAugOp { - Bin(BinOp), - Aug(AugOp), -} - /// ExprContext represents the location information of the AST node. /// The left side of the assignment symbol represents `Store`, /// and the right side represents `Load`. -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum ExprContext { Load, Store, } /// A expression -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type", content = "value")] pub enum Type { Any, Named(Identifier), @@ -1472,9 +1624,16 @@ pub enum Type { Dict(DictType), Union(UnionType), Literal(LiteralType), + Function(FunctionType), } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct FunctionType { + pub params_ty: Option>>, + pub ret_ty: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum BasicType { Bool, Int, @@ -1482,37 +1641,44 @@ pub enum BasicType { Str, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ListType { pub inner_type: Option>, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct DictType { pub key_type: Option>, pub value_type: Option>, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct UnionType { pub type_elements: Vec>, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[serde(tag = "type", content = "value")] pub enum LiteralType { Bool(bool), - Int(i64, Option), // value + suffix + Int(IntLiteralType), // value + suffix Float(f64), Str(String), } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct IntLiteralType { + pub value: i64, + pub suffix: Option, +} + impl ToString for Type { fn to_string(&self) -> String { fn to_str(typ: &Type, w: &mut String) { match typ { Type::Any => w.push_str("any"), Type::Named(x) => { - w.push_str(&x.names.join(".")); + w.push_str(&x.get_name()); } Type::Basic(x) => { w.push_str(match x { @@ -1547,7 +1713,7 @@ impl ToString for Type { } for (i, t) in x.type_elements.iter().enumerate() { if i > 0 { - w.push('|'); + w.push_str(" | ") } to_str(&t.node, w); } @@ -1561,7 +1727,7 @@ impl ToString for Type { w.push_str("False"); } } - LiteralType::Int(v, suffix) => { + LiteralType::Int(IntLiteralType { value: v, suffix }) => { if let Some(suffix) = suffix { w.push_str(&format!("{}{}", v, suffix.value())); } else { @@ -1579,6 +1745,22 @@ impl ToString for Type { w.push_str(&format!("\"{}\"", v.replace('"', "\\\""))); } }, + Type::Function(v) => { + w.push('('); + if let Some(params) = &v.params_ty { + for (i, param) in params.iter().enumerate() { + if i > 0 { + w.push_str(", "); + } + to_str(¶m.node, w); + } + } + w.push(')'); + if let Some(ret) = &v.ret_ty { + w.push_str(" -> "); + to_str(&ret.node, w); + } + } } } @@ -1588,6 +1770,17 @@ impl ToString for Type { } } +impl From for Type { + /// Build a named type from the string. + fn from(value: String) -> Self { + Type::Named(Identifier { + names: vec![Node::dummy_node(value)], + pkgpath: "".to_string(), + ctx: ExprContext::Load, + }) + } +} + impl From for AugOp { fn from(op_kind: token::BinOpToken) -> Self { match op_kind { diff --git a/kclvm/ast/src/lib.rs b/kclvm/ast/src/lib.rs index 8eeb09a1f..a6bed9d3c 100644 --- a/kclvm/ast/src/lib.rs +++ b/kclvm/ast/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod ast; pub mod config; diff --git a/kclvm/ast/src/path.rs b/kclvm/ast/src/path.rs index d41fcf8f8..f3c3043d2 100644 --- a/kclvm/ast/src/path.rs +++ b/kclvm/ast/src/path.rs @@ -10,7 +10,7 @@ use crate::ast; /// use kclvm_ast::path::get_key_path; /// /// let ident = Some(Box::new(ast::Node::dummy_node(ast::Expr::Identifier(ast::Identifier { -/// names: vec!["alice".to_string()], +/// names: vec![ast::Node::dummy_node("alice".to_string())], /// pkgpath: "".to_string(), /// ctx: ast::ExprContext::Load, /// })))); diff --git a/kclvm/ast/src/pos.rs b/kclvm/ast/src/pos.rs index c437faab7..f8d56fa2c 100644 --- a/kclvm/ast/src/pos.rs +++ b/kclvm/ast/src/pos.rs @@ -1,4 +1,4 @@ -use kclvm_error::Position; +use kclvm_error::{diagnostic::Range, Position}; use crate::ast; @@ -9,7 +9,7 @@ pub trait ContainsPos { pub trait GetPos { /// Get start and end position from node. - fn get_span_pos(&self) -> (Position, Position) { + fn get_span_pos(&self) -> Range { (self.get_pos(), self.get_end_pos()) } /// Get start pos from node. @@ -25,6 +25,12 @@ impl ContainsPos for ast::Node { } } +impl ContainsPos for Range { + fn contains_pos(&self, pos: &Position) -> bool { + self.0.filename == pos.filename && self.0.less_equal(pos) && pos.less_equal(&self.1) + } +} + impl GetPos for ast::Node { fn get_pos(&self) -> Position { Position { diff --git a/kclvm/ast/src/tests.rs b/kclvm/ast/src/tests.rs index 3a389728e..ebaa19797 100644 --- a/kclvm/ast/src/tests.rs +++ b/kclvm/ast/src/tests.rs @@ -5,7 +5,7 @@ use crate::{ast, ast::*}; /// Construct an AssignStmt node with assign_value as value fn build_assign_node(attr_name: &str, assign_value: NodeRef) -> NodeRef { let iden = node_ref!(Identifier { - names: vec![attr_name.to_string()], + names: vec![Node::dummy_node(attr_name.to_string())], pkgpath: String::new(), ctx: ExprContext::Store }); @@ -13,7 +13,6 @@ fn build_assign_node(attr_name: &str, assign_value: NodeRef) -> NodeRef ast::Node { ast::AssignStmt { targets: vec![Box::new(ast::Node::new( ast::Identifier { - names: vec![String::from("a")], + names: vec![Node::dummy_node(String::from("a"))], pkgpath: String::from(filename), ctx: ast::ExprContext::Load, }, @@ -50,7 +49,6 @@ fn get_dummy_assign_ast() -> ast::Node { end_line, end_column, )), - type_annotation: None, ty: None, }, String::from(filename), @@ -71,7 +69,7 @@ fn get_dummy_assign_binary_ast() -> ast::Node { ast::AssignStmt { targets: vec![Box::new(ast::Node::new( ast::Identifier { - names: vec![String::from("a")], + names: vec![Node::dummy_node(String::from("a"))], pkgpath: String::from(filename), ctx: ast::ExprContext::Load, }, @@ -83,10 +81,10 @@ fn get_dummy_assign_binary_ast() -> ast::Node { ))], value: Box::new(ast::Node::new( ast::Expr::Binary(ast::BinaryExpr { - op: ast::BinOrCmpOp::Bin(ast::BinOp::Add), + op: ast::BinOp::Add, left: Box::new(ast::Node::new( ast::Expr::Identifier(ast::Identifier { - names: vec![String::from("a")], + names: vec![Node::dummy_node(String::from("a"))], pkgpath: String::from(filename), ctx: ast::ExprContext::Load, }), @@ -98,7 +96,7 @@ fn get_dummy_assign_binary_ast() -> ast::Node { )), right: Box::new(ast::Node::new( ast::Expr::Identifier(ast::Identifier { - names: vec![String::from("a")], + names: vec![Node::dummy_node(String::from("a"))], pkgpath: String::from(filename), ctx: ast::ExprContext::Load, }), @@ -115,7 +113,6 @@ fn get_dummy_assign_binary_ast() -> ast::Node { end_line, end_column, )), - type_annotation: None, ty: None, }, String::from(filename), @@ -147,15 +144,15 @@ fn test_mut_walker() { pub struct VarMutSelfMutWalker; impl<'ctx> MutSelfMutWalker<'ctx> for VarMutSelfMutWalker { fn walk_identifier(&mut self, identifier: &'ctx mut ast::Identifier) { - if identifier.names[0] == "a" { + if identifier.names[0].node == "a" { let id_mut = identifier.names.get_mut(0).unwrap(); - *id_mut = "x".to_string(); + id_mut.node = "x".to_string(); } } } let mut assign_stmt = get_dummy_assign_ast(); VarMutSelfMutWalker {}.walk_assign_stmt(&mut assign_stmt.node); - assert_eq!(assign_stmt.node.targets[0].node.names[0], "x") + assert_eq!(assign_stmt.node.targets[0].node.names[0].node, "x") } #[test] @@ -184,7 +181,7 @@ fn test_filter_schema_with_no_schema() { let ast_mod = Module { filename: "".to_string(), pkg: "".to_string(), - doc: "".to_string(), + doc: Some(node_ref!("".to_string())), name: "".to_string(), body: vec![], comments: vec![], @@ -198,7 +195,7 @@ fn test_filter_schema_with_one_schema() { let mut ast_mod = Module { filename: "".to_string(), pkg: "".to_string(), - doc: "".to_string(), + doc: Some(node_ref!("".to_string())), name: "".to_string(), body: vec![], comments: vec![], @@ -215,7 +212,7 @@ fn test_filter_schema_with_mult_schema() { let mut ast_mod = Module { filename: "".to_string(), pkg: "".to_string(), - doc: "".to_string(), + doc: Some(node_ref!("".to_string())), name: "".to_string(), body: vec![], comments: vec![], @@ -235,7 +232,10 @@ fn test_filter_schema_with_mult_schema() { #[test] fn test_build_assign_stmt() { let test_expr = node_ref!(ast::Expr::Identifier(Identifier { - names: vec!["name1".to_string(), "name2".to_string()], + names: vec![ + Node::dummy_node("name1".to_string()), + Node::dummy_node("name2".to_string()) + ], pkgpath: "test".to_string(), ctx: ast::ExprContext::Load })); @@ -244,8 +244,8 @@ fn test_build_assign_stmt() { if let ast::Stmt::Assign(ref assign) = assgin_stmt.node { if let ast::Expr::Identifier(ref iden) = &assign.value.node { assert_eq!(iden.names.len(), 2); - assert_eq!(iden.names[0], "name1".to_string()); - assert_eq!(iden.names[1], "name2".to_string()); + assert_eq!(iden.names[0].node, "name1".to_string()); + assert_eq!(iden.names[1].node, "name2".to_string()); assert_eq!(iden.pkgpath, "test".to_string()); match iden.ctx { ast::ExprContext::Load => {} @@ -265,7 +265,7 @@ fn gen_schema_stmt(count: i32) -> Vec> { let mut schema_stmts = Vec::new(); for c in 0..count { schema_stmts.push(node_ref!(ast::Stmt::Schema(SchemaStmt { - doc: "".to_string(), + doc: Some(node_ref!("".to_string())), name: node_ref!("schema_stmt_".to_string() + &c.to_string()), parent_name: None, for_host_name: None, diff --git a/kclvm/ast/src/token.rs b/kclvm/ast/src/token.rs index 9f3d7ee83..59b5ea7a1 100644 --- a/kclvm/ast/src/token.rs +++ b/kclvm/ast/src/token.rs @@ -4,7 +4,6 @@ //! Including indent and dedent tokens. //! Not Include some tokens of low level tokens, such as ';', '..', '..=', '<-'. pub use BinCmpToken::*; -pub use BinCmpToken::*; pub use BinOpToken::*; pub use DelimToken::*; pub use LitKind::*; @@ -12,7 +11,8 @@ pub use TokenKind::*; pub use UnaryOpToken::*; use compiler_base_span::{Span, DUMMY_SP}; -use kclvm_span::symbol::{Ident, Symbol}; +pub use kclvm_span::symbol::{Ident, Symbol}; +pub const VALID_SPACES_LENGTH: usize = 0; #[derive(Clone, Copy, PartialEq, Debug)] pub enum CommentKind { @@ -180,10 +180,10 @@ pub enum TokenKind { DocComment(CommentKind), /// '\t' or ' ' - Indent, + Indent(usize), /// Remove an indent - Dedent, + Dedent(usize), /// '\n' Newline, @@ -280,8 +280,8 @@ impl From for String { DocComment(kind) => match kind { CommentKind::Line(_) => "inline_comment", }, - Indent => "indent", - Dedent => "dedent", + Indent(_) => "indent", + Dedent(_) => "dedent", Newline => "newline", Dummy => "dummy", Eof => "eof", @@ -334,12 +334,35 @@ impl Token { self.run_on_ident(|id| id.name == kw) } + /// Whether the token is a string literal token. + pub fn is_string_lit(&self) -> bool { + match self.kind { + TokenKind::Literal(lit) => { + if let LitKind::Str { .. } = lit.kind { + true + } else { + false + } + } + _ => false, + } + } + fn run_on_ident(&self, pred: impl FnOnce(Ident) -> bool) -> bool { match self.ident() { Some(id) => pred(id), _ => false, } } + + /// Whether the token kind is in the recovery token set, when meets errors, drop it. + #[inline] + pub fn is_in_recovery_set(&self) -> bool { + matches!( + self.kind, + TokenKind::Indent(VALID_SPACES_LENGTH) | TokenKind::Dummy + ) + } } impl PartialEq for Token { diff --git a/kclvm/ast/src/walker.rs b/kclvm/ast/src/walker.rs index f82f17187..49932e4b8 100644 --- a/kclvm/ast/src/walker.rs +++ b/kclvm/ast/src/walker.rs @@ -266,6 +266,7 @@ pub trait MutSelfMutWalker<'ctx> { } fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx mut ast::TypeAliasStmt) { self.walk_identifier(&mut type_alias_stmt.type_name.node); + self.walk_type(&mut type_alias_stmt.ty.node); } fn walk_unification_stmt(&mut self, unification_stmt: &'ctx mut ast::UnificationStmt) { self.walk_identifier(&mut unification_stmt.target.node); @@ -276,6 +277,7 @@ pub trait MutSelfMutWalker<'ctx> { self.walk_identifier(&mut target.node) } self.walk_expr(&mut assign_stmt.value.node); + walk_if_mut!(self, walk_type, assign_stmt.ty); } fn walk_aug_assign_stmt(&mut self, aug_assign_stmt: &'ctx mut ast::AugAssignStmt) { self.walk_identifier(&mut aug_assign_stmt.target.node); @@ -297,6 +299,33 @@ pub trait MutSelfMutWalker<'ctx> { fn walk_schema_attr(&mut self, schema_attr: &'ctx mut ast::SchemaAttr) { walk_list_mut!(self, walk_call_expr, schema_attr.decorators); walk_if_mut!(self, walk_expr, schema_attr.value); + self.walk_type(&mut schema_attr.ty.node); + } + + fn walk_type(&mut self, ty: &'ctx mut ast::Type) { + match ty { + ast::Type::Named(id) => self.walk_identifier(id), + ast::Type::List(list_ty) => { + if let Some(ty) = &mut list_ty.inner_type { + self.walk_type(&mut ty.node) + } + } + ast::Type::Dict(dict_ty) => { + if let Some(ty) = &mut dict_ty.key_type { + self.walk_type(&mut ty.node) + } + if let Some(ty) = &mut dict_ty.value_type { + self.walk_type(&mut ty.node) + } + } + ast::Type::Union(union_ty) => { + union_ty + .type_elements + .iter_mut() + .for_each(|ty| self.walk_type(&mut ty.node)); + } + _ => {} + } } fn walk_schema_stmt(&mut self, schema_stmt: &'ctx mut ast::SchemaStmt) { walk_if_mut!(self, walk_identifier, schema_stmt.parent_name); @@ -413,6 +442,7 @@ pub trait MutSelfMutWalker<'ctx> { fn walk_lambda_expr(&mut self, lambda_expr: &'ctx mut ast::LambdaExpr) { walk_if_mut!(self, walk_arguments, lambda_expr.args); walk_list_mut!(self, walk_stmt, lambda_expr.body); + walk_if_mut!(self, walk_type, lambda_expr.return_ty); } fn walk_keyword(&mut self, keyword: &'ctx mut ast::Keyword) { self.walk_identifier(&mut keyword.arg.node); @@ -427,6 +457,11 @@ pub trait MutSelfMutWalker<'ctx> { self.walk_expr(&mut d.node) } } + for ty in arguments.ty_list.iter_mut() { + if let Some(ty) = ty.as_deref_mut() { + self.walk_type(&mut ty.node); + } + } } fn walk_compare(&mut self, compare: &'ctx mut ast::Compare) { self.walk_expr(&mut compare.left.node); diff --git a/kclvm/ast_pretty/Cargo.toml b/kclvm/ast_pretty/Cargo.toml index d5e591122..7f0c7cd63 100644 --- a/kclvm/ast_pretty/Cargo.toml +++ b/kclvm/ast_pretty/Cargo.toml @@ -1,12 +1,11 @@ [package] name = "kclvm-ast-pretty" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -kclvm-parser = {path = "../parser"} kclvm-error = {path = "../error"} kclvm-ast = {path = "../ast"} @@ -15,3 +14,6 @@ fancy-regex = "0.7.1" pretty_assertions = "1.3.0" compiler_base_session = {path = "../../compiler_base/session"} compiler_base_macros = "0.0.1" + +[dev-dependencies] +kclvm-parser = {path = "../parser"} diff --git a/kclvm/ast_pretty/src/lib.rs b/kclvm/ast_pretty/src/lib.rs index 67a000e2f..ab5973b04 100644 --- a/kclvm/ast_pretty/src/lib.rs +++ b/kclvm/ast_pretty/src/lib.rs @@ -261,7 +261,7 @@ impl<'p> Printer<'p> { } } -/// Print AST to string +/// Print AST to string. The default format is according to the KCL code style defined here: https://kcl-lang.io/docs/reference/lang/spec/codestyle pub fn print_ast_module(module: &Module) -> String { let mut printer = Printer::default(); printer.write_module(module); @@ -274,3 +274,10 @@ pub fn print_ast_node(node: ASTNode) -> String { printer.write_node(node); printer.out } + +/// Print schema expression AST node to string. +pub fn print_schema_expr(schema_expr: &ast::SchemaExpr) -> String { + let mut printer = Printer::default(); + printer.walk_schema_expr(schema_expr); + printer.out +} diff --git a/kclvm/ast_pretty/src/node.rs b/kclvm/ast_pretty/src/node.rs index efecaab25..d32845968 100644 --- a/kclvm/ast_pretty/src/node.rs +++ b/kclvm/ast_pretty/src/node.rs @@ -10,10 +10,7 @@ use kclvm_ast::{ use super::{Indentation, Printer}; type ParameterType<'a> = ( - ( - &'a ast::NodeRef, - &'a Option>, - ), + (&'a ast::NodeRef, Option), &'a Option>, ); @@ -39,10 +36,11 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { for comment in &module.comments { self.comments.push_back(comment.clone()); } - if !module.doc.is_empty() { - self.write(&module.doc); + if let Some(doc) = &module.doc { + self.write(&doc.node); self.write_newline(); } + self.stmts(&module.body); } @@ -123,15 +121,24 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { self.write_indentation(Indentation::Indent); self.stmts(&if_stmt.body); self.write_indentation(Indentation::Dedent); + if !if_stmt.orelse.is_empty() { - if let ast::Stmt::If(elif_stmt) = &if_stmt.orelse[0].node { - // Nested if statements need to be considered, - // so `el` needs to be preceded by the current indentation. - self.fill("el"); - self.walk_if_stmt(elif_stmt); + // Check if orelse contains exactly one if statement + if if_stmt.orelse.len() == 1 { + if let ast::Stmt::If(elif_stmt) = &if_stmt.orelse[0].node { + // Nested if statements need to be considered, + // so `el` needs to be preceded by the current indentation. + self.fill("el"); + self.walk_if_stmt(elif_stmt); + } else { + self.fill("else:"); + self.write_newline_without_fill(); + self.write_indentation(Indentation::Indent); + self.stmts(&if_stmt.orelse); + self.write_indentation(Indentation::Dedent); + } } else { - // Nested if statements need to be considered, - // so `el` needs to be preceded by the current indentation. + // Handle multiple else statements self.fill("else:"); self.write_newline_without_fill(); self.write_indentation(Indentation::Indent); @@ -145,10 +152,10 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { fn walk_import_stmt(&mut self, import_stmt: &'ctx ast::ImportStmt) -> Self::Result { self.write("import "); - self.write(&import_stmt.path); + self.write(&import_stmt.path.node); if let Some(as_name) = &import_stmt.asname { self.write(" as "); - self.write(as_name); + self.write(&as_name.node); } self.write_newline_without_fill(); } @@ -190,11 +197,13 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { self.write_token(TokenKind::Colon); self.write_newline_without_fill(); self.write_indentation(Indentation::Indent); - if !schema_stmt.doc.is_empty() { + + if let Some(doc) = &schema_stmt.doc { self.fill(""); - self.write(&schema_stmt.doc); + self.write(&doc.node); self.write_newline_without_fill(); } + if !schema_stmt.mixins.is_empty() { self.fill(""); self.write("mixin ["); @@ -221,11 +230,11 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { if let Some(key_name) = &index_signature.node.key_name { self.write(&format!("{}: ", key_name)); } - self.write(&index_signature.node.key_type.node); + self.write(&index_signature.node.key_ty.node.to_string()); self.write_token(TokenKind::CloseDelim(DelimToken::Bracket)); self.write_token(TokenKind::Colon); self.write_space(); - self.write(&index_signature.node.value_type.node); + self.write(&index_signature.node.value_ty.node.to_string()); if let Some(value) = &index_signature.node.value { self.write(" = "); self.expr(value); @@ -287,8 +296,8 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { self.write_token(TokenKind::Colon); // Rule Stmt indent self.write_indentation(Indentation::IndentWithNewline); - if !rule_stmt.doc.is_empty() { - self.write(&rule_stmt.doc); + if let Some(doc) = &rule_stmt.doc { + self.write(&doc.node); self.write_newline(); } if !rule_stmt.checks.is_empty() { @@ -342,17 +351,14 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { if !schema_attr.decorators.is_empty() { self.write_newline(); } - self.write(&schema_attr.name.node); + self.write_attribute(&schema_attr.name); if schema_attr.is_optional { self.write("?"); } self.write(": "); - self.write(&schema_attr.type_str.node); + self.write(&schema_attr.ty.node.to_string()); if let Some(op) = &schema_attr.op { - let symbol = match op { - ast::BinOrAugOp::Bin(bin_op) => bin_op.symbol(), - ast::BinOrAugOp::Aug(aug_op) => aug_op.symbol(), - }; + let symbol = op.symbol(); self.write_space(); self.write(symbol); self.write_space(); @@ -382,10 +388,7 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { } fn walk_binary_expr(&mut self, binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { - let symbol = match &binary_expr.op { - ast::BinOrCmpOp::Bin(bin_op) => bin_op.symbol(), - ast::BinOrCmpOp::Cmp(cmp_op) => cmp_op.symbol(), - }; + let symbol = binary_expr.op.symbol(); self.expr(&binary_expr.left); self.write_space(); self.write(symbol); @@ -668,11 +671,11 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { self.write_space(); self.walk_arguments(&args.node); } - if let Some(ty_str) = &lambda_expr.return_type_str { + if let Some(ty_str) = &lambda_expr.return_ty { self.write_space(); self.write_token(TokenKind::RArrow); self.write_space(); - self.write(ty_str); + self.write(&ty_str.node.to_string()); } self.write_space(); self.write_token(TokenKind::OpenDelim(DelimToken::Brace)); @@ -683,7 +686,7 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { self.stmts(&lambda_expr.body); self.write_indentation(Indentation::Dedent); - self.write_newline(); + self.fill(""); self.write_token(TokenKind::CloseDelim(DelimToken::Brace)); } @@ -699,7 +702,12 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { let parameter_zip_list: Vec> = arguments .args .iter() - .zip(arguments.type_annotation_list.iter()) + .zip( + arguments + .ty_list + .iter() + .map(|ty| ty.clone().map(|n| n.node.to_string())), + ) .zip(arguments.defaults.iter()) .collect(); interleave!( @@ -708,7 +716,7 @@ impl<'p, 'ctx> MutSelfTypedResultWalker<'ctx> for Printer<'p> { let ((arg, ty_str), default) = para; self.walk_identifier(&arg.node); if let Some(ty_str) = ty_str { - self.write(&format!(": {}", ty_str.node)); + self.write(&format!(": {}", ty_str)); } if let Some(default) = default { self.write(" = "); @@ -848,16 +856,16 @@ impl<'p> Printer<'p> { ast::Expr::Identifier(identifier) => { self.hook.pre(self, super::ASTNode::Expr(key)); self.write_ast_comments(key); - // Judge contains string identifier, e.g., "x-y-z" + // Judge contains string or dot identifier, e.g., "x-y-z" and "a.b.c" let names = &identifier.names; let re = fancy_regex::Regex::new(IDENTIFIER_REGEX).unwrap(); - let need_right_brace = !names.iter().all(|n| re.is_match(n).unwrap_or(false)); + let need_right_brace = !names.iter().all(|n| re.is_match(&n.node).unwrap_or(false)); let count = if need_right_brace { self.write( &names .iter() - .map(|n| format!("{n:?}")) + .map(|n| format!("{:?}", n.node)) .collect::>() .join(": {"), ); @@ -875,6 +883,16 @@ impl<'p> Printer<'p> { } } } + + fn write_attribute(&mut self, attr: &ast::NodeRef) { + let re = fancy_regex::Regex::new(IDENTIFIER_REGEX).unwrap(); + let need_quote = !re.is_match(&attr.node).unwrap(); + if need_quote { + self.write(&format!("{:?}", attr.node)); + } else { + self.write(&attr.node); + }; + } } impl<'p> Printer<'p> { @@ -904,8 +922,18 @@ impl<'p> Printer<'p> { } pub fn stmts(&mut self, stmts: &[ast::NodeRef]) { + let mut prev_stmt: Option = None; for stmt in stmts { + let import_stmt_alter = match (prev_stmt.as_ref(), stmt.as_ref().node.to_owned()) { + (Some(ast::Stmt::Import(_)), ast::Stmt::Import(_)) => false, + (Some(ast::Stmt::Import(_)), _) => true, + _ => false, + }; + if import_stmt_alter { + self.write_newline(); + } self.stmt(stmt); + prev_stmt = Some(stmt.node.to_owned()); } } } diff --git a/kclvm/ast_pretty/src/test_data/codelayout.input b/kclvm/ast_pretty/src/test_data/codelayout.input index 46121bd5e..8df50874f 100644 --- a/kclvm/ast_pretty/src/test_data/codelayout.input +++ b/kclvm/ast_pretty/src/test_data/codelayout.input @@ -7,6 +7,8 @@ import math as alias_math schema Person ( Base): name:str age:int + "attr": str + "attr-x": str check : age>0 if age , "age must > 0" person = Person{ diff --git a/kclvm/ast_pretty/src/test_data/codelayout.output b/kclvm/ast_pretty/src/test_data/codelayout.output index d8253bd56..d7171dd65 100644 --- a/kclvm/ast_pretty/src/test_data/codelayout.output +++ b/kclvm/ast_pretty/src/test_data/codelayout.output @@ -2,9 +2,12 @@ Module documents """ import math as alias_math + schema Person(Base): name: str age: int + attr: str + "attr-x": str check: age > 0 if age, "age must > 0" diff --git a/kclvm/ast_pretty/src/test_data/lambda.output b/kclvm/ast_pretty/src/test_data/lambda.output index fde503ab9..29ba32df7 100644 --- a/kclvm/ast_pretty/src/test_data/lambda.output +++ b/kclvm/ast_pretty/src/test_data/lambda.output @@ -3,19 +3,15 @@ sumFunc1 = lambda x, y { z = x + y # Inline comments 2 z + x - } sumFunc2 = lambda x, y = 1 { x + y - } sumFunc3 = lambda x = 1, y = 1 { x + y - } sumFunc4 = lambda x: int = 1, y: int = 1 -> int { x + y - } x0 = sumFunc1(1, 2) x1 = sumFunc1(2, 3) @@ -24,5 +20,4 @@ x3 = sumFunc1(4, 5) x = lambda { # Inline comments 1 - }() diff --git a/kclvm/ast_pretty/src/test_data/orelse.input b/kclvm/ast_pretty/src/test_data/orelse.input new file mode 100644 index 000000000..613d7ec74 --- /dev/null +++ b/kclvm/ast_pretty/src/test_data/orelse.input @@ -0,0 +1,31 @@ +if True: + a = 1 +else: + if True: + b = 2 + + if True: + c = 3 + +d = [ + if True: + 1 + else: + if True: + 2 + + if True: + 3 + +] +e = { + if True: + a = 1 + else: + if True: + b = 2 + + if True: + c = 3 + +} diff --git a/kclvm/ast_pretty/src/test_data/orelse.output b/kclvm/ast_pretty/src/test_data/orelse.output new file mode 100644 index 000000000..613d7ec74 --- /dev/null +++ b/kclvm/ast_pretty/src/test_data/orelse.output @@ -0,0 +1,31 @@ +if True: + a = 1 +else: + if True: + b = 2 + + if True: + c = 3 + +d = [ + if True: + 1 + else: + if True: + 2 + + if True: + 3 + +] +e = { + if True: + a = 1 + else: + if True: + b = 2 + + if True: + c = 3 + +} diff --git a/kclvm/ast_pretty/src/test_data/type_alias.output b/kclvm/ast_pretty/src/test_data/type_alias.output index d80ac1c1b..f8c7ca3f2 100644 --- a/kclvm/ast_pretty/src/test_data/type_alias.output +++ b/kclvm/ast_pretty/src/test_data/type_alias.output @@ -1,4 +1,4 @@ -type Color = "Red"|"Yellow"|"Blue" +type Color = "Red" | "Yellow" | "Blue" colorRed: Color = "Red" colorYellow: Color = "Yellow" colorBlue: Color = "Blue" diff --git a/kclvm/ast_pretty/src/tests.rs b/kclvm/ast_pretty/src/tests.rs index 191327ebe..5ef2f2494 100644 --- a/kclvm/ast_pretty/src/tests.rs +++ b/kclvm/ast_pretty/src/tests.rs @@ -1,12 +1,12 @@ use std::path::{Path, PathBuf}; use super::print_ast_module; -use kclvm_parser::parse_file; +use kclvm_parser::parse_file_force_errors; use pretty_assertions::assert_eq; const FILE_INPUT_SUFFIX: &str = ".input"; const FILE_OUTPUT_SUFFIX: &str = ".output"; -const TEST_CASES: &[&'static str; 16] = &[ +const TEST_CASES: &[&str] = &[ "arguments", "empty", "if_stmt", @@ -18,6 +18,7 @@ const TEST_CASES: &[&'static str; 16] = &[ "index_sign", "joined_str", "lambda", + "orelse", "quant", "rule", "str", @@ -30,18 +31,18 @@ fn read_data(data_name: &str) -> (String, String) { filename.push( Path::new("src") .join("test_data") - .join(&format!("{}{}", data_name, FILE_INPUT_SUFFIX)) + .join(format!("{}{}", data_name, FILE_INPUT_SUFFIX)) .display() .to_string(), ); - let module = parse_file(filename.to_str().unwrap(), None); + let module = parse_file_force_errors(filename.to_str().unwrap(), None); let mut filename_expect = PathBuf::from(env!("CARGO_MANIFEST_DIR")); filename_expect.push( Path::new("src") .join("test_data") - .join(&format!("{}{}", data_name, FILE_OUTPUT_SUFFIX)) + .join(format!("{}{}", data_name, FILE_OUTPUT_SUFFIX)) .display() .to_string(), ); diff --git a/kclvm/cmd/Cargo.toml b/kclvm/cmd/Cargo.toml index 6a9e24eaf..c4f07acaf 100644 --- a/kclvm/cmd/Cargo.toml +++ b/kclvm/cmd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-cmd" -version = "0.5.0" +version = "0.8.1" edition = "2021" [dependencies] diff --git a/kclvm/cmd/src/fmt.rs b/kclvm/cmd/src/fmt.rs index 78f2d3a83..aa8c4fadb 100644 --- a/kclvm/cmd/src/fmt.rs +++ b/kclvm/cmd/src/fmt.rs @@ -13,6 +13,7 @@ pub fn fmt_command(matches: &ArgMatches) -> Result<()> { &FormatOptions { is_stdout: bool_from_matches(matches, "std_output").unwrap_or_default(), recursively: bool_from_matches(matches, "recursive").unwrap_or_default(), + omit_errors: true, }, )?; Ok(()) diff --git a/kclvm/cmd/src/lib.rs b/kclvm/cmd/src/lib.rs index 17b469160..9ce5a428a 100644 --- a/kclvm/cmd/src/lib.rs +++ b/kclvm/cmd/src/lib.rs @@ -57,19 +57,34 @@ pub fn app() -> Command { .arg(arg!(strict_range_check: -r --strict_range_check "Do perform strict numeric range checks")) .arg(arg!(debug: -d --debug "Run in debug mode (for developers only)")) .arg(arg!(sort_keys: -k --sort_keys "Sort result keys")) + .arg(arg!(show_hidden: -H --show_hidden "Display hidden attributes")) .arg(arg!(arguments: -D --argument ... "Specify the top-level argument").num_args(1..)) .arg(arg!(path_selector: -S --path_selector ... "Specify the path selector").num_args(1..)) .arg(arg!(overrides: -O --overrides ... "Specify the configuration override path and value").num_args(1..)) .arg(arg!(target: --target "Specify the target type")) + .arg(arg!(recursive: -R --recursive "Compile the files directory recursively")) .arg(arg!(package_map: -E --external ... "Mapping of package name and path where the package is located").num_args(1..)), ) .subcommand( Command::new("lint") .about("lint") .arg(arg!([input] ... "Sets the input file to use").num_args(0..)) + .arg(arg!(output: -o --output "Specify the YAML output file path")) .arg(arg!(setting: -Y --setting ... "Sets the input file to use").num_args(1..)) .arg(arg!(verbose: -v --verbose "Print test information verbosely").action(ArgAction::Count)) - .arg(arg!(emit_warning: --emit_warning "Emit warning message")), + .arg(arg!(emit_warning: --emit_warning "Emit warning message")) + .arg(arg!(disable_none: -n --disable_none "Disable dumping None values")) + .arg(arg!(strict_range_check: -r --strict_range_check "Do perform strict numeric range checks")) + .arg(arg!(debug: -d --debug "Run in debug mode (for developers only)")) + .arg(arg!(sort_keys: -k --sort_keys "Sort result keys")) + .arg(arg!(show_hidden: -H --show_hidden "Display hidden attributes")) + .arg(arg!(arguments: -D --argument ... "Specify the top-level argument").num_args(1..)) + .arg(arg!(path_selector: -S --path_selector ... "Specify the path selector").num_args(1..)) + .arg(arg!(overrides: -O --overrides ... "Specify the configuration override path and value").num_args(1..)) + .arg(arg!(target: --target "Specify the target type")) + .arg(arg!(recursive: -R --recursive "Compile the files directory recursively")) + .arg(arg!(package_map: -E --external ... "Mapping of package name and path where the package is located").num_args(1..)) + .arg(arg!(fix: -f --fix "Auto fix")), ) .subcommand( Command::new("fmt") diff --git a/kclvm/cmd/src/lint.rs b/kclvm/cmd/src/lint.rs index f6a8bb36e..26e2d55a4 100644 --- a/kclvm/cmd/src/lint.rs +++ b/kclvm/cmd/src/lint.rs @@ -1,8 +1,9 @@ +use crate::util::*; use anyhow::Result; use clap::ArgMatches; use kclvm_error::Handler; use kclvm_runner::ExecProgramArgs; -use kclvm_tools::lint::lint_files; +use kclvm_tools::{fix, lint::lint_files}; use crate::settings::must_build_settings; @@ -22,11 +23,19 @@ pub fn lint_command(matches: &ArgMatches) -> Result<()> { args.get_files() }; let (mut err_handler, mut warning_handler) = (Handler::default(), Handler::default()); + (err_handler.diagnostics, warning_handler.diagnostics) = lint_files(&files, Some(args.get_load_program_options())); - if matches.get_count("emit_warning") > 0 { + if bool_from_matches(matches, "emit_warning").unwrap_or_default() { warning_handler.emit()?; } + + if bool_from_matches(matches, "fix").unwrap_or_default() { + let mut diags = vec![]; + diags.extend(err_handler.diagnostics.clone()); + diags.extend(warning_handler.diagnostics); + fix::fix(diags)?; + } err_handler.abort_if_any_errors(); Ok(()) } diff --git a/kclvm/cmd/src/run.rs b/kclvm/cmd/src/run.rs index b66a286a9..9ab1fd469 100644 --- a/kclvm/cmd/src/run.rs +++ b/kclvm/cmd/src/run.rs @@ -15,17 +15,31 @@ pub fn run_command(matches: &ArgMatches, writer: &mut W) -> Result<()> let output = settings.output(); let sess = Arc::new(ParseSession::default()); match exec_program(sess.clone(), &settings.try_into()?) { - Ok(result) => match output { - Some(o) => { - std::fs::write(o, result.yaml_result)?; + Ok(result) => { + // Output log message + if !result.log_message.is_empty() { + write!(writer, "{}", result.log_message)?; } - // [`println!`] is not a good way to output content to stdout, - // using [`writeln`] can be better to redirect the output. - None => writeln!(writer, "{}", result.yaml_result)?, - }, + // Output execute error message + if !result.err_message.is_empty() { + if !sess.0.diag_handler.has_errors()? { + sess.0.add_err(StringError(result.err_message))?; + } + sess.0.emit_stashed_diagnostics_and_abort()?; + } + if !result.yaml_result.is_empty() { + match output { + Some(o) => std::fs::write(o, result.yaml_result)?, + // [`println!`] is not a good way to output content to stdout, + // using [`writeln`] can be better to redirect the output. + None => writeln!(writer, "{}", result.yaml_result)?, + } + } + } + // Other error message Err(msg) => { if !sess.0.diag_handler.has_errors()? { - sess.0.add_err(StringError(msg))?; + sess.0.add_err(StringError(msg.to_string()))?; } sess.0.emit_stashed_diagnostics_and_abort()?; } diff --git a/kclvm/cmd/src/settings.rs b/kclvm/cmd/src/settings.rs index 3a8d27928..07e7d180f 100644 --- a/kclvm/cmd/src/settings.rs +++ b/kclvm/cmd/src/settings.rs @@ -52,6 +52,7 @@ pub(crate) fn build_settings(matches: &ArgMatches) -> Result { verbose: u32_from_matches(matches, "verbose"), debug: bool_from_matches(matches, "debug"), sort_keys: bool_from_matches(matches, "sort_keys"), + show_hidden: bool_from_matches(matches, "show_hidden"), package_maps, ..Default::default() }), diff --git a/kclvm/cmd/src/test_data/cache_test/kcl.mod b/kclvm/cmd/src/test_data/cache_test/kcl.mod new file mode 100644 index 000000000..45eec5c29 --- /dev/null +++ b/kclvm/cmd/src/test_data/cache_test/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "cache_test" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.0" diff --git a/kclvm/cmd/src/test_data/cache_test/main.k b/kclvm/cmd/src/test_data/cache_test/main.k new file mode 100644 index 000000000..7d2efc690 --- /dev/null +++ b/kclvm/cmd/src/test_data/cache_test/main.k @@ -0,0 +1,3 @@ +import helloworld as hw + +a = hw.The_first_kcl_program \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/failed/keyword_argument_error.k b/kclvm/cmd/src/test_data/failed/keyword_argument_error.k new file mode 100644 index 000000000..e034af544 --- /dev/null +++ b/kclvm/cmd/src/test_data/failed/keyword_argument_error.k @@ -0,0 +1 @@ +a = "{ID}".format(2) # keyword argument not found -> keyword argument 'ID' not found \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/fuzz_match/main.k b/kclvm/cmd/src/test_data/fuzz_match/main.k new file mode 100644 index 000000000..1a5682818 --- /dev/null +++ b/kclvm/cmd/src/test_data/fuzz_match/main.k @@ -0,0 +1,6 @@ +schema Person: + aa?: int + aaa?: int + +p = Person {} +a = p.a # Error, attribute 'a' not found in `Person`, did you mean `aa`? \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/fuzz_match/main_unmatched.k b/kclvm/cmd/src/test_data/fuzz_match/main_unmatched.k new file mode 100644 index 000000000..f802a7d70 --- /dev/null +++ b/kclvm/cmd/src/test_data/fuzz_match/main_unmatched.k @@ -0,0 +1,6 @@ +schema Person: + en?: int + sd?: int + +p = Person {} +a = p.a # Error, attribute 'a' not found in `Person` \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_1/expected b/kclvm/cmd/src/test_data/instances/test_inst_1/expected new file mode 100644 index 000000000..068711d7a --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_1/expected @@ -0,0 +1,4 @@ +a: + id: 1 +k1_inst: +- id: 1 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.mod new file mode 100644 index 000000000..ab572545d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl1" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.yaml new file mode 100644 index 000000000..77eae8d83 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_1/kcl.yaml @@ -0,0 +1,4 @@ +kcl_cli_configs: + file: + - ./main.k + - ./main1.k \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_1/main.k b/kclvm/cmd/src/test_data/instances/test_inst_1/main.k new file mode 100644 index 000000000..5fb051abc --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_1/main.k @@ -0,0 +1,3 @@ +a = K1 { + id: 1 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_1/main1.k b/kclvm/cmd/src/test_data/instances/test_inst_1/main1.k new file mode 100644 index 000000000..ee0e11d82 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_1/main1.k @@ -0,0 +1,5 @@ +schema K1: + id: int + +k1_inst = K1.instances() + \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/expected b/kclvm/cmd/src/test_data/instances/test_inst_10/expected new file mode 100644 index 000000000..2e394772b --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/expected @@ -0,0 +1,3 @@ +a: + id: 102 +inst102: [] diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_10/kcl.yaml new file mode 100644 index 000000000..0dfc987fd --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/kcl.yaml @@ -0,0 +1,7 @@ +kcl_cli_configs: + file: + - ./test_inst_101/main.k + - ${test_inst_102:KCL_MOD}/main.k + package_maps: + test_inst_102: ./src/test_data/instances/test_inst_10/test_inst_102 + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/kcl.mod new file mode 100644 index 000000000..3040fb9e1 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_101" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/main.k b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/main.k new file mode 100644 index 000000000..12d2fe392 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_101/main.k @@ -0,0 +1,5 @@ +import test_inst_102 as k102 + +a = k102.K102 { + id: 102 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/kcl.mod new file mode 100644 index 000000000..341192b5c --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_102" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/main.k b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/main.k new file mode 100644 index 000000000..27b218bce --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_10/test_inst_102/main.k @@ -0,0 +1,4 @@ +schema K102: + id: int + +inst102 = K102.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_11/kcl.mod new file mode 100644 index 000000000..a626cfb0f --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_11" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/model/main.k b/kclvm/cmd/src/test_data/instances/test_inst_11/model/main.k new file mode 100644 index 000000000..b43778076 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/model/main.k @@ -0,0 +1,3 @@ +schema K11: + msg: str + \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/sub/main.k b/kclvm/cmd/src/test_data/instances/test_inst_11/sub/main.k new file mode 100644 index 000000000..486e93f97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/sub/main.k @@ -0,0 +1,5 @@ +import model as m + +k11_inst: m.K11 { + msg: "k11_in_sub" +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/expected b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/expected new file mode 100644 index 000000000..3ad7b524b --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/expected @@ -0,0 +1,2 @@ +k11_inst: + msg: k11_in_main diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.mod new file mode 100644 index 000000000..5c0234dc8 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_111" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.yaml new file mode 100644 index 000000000..553e82d00 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/kcl.yaml @@ -0,0 +1,6 @@ +kcl_cli_configs: + file: + - ../sub/main.k + - ./main.k + package_maps: + test_inst_11: ./src/test_data/instances/test_inst_11 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/main.k b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/main.k new file mode 100644 index 000000000..c6985755e --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_11/test_inst_111/main.k @@ -0,0 +1,5 @@ +import test_inst_11.model as m + +k11_inst: m.K11 { + msg= "k11_in_main" +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_2/expected b/kclvm/cmd/src/test_data/instances/test_inst_2/expected new file mode 100644 index 000000000..96310e046 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_2/expected @@ -0,0 +1,4 @@ +a: + id: 2 +k2_inst: +- id: 2 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.mod new file mode 100644 index 000000000..5fb058acd --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl2" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.yaml new file mode 100644 index 000000000..9dcc889ec --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_2/kcl.yaml @@ -0,0 +1,4 @@ +kcl_cli_configs: + file: + - ./main.k + - ./sub/main.k \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_2/main.k b/kclvm/cmd/src/test_data/instances/test_inst_2/main.k new file mode 100644 index 000000000..2a75ebbf4 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_2/main.k @@ -0,0 +1,3 @@ +a = K2 { + id: 2 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_2/sub/main.k b/kclvm/cmd/src/test_data/instances/test_inst_2/sub/main.k new file mode 100644 index 000000000..8e53dab35 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_2/sub/main.k @@ -0,0 +1,5 @@ +schema K2: + id: int + +k2_inst = K2.instances() + \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/expected b/kclvm/cmd/src/test_data/instances/test_inst_3/expected new file mode 100644 index 000000000..d22191949 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/expected @@ -0,0 +1,4 @@ +a: + id: 3 +k3_inst: +- id: 3 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.mod new file mode 100644 index 000000000..b99124970 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl3" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.yaml new file mode 100644 index 000000000..2d7b7fdcd --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/kcl.yaml @@ -0,0 +1,5 @@ +kcl_cli_configs: + file: + - ./main.k + - ./sub/main.k + - ./main1.k \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/main.k b/kclvm/cmd/src/test_data/instances/test_inst_3/main.k new file mode 100644 index 000000000..60db6eef8 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/main.k @@ -0,0 +1,3 @@ +a = K3 { + id: 3 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/main1.k b/kclvm/cmd/src/test_data/instances/test_inst_3/main1.k new file mode 100644 index 000000000..d312a229e --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/main1.k @@ -0,0 +1 @@ +k3_inst = K3.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_3/sub/main.k b/kclvm/cmd/src/test_data/instances/test_inst_3/sub/main.k new file mode 100644 index 000000000..cdcb7ca7e --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_3/sub/main.k @@ -0,0 +1,2 @@ +schema K3: + id: int diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/expected b/kclvm/cmd/src/test_data/instances/test_inst_4/expected new file mode 100644 index 000000000..f01127b25 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/expected @@ -0,0 +1,4 @@ +a: + id: 4 +k4_inst: +- id: 4 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_4/kcl.yaml new file mode 100644 index 000000000..e5d69adb0 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/kcl.yaml @@ -0,0 +1,6 @@ +kcl_cli_configs: + file: + - ./test_inst_41/main.k + - ${test_inst_42:KCL_MOD}/main.k + package_maps: + test_inst_42: ./src/test_data/instances/test_inst_4/test_inst_42 \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/kcl.mod new file mode 100644 index 000000000..d091b26c8 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_41" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/main.k b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/main.k new file mode 100644 index 000000000..369306369 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_41/main.k @@ -0,0 +1,3 @@ +a = K4 { + id: 4 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/kcl.mod new file mode 100644 index 000000000..48145caaa --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_42" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/main.k b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/main.k new file mode 100644 index 000000000..4ea096248 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_4/test_inst_42/main.k @@ -0,0 +1,5 @@ +schema K4: + id: int + +k4_inst = K4.instances() + \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/expected b/kclvm/cmd/src/test_data/instances/test_inst_5/expected new file mode 100644 index 000000000..41fa02201 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/expected @@ -0,0 +1,5 @@ +a: + id: 5 +b: 5 +k5_inst: +- id: 5 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_5/kcl.yaml new file mode 100644 index 000000000..e28df2d75 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/kcl.yaml @@ -0,0 +1,8 @@ +kcl_cli_configs: + file: + - ./test_inst_51/ + - ${test_inst_52:KCL_MOD}/main.k + - ${test_inst_53:KCL_MOD}/main.k + package_maps: + test_inst_52: ./src/test_data/instances/test_inst_5/test_inst_52 + test_inst_53: ./src/test_data/instances/test_inst_5/test_inst_53 \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/kcl.mod new file mode 100644 index 000000000..dfbf2645d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_51" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main.k b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main.k new file mode 100644 index 000000000..18fa27a97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main.k @@ -0,0 +1,3 @@ +a = K5 { + id: 5 +} diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main1.k b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main1.k new file mode 100644 index 000000000..b3c0d6826 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_51/main1.k @@ -0,0 +1 @@ +b = 5 \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/kcl.mod new file mode 100644 index 000000000..275d64c97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_52" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/main.k b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/main.k new file mode 100644 index 000000000..d61010865 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_52/main.k @@ -0,0 +1,2 @@ +schema K5: + id: int diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/kcl.mod new file mode 100644 index 000000000..02ba5f429 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_53" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/main.k b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/main.k new file mode 100644 index 000000000..696729ce2 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_5/test_inst_53/main.k @@ -0,0 +1 @@ +k5_inst = K5.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/expected b/kclvm/cmd/src/test_data/instances/test_inst_6/expected new file mode 100644 index 000000000..af351576e --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/expected @@ -0,0 +1,4 @@ +a: + id: 6 +k6_inst: +- id: 6 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_6/kcl.yaml new file mode 100644 index 000000000..8770ea1e8 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/kcl.yaml @@ -0,0 +1,8 @@ +kcl_cli_configs: + file: + - ${test_inst_61:KCL_MOD}/main.k + - ./test_inst_62/ + - ${test_inst_63:KCL_MOD}/main.k + package_maps: + test_inst_61: ./src/test_data/instances/test_inst_6/test_inst_61 + test_inst_63: ./src/test_data/instances/test_inst_6/test_inst_63 \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/kcl.mod new file mode 100644 index 000000000..dfbf2645d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_51" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/main.k b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/main.k new file mode 100644 index 000000000..355fc8f4d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_61/main.k @@ -0,0 +1,3 @@ +a = K6 { + id: 6 +} diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/kcl.mod new file mode 100644 index 000000000..275d64c97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_52" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/main.k b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/main.k new file mode 100644 index 000000000..2d4badc7e --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_62/main.k @@ -0,0 +1,2 @@ +schema K6: + id: int diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/kcl.mod new file mode 100644 index 000000000..02ba5f429 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_53" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/main.k b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/main.k new file mode 100644 index 000000000..7eb738e2c --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_6/test_inst_63/main.k @@ -0,0 +1 @@ +k6_inst = K6.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/expected b/kclvm/cmd/src/test_data/instances/test_inst_7/expected new file mode 100644 index 000000000..27cd4a719 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/expected @@ -0,0 +1,4 @@ +a: + id: 7 +k7_inst: +- id: 7 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_7/kcl.yaml new file mode 100644 index 000000000..13ba11147 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/kcl.yaml @@ -0,0 +1,8 @@ +kcl_cli_configs: + file: + - ${test_inst_71:KCL_MOD}/main.k + - ${test_inst_72:KCL_MOD}/main.k + - ./test_inst_73/ + package_maps: + test_inst_71: ./src/test_data/instances/test_inst_7/test_inst_71 + test_inst_72: ./src/test_data/instances/test_inst_7/test_inst_72 \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/kcl.mod new file mode 100644 index 000000000..dfbf2645d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_51" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/main.k b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/main.k new file mode 100644 index 000000000..4093b9ac7 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_71/main.k @@ -0,0 +1,3 @@ +a = K7 { + id: 7 +} diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/kcl.mod new file mode 100644 index 000000000..275d64c97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_52" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/main.k b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/main.k new file mode 100644 index 000000000..44c5fd90a --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_72/main.k @@ -0,0 +1,2 @@ +schema K7: + id: int diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/kcl.mod new file mode 100644 index 000000000..02ba5f429 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_53" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/main.k b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/main.k new file mode 100644 index 000000000..d13a3dec5 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_7/test_inst_73/main.k @@ -0,0 +1 @@ +k7_inst = K7.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/expected b/kclvm/cmd/src/test_data/instances/test_inst_8/expected new file mode 100644 index 000000000..f4401ec70 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/expected @@ -0,0 +1,17 @@ +a: + id: 8 +b: + id: 81 +c: + id: 82 +k8_inst_1: +- id: 8 +- id: 81 +- id: 82 +d: + id: 83 +k8_inst_2: +- id: 8 +- id: 81 +- id: 82 +- id: 83 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.mod new file mode 100644 index 000000000..f94033c0d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_8" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.yaml new file mode 100644 index 000000000..f72877684 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/kcl.yaml @@ -0,0 +1,14 @@ +kcl_cli_configs: + file: + - ${test_inst_81:KCL_MOD}/main.k + - ./main.k + - ${test_inst_82:KCL_MOD}/main.k + - ./main1.k + - ${test_inst_83:KCL_MOD}/main.k + - ./main2.k + - ${test_inst_84:KCL_MOD}/main.k + package_maps: + test_inst_81: ./src/test_data/instances/test_inst_8/test_inst_81 + test_inst_82: ./src/test_data/instances/test_inst_8/test_inst_82 + test_inst_83: ./src/test_data/instances/test_inst_8/test_inst_83 + test_inst_84: ./src/test_data/instances/test_inst_8/test_inst_84 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/main.k b/kclvm/cmd/src/test_data/instances/test_inst_8/main.k new file mode 100644 index 000000000..c62b3d2f3 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/main.k @@ -0,0 +1,3 @@ +b = K8 { + id: 81 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/main1.k b/kclvm/cmd/src/test_data/instances/test_inst_8/main1.k new file mode 100644 index 000000000..17acf70a6 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/main1.k @@ -0,0 +1,3 @@ +c = K8 { + id: 82 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/main2.k b/kclvm/cmd/src/test_data/instances/test_inst_8/main2.k new file mode 100644 index 000000000..c99980af3 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/main2.k @@ -0,0 +1,3 @@ +d = K8 { + id: 83 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/kcl.mod new file mode 100644 index 000000000..dfbf2645d --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_51" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/main.k b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/main.k new file mode 100644 index 000000000..cb29f08b7 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_81/main.k @@ -0,0 +1,3 @@ +a = K8 { + id: 8 +} diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/kcl.mod new file mode 100644 index 000000000..275d64c97 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_52" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/main.k b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/main.k new file mode 100644 index 000000000..706da08e9 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_82/main.k @@ -0,0 +1,2 @@ +schema K8: + id: int diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/kcl.mod new file mode 100644 index 000000000..02ba5f429 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_53" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/main.k b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/main.k new file mode 100644 index 000000000..71513c9f9 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_83/main.k @@ -0,0 +1 @@ +k8_inst_1 = K8.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/kcl.mod new file mode 100644 index 000000000..02ba5f429 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_53" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/main.k b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/main.k new file mode 100644 index 000000000..e257da19c --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_8/test_inst_84/main.k @@ -0,0 +1 @@ +k8_inst_2 = K8.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/expected b/kclvm/cmd/src/test_data/instances/test_inst_9/expected new file mode 100644 index 000000000..f27fc6f83 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/expected @@ -0,0 +1,4 @@ +a: + id: 92 +inst92: +- id: 92 diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/kcl.yaml b/kclvm/cmd/src/test_data/instances/test_inst_9/kcl.yaml new file mode 100644 index 000000000..506e7a6d6 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/kcl.yaml @@ -0,0 +1,7 @@ +kcl_cli_configs: + file: + - ./test_inst_91/main.k + - ${test_inst_92:KCL_MOD}/main.k + package_maps: + test_inst_92: ./src/test_data/instances/test_inst_9/test_inst_92 + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/kcl.mod new file mode 100644 index 000000000..3040fb9e1 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_101" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/main.k b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/main.k new file mode 100644 index 000000000..990f4bb24 --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_91/main.k @@ -0,0 +1,5 @@ +import test_inst_92.sub as k92 + +a = k92.K92 { + id: 92 +} \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/kcl.mod b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/kcl.mod new file mode 100644 index 000000000..341192b5c --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_inst_102" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/main.k b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/main.k new file mode 100644 index 000000000..1d27555ca --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/main.k @@ -0,0 +1,3 @@ +import sub as s + +inst92 = s.K92.instances() \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/sub/main.k b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/sub/main.k new file mode 100644 index 000000000..73354a6ef --- /dev/null +++ b/kclvm/cmd/src/test_data/instances/test_inst_9/test_inst_92/sub/main.k @@ -0,0 +1,2 @@ +schema K92: + id: int \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/lint/test.k b/kclvm/cmd/src/test_data/lint/test.k new file mode 100644 index 000000000..7a72a2df5 --- /dev/null +++ b/kclvm/cmd/src/test_data/lint/test.k @@ -0,0 +1,9 @@ +name = "kcl" +age = 1 +schema Person: + name: str = "kcl" + age: int = 1 + +x0 = Person {} + +x1 = Person {age = 101} diff --git a/kclvm/cmd/src/test_data/multimod/kcl1/kcl.mod b/kclvm/cmd/src/test_data/multimod/kcl1/kcl.mod new file mode 100644 index 000000000..ab572545d --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl1/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl1" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/multimod/kcl1/main.k b/kclvm/cmd/src/test_data/multimod/kcl1/main.k new file mode 100644 index 000000000..45ada83b6 --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl1/main.k @@ -0,0 +1 @@ +kcl1 = 'hello 1' \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/multimod/kcl2/kcl.mod b/kclvm/cmd/src/test_data/multimod/kcl2/kcl.mod new file mode 100644 index 000000000..5fb058acd --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl2/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl2" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/multimod/kcl2/main.k b/kclvm/cmd/src/test_data/multimod/kcl2/main.k new file mode 100644 index 000000000..9c30e151e --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl2/main.k @@ -0,0 +1 @@ +kcl2 = "hello 2" \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/multimod/kcl3/kcl.mod b/kclvm/cmd/src/test_data/multimod/kcl3/kcl.mod new file mode 100644 index 000000000..b99124970 --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl3/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl3" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/kcl.mod b/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/kcl.mod new file mode 100644 index 000000000..98f429002 --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl4" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/main.k b/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/main.k new file mode 100644 index 000000000..f91707fe6 --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl3/kcl4/main.k @@ -0,0 +1 @@ +k4 = 'Hello World 4' \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/multimod/kcl3/main.k b/kclvm/cmd/src/test_data/multimod/kcl3/main.k new file mode 100644 index 000000000..3b9852426 --- /dev/null +++ b/kclvm/cmd/src/test_data/multimod/kcl3/main.k @@ -0,0 +1 @@ +k3 = 'Hello World 3' \ No newline at end of file diff --git a/kclvm/cmd/src/test_data/plugin/plugin_not_found/kcl.mod b/kclvm/cmd/src/test_data/plugin/plugin_not_found/kcl.mod new file mode 100644 index 000000000..4054bce69 --- /dev/null +++ b/kclvm/cmd/src/test_data/plugin/plugin_not_found/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "plugin_not_found" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/cmd/src/test_data/plugin/plugin_not_found/main.k b/kclvm/cmd/src/test_data/plugin/plugin_not_found/main.k new file mode 100644 index 000000000..a227182df --- /dev/null +++ b/kclvm/cmd/src/test_data/plugin/plugin_not_found/main.k @@ -0,0 +1,3 @@ +import kcl_plugin.not_exist + +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/cmd/src/tests.rs b/kclvm/cmd/src/tests.rs index 4a3be5e50..cc7009236 100644 --- a/kclvm/cmd/src/tests.rs +++ b/kclvm/cmd/src/tests.rs @@ -2,12 +2,20 @@ use std::{ env, fs::{self, remove_file}, path::{Path, PathBuf}, + sync::Arc, }; use kclvm_config::modfile::KCL_PKG_PATH; +use kclvm_parser::ParseSession; +use kclvm_runner::{exec_program, MapErrorResult}; use crate::{ - app, fmt::fmt_command, run::run_command, settings::build_settings, util::hashmaps_from_matches, + app, + fmt::fmt_command, + lint::lint_command, + run::run_command, + settings::{build_settings, must_build_settings}, + util::hashmaps_from_matches, vet::vet_command, }; @@ -195,6 +203,18 @@ fn test_external_cmd_invalid() { } } +#[test] +fn test_lint_cmd() { + let input = std::path::Path::new(".") + .join("src") + .join("test_data") + .join("lint") + .join("test.k"); + let matches = app().get_matches_from(&[ROOT_CMD, "lint", input.to_str().unwrap()]); + let matches = matches.subcommand_matches("lint").unwrap(); + assert!(lint_command(&matches).is_ok()) +} + #[test] // All the unit test cases in [`test_run_command`] can not be executed concurrently. fn test_run_command() { @@ -203,6 +223,14 @@ fn test_run_command() { test_run_command_with_konfig(); test_load_cache_with_different_pkg(); test_kcl_path_is_sym_link(); + test_compile_two_kcl_mod(); + test_main_pkg_not_found(); + test_multi_mod_file(); + test_instances_with_yaml(); + test_plugin_not_found(); + test_error_message_fuzz_matched(); + test_error_message_fuzz_unmatched(); + test_keyword_argument_error_message(); } fn test_run_command_with_import() { @@ -352,3 +380,254 @@ fn test_kcl_path_is_sym_link() { // clean up the symlink remove_file(link).unwrap(); } + +fn test_compile_two_kcl_mod() { + let test_case_path = PathBuf::from("./src/test_data/multimod"); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.join("kcl1/main.k").display().to_string(), + "${kcl2:KCL_MOD}/main.k", + "-E", + &format!("kcl2={}", test_case_path.join("kcl2").display().to_string()), + ]); + + let mut buf = Vec::new(); + run_command(matches.subcommand_matches("run").unwrap(), &mut buf).unwrap(); + + assert_eq!( + "kcl1: hello 1\nkcl2: hello 2\n", + String::from_utf8(buf).unwrap() + ); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.join("kcl2/main.k").display().to_string(), + "${kcl1:KCL_MOD}/main.k", + "-E", + &format!("kcl1={}", test_case_path.join("kcl1").display().to_string()), + ]); + + let mut buf = Vec::new(); + run_command(matches.subcommand_matches("run").unwrap(), &mut buf).unwrap(); + + assert_eq!( + "kcl2: hello 2\nkcl1: hello 1\n", + String::from_utf8(buf).unwrap() + ); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.join("kcl3/main.k").display().to_string(), + "${kcl4:KCL_MOD}/main.k", + "-E", + &format!( + "kcl4={}", + test_case_path + .join("kcl3") + .join("kcl4") + .display() + .to_string() + ), + ]); + + let mut buf = Vec::new(); + run_command(matches.subcommand_matches("run").unwrap(), &mut buf).unwrap(); + + assert_eq!( + "k3: Hello World 3\nk4: Hello World 4\n", + String::from_utf8(buf).unwrap() + ); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path + .join("kcl3/kcl4/main.k") + .display() + .to_string(), + "${kcl3:KCL_MOD}/main.k", + "-E", + &format!("kcl3={}", test_case_path.join("kcl3").display().to_string()), + ]); + + let mut buf = Vec::new(); + run_command(matches.subcommand_matches("run").unwrap(), &mut buf).unwrap(); + + assert_eq!( + "k4: Hello World 4\nk3: Hello World 3\n", + String::from_utf8(buf).unwrap() + ); +} + +fn test_instances_with_yaml() { + let test_cases = [ + "test_inst_1", + "test_inst_2", + "test_inst_3", + "test_inst_4", + "test_inst_5", + "test_inst_6", + "test_inst_7", + "test_inst_8", + "test_inst_9", + "test_inst_10", + "test_inst_11/test_inst_111", + ]; + + for case in &test_cases { + let expected = format!("{}/expected", case); + let case_yaml = format!("{}/kcl.yaml", case); + test_instances(&case_yaml, &expected); + } +} + +fn test_instances(kcl_yaml_path: &str, expected_file_path: &str) { + let test_case_path = PathBuf::from("./src/test_data/instances"); + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + "-Y", + &test_case_path.join(kcl_yaml_path).display().to_string(), + ]); + + let mut buf = Vec::new(); + run_command(matches.subcommand_matches("run").unwrap(), &mut buf).unwrap(); + let expect = fs::read_to_string( + test_case_path + .join(expected_file_path) + .display() + .to_string(), + ) + .unwrap(); + + assert_eq!( + expect.replace("\r\n", "\n"), + String::from_utf8(buf).unwrap() + ); +} + +fn test_main_pkg_not_found() { + let test_case_path = PathBuf::from("./src/test_data/multimod"); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + "${kcl3:KCL_MOD}/main.k", + "-E", + &format!("kcl3={}", test_case_path.join("kcl3").display().to_string()), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()) + .map_err_to_result() + .map_err(|e| e.to_string()) + { + Ok(_) => panic!("unreachable code."), + Err(msg) => assert_eq!( + msg, + "Cannot find the kcl file, please check the file path ${kcl3:KCL_MOD}/main.k" + ), + } +} + +fn test_multi_mod_file() { + let test_case_path = PathBuf::from("./src/test_data/multimod"); + + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.join("kcl1").display().to_string(), + &test_case_path.join("kcl2").display().to_string(), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()) { + Ok(res) => { + assert_eq!(res.yaml_result, "kcl1: hello 1\nkcl2: hello 2"); + assert_eq!( + res.json_result, + "{\"kcl1\": \"hello 1\", \"kcl2\": \"hello 2\"}" + ); + } + Err(_) => panic!("unreachable code."), + } +} + +fn test_plugin_not_found() { + let test_case_path = PathBuf::from("./src/test_data/plugin/plugin_not_found"); + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + test_case_path.as_path().display().to_string().as_str(), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()).map_err_to_result().map_err(|e|e.to_string()) { + Ok(_) => panic!("unreachable code."), + Err(msg) => assert!(msg.contains("the plugin package `kcl_plugin.not_exist` is not found, please confirm if plugin mode is enabled")), + } +} + +fn test_error_message_fuzz_matched() { + let test_case_path = PathBuf::from("./src/test_data/fuzz_match/main.k"); + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.canonicalize().unwrap().display().to_string(), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()) + .map_err_to_result() + .map_err(|e| e.to_string()) + { + Ok(_) => panic!("unreachable code."), + Err(msg) => { + assert!(msg.contains("attribute 'a' not found in 'Person', did you mean '[\"aa\"]'?")) + } + } +} + +fn test_error_message_fuzz_unmatched() { + let test_case_path = PathBuf::from("./src/test_data/fuzz_match/main_unmatched.k"); + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.canonicalize().unwrap().display().to_string(), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()) + .map_err_to_result() + .map_err(|e| e.to_string()) + { + Ok(_) => panic!("unreachable code."), + Err(msg) => { + assert!(msg.contains("attribute 'a' not found in 'Person'")) + } + } +} + +fn test_keyword_argument_error_message() { + let test_case_path = PathBuf::from("./src/test_data/failed/keyword_argument_error.k"); + let matches = app().arg_required_else_help(true).get_matches_from(&[ + ROOT_CMD, + "run", + &test_case_path.canonicalize().unwrap().display().to_string(), + ]); + let settings = must_build_settings(matches.subcommand_matches("run").unwrap()); + let sess = Arc::new(ParseSession::default()); + match exec_program(sess.clone(), &settings.try_into().unwrap()) + .map_err_to_result() + .map_err(|e| e.to_string()) + { + Ok(_) => panic!("unreachable code."), + Err(msg) => { + assert!(msg.contains("keyword argument 'ID' not found")); + } + } +} diff --git a/kclvm/cmd/src/vet.rs b/kclvm/cmd/src/vet.rs index 86a1d2950..c2c1e355a 100644 --- a/kclvm/cmd/src/vet.rs +++ b/kclvm/cmd/src/vet.rs @@ -30,8 +30,7 @@ pub fn vet_command(matches: &ArgMatches) -> Result<()> { Some(kcl_file.to_string()), None, )) - .map_err(|err| anyhow::anyhow!(err))?; - Ok(()) + .map(|_| ()) } _ => Err(anyhow::anyhow!("No input data file or kcl file")), } diff --git a/kclvm/compiler/Cargo.toml b/kclvm/compiler/Cargo.toml index fc78677b3..3ddf5f9e7 100644 --- a/kclvm/compiler/Cargo.toml +++ b/kclvm/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-compiler" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/kclvm/compiler/src/codegen/error.rs b/kclvm/compiler/src/codegen/error.rs index 50cc0fb2c..1b165e80f 100644 --- a/kclvm/compiler/src/codegen/error.rs +++ b/kclvm/compiler/src/codegen/error.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use std::error; use std::fmt::{self, Debug}; diff --git a/kclvm/compiler/src/codegen/llvm/context.rs b/kclvm/compiler/src/codegen/llvm/context.rs index 53df01540..cc3964b1b 100644 --- a/kclvm/compiler/src/codegen/llvm/context.rs +++ b/kclvm/compiler/src/codegen/llvm/context.rs @@ -26,16 +26,15 @@ use kclvm_ast::walker::TypedResultWalker; use kclvm_error::*; use kclvm_runtime::{ApiFunc, MAIN_PKG_PATH, PKG_PATH_PREFIX}; use kclvm_sema::builtin; +use kclvm_sema::pkgpath_without_prefix; use kclvm_sema::plugin; use crate::codegen::abi::Align; -use crate::codegen::{error as kcl_error, EmitOptions, INNER_LEVEL}; +use crate::codegen::{error as kcl_error, EmitOptions}; use crate::codegen::{ - traits::*, ENTRY_NAME, GLOBAL_VAL_ALIGNMENT, KCL_CONTEXT_VAR_NAME, MODULE_NAME, - PKG_INIT_FUNCTION_SUFFIX, + traits::*, ENTRY_NAME, GLOBAL_VAL_ALIGNMENT, MODULE_NAME, PKG_INIT_FUNCTION_SUFFIX, }; use crate::codegen::{CodeGenContext, GLOBAL_LEVEL}; -use crate::pkgpath_without_prefix; use crate::value; use super::OBJECT_FILE_SUFFIX; @@ -60,7 +59,7 @@ pub type CompileResult<'a> = Result, kcl_error::KCLError>; pub struct Scope<'ctx> { /// Scalars denotes the expression statement values without attribute. pub scalars: RefCell>>, - /// schema_scalar_idxdenotes whether a schema exists in the scalar list. + /// schema_scalar_idx denotes whether a schema exists in the scalar list. pub schema_scalar_idx: RefCell, pub variables: RefCell>>, pub closures: RefCell>>, @@ -86,7 +85,7 @@ pub struct LLVMCodeGenContext<'ctx> { pub imported: RefCell>, pub local_vars: RefCell>, pub schema_stack: RefCell>, - pub lambda_stack: RefCell>, + pub lambda_stack: RefCell>, pub schema_expr_stack: RefCell>, pub pkgpath_stack: RefCell>, pub filename_stack: RefCell>, @@ -103,6 +102,7 @@ pub struct LLVMCodeGenContext<'ctx> { // No link mode pub no_link: bool, pub modules: RefCell>>>, + pub workdir: String, } impl<'ctx> CodeGenObject for BasicValueEnum<'ctx> {} @@ -353,7 +353,10 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { let i64_type = self.context.i64_type(); self.build_call( &ApiFunc::kclvm_value_Int.name(), - &[i64_type.const_int(v as u64, false).into()], + &[ + self.current_runtime_ctx_ptr(), + i64_type.const_int(v as u64, false).into(), + ], ) } @@ -362,14 +365,20 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { let f64_type = self.context.f64_type(); self.build_call( &ApiFunc::kclvm_value_Float.name(), - &[f64_type.const_float(v).into()], + &[ + self.current_runtime_ctx_ptr(), + f64_type.const_float(v).into(), + ], ) } /// Construct a string value using &str fn string_value(&self, v: &str) -> Self::Value { let string_ptr_value = self.native_global_string(v, ""); - self.build_call(&ApiFunc::kclvm_value_Str.name(), &[string_ptr_value.into()]) + self.build_call( + &ApiFunc::kclvm_value_Str.name(), + &[self.current_runtime_ctx_ptr(), string_ptr_value.into()], + ) } /// Construct a bool value @@ -377,36 +386,55 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { let i8_type = self.context.i8_type(); self.build_call( &ApiFunc::kclvm_value_Bool.name(), - &[i8_type.const_int(v as u64, false).into()], + &[ + self.current_runtime_ctx_ptr(), + i8_type.const_int(v as u64, false).into(), + ], ) } /// Construct a None value fn none_value(&self) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_None.name(), &[]) + self.build_call( + &ApiFunc::kclvm_value_None.name(), + &[self.current_runtime_ctx_ptr()], + ) } /// Construct a Undefined value fn undefined_value(&self) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_Undefined.name(), &[]) + self.build_call( + &ApiFunc::kclvm_value_Undefined.name(), + &[self.current_runtime_ctx_ptr()], + ) } /// Construct a empty kcl list value fn list_value(&self) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_List.name(), &[]) + self.build_call( + &ApiFunc::kclvm_value_List.name(), + &[self.current_runtime_ctx_ptr()], + ) } /// Construct a list value with `n` elements fn list_values(&self, values: &[Self::Value]) -> Self::Value { + let mut args = vec![self.current_runtime_ctx_ptr()]; + for value in values { + args.push(*value); + } self.build_call( &format!("{}{}", ApiFunc::kclvm_value_List.name(), values.len()), - values, + args.as_slice(), ) } /// Construct a empty kcl dict value. fn dict_value(&self) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_Dict.name(), &[]) + self.build_call( + &ApiFunc::kclvm_value_Dict.name(), + &[self.current_runtime_ctx_ptr()], + ) } /// Construct a unit value @@ -417,6 +445,7 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { self.build_call( &ApiFunc::kclvm_value_Unit.name(), &[ + self.current_runtime_ctx_ptr(), f64_type.const_float(v).into(), i64_type.const_int(raw as u64, false).into(), unit_native_str.into(), @@ -434,7 +463,7 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { ); self.build_call( &ApiFunc::kclvm_value_Function_using_ptr.name(), - &[lambda_fn_ptr, func_name_ptr], + &[self.current_runtime_ctx_ptr(), lambda_fn_ptr, func_name_ptr], ) } /// Construct a closure function value with the closure variable. @@ -449,13 +478,20 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { ); self.build_call( &ApiFunc::kclvm_value_Function.name(), - &[fn_ptr, closure, func_name_ptr, self.native_i8_zero().into()], + &[ + self.current_runtime_ctx_ptr(), + fn_ptr, + closure, + func_name_ptr, + self.native_i8_zero().into(), + ], ) } /// Construct a schema function value using native functions. fn struct_function_value( &self, functions: &[FunctionValue<'ctx>], + attr_functions: &HashMap>>, runtime_type: &str, ) -> Self::Value { if functions.is_empty() { @@ -482,12 +518,18 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { .into() }; let runtime_type_native_str = self.native_global_string_value(runtime_type); + let attr_map = self.dict_value(); + for attr in attr_functions.keys() { + self.dict_insert_override_item(attr_map, attr, self.undefined_value()) + } self.builder .build_call( self.lookup_function(&ApiFunc::kclvm_value_schema_function.name()), &[ + self.current_runtime_ctx_ptr().into(), schema_body_fn_ptr.into(), check_block_fn_ptr.into(), + attr_map.into(), runtime_type_native_str.into(), ], runtime_type, @@ -531,126 +573,192 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { global_var.as_pointer_value().into() } /// Get the global runtime context pointer. - fn global_ctx_ptr(&self) -> Self::Value { - if self.no_link { - self.build_call(&ApiFunc::kclvm_context_current.name(), &[]) - } else { - let ctx_ptr = self - .module - .get_global(KCL_CONTEXT_VAR_NAME) - .expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG) - .as_pointer_value(); - self.builder.build_load(ctx_ptr, "") - } + fn current_runtime_ctx_ptr(&self) -> Self::Value { + self.builder + .get_insert_block() + .unwrap() + .get_parent() + .unwrap() + .get_first_param() + .expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG) } } impl<'ctx> ValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// lhs + rhs fn add(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_add.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_add.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs - rhs fn sub(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_sub.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_sub.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs * rhs fn mul(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_mul.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_mul.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs / rhs fn div(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_div.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_div.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs // rhs fn floor_div(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_floor_div.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_floor_div.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs % rhs fn r#mod(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_mod.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_mod.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs ** rhs fn pow(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_pow.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_pow.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs << rhs fn bit_lshift(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_bit_lshift.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_bit_lshift.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs >> rhs fn bit_rshift(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_bit_rshift.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_bit_rshift.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs & rhs fn bit_and(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_bit_and.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_bit_and.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs | rhs fn bit_or(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_bit_or.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_bit_or.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs ^ rhs fn bit_xor(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_op_bit_xor.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_op_bit_xor.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs and rhs fn logic_and(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_logic_and.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_logic_and.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs or rhs fn logic_or(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_logic_or.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_logic_or.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs == rhs fn cmp_equal_to(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_cmp_equal_to.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_cmp_equal_to.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs != rhs fn cmp_not_equal_to(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_cmp_not_equal_to.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_cmp_not_equal_to.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs > rhs fn cmp_greater_than(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_cmp_greater_than.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_cmp_greater_than.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs >= rhs fn cmp_greater_than_or_equal(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { self.build_call( &ApiFunc::kclvm_value_cmp_greater_than_or_equal.name(), - &[lhs, rhs], + &[self.current_runtime_ctx_ptr(), lhs, rhs], ) } /// lhs < rhs fn cmp_less_than(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_cmp_less_than.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_cmp_less_than.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs <= rhs fn cmp_less_than_or_equal(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { self.build_call( &ApiFunc::kclvm_value_cmp_less_than_or_equal.name(), - &[lhs, rhs], + &[self.current_runtime_ctx_ptr(), lhs, rhs], ) } /// lhs as rhs fn r#as(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_as.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_as.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs is rhs fn is(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_is.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_is.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs is not rhs fn is_not(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_is_not.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_is_not.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs in rhs fn r#in(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_in.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_in.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } /// lhs not in rhs fn not_in(&self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_not_in.name(), &[lhs, rhs]) + self.build_call( + &ApiFunc::kclvm_value_not_in.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ) } } @@ -658,7 +766,10 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// Value subscript a[b] #[inline] fn value_subscript(&self, value: Self::Value, item: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_subscr.name(), &[value, item]) + self.build_call( + &ApiFunc::kclvm_value_subscr.name(), + &[self.current_runtime_ctx_ptr(), value, item], + ) } /// Value is truth function, return i1 value. fn value_is_truthy(&self, value: Self::Value) -> Self::Value { @@ -672,17 +783,26 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// Value deep copy #[inline] fn value_deep_copy(&self, value: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_value_deep_copy.name(), &[value]) + self.build_call( + &ApiFunc::kclvm_value_deep_copy.name(), + &[self.current_runtime_ctx_ptr(), value], + ) } /// value_union unions two collection elements. #[inline] fn value_union(&self, lhs: Self::Value, rhs: Self::Value) { - self.build_void_call(&ApiFunc::kclvm_value_union.name(), &[lhs, rhs]); + self.build_void_call( + &ApiFunc::kclvm_value_union.name(), + &[self.current_runtime_ctx_ptr(), lhs, rhs], + ); } // List get the item using the index. #[inline] fn list_get(&self, list: Self::Value, index: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_list_get.name(), &[list, index]) + self.build_call( + &ApiFunc::kclvm_list_get.name(), + &[self.current_runtime_ctx_ptr(), list, index], + ) } // List set the item using the index. #[inline] @@ -700,7 +820,7 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { ) -> Self::Value { self.build_call( &ApiFunc::kclvm_value_slice.name(), - &[list, start, stop, step], + &[self.current_runtime_ctx_ptr(), list, start, stop, step], ) } /// Append a item into the list. @@ -716,12 +836,18 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// Runtime list value pop #[inline] fn list_pop(&self, list: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_list_pop.name(), &[list]) + self.build_call( + &ApiFunc::kclvm_list_pop.name(), + &[self.current_runtime_ctx_ptr(), list], + ) } /// Runtime list pop the first value #[inline] fn list_pop_first(&self, list: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_list_pop_first.name(), &[list]) + self.build_call( + &ApiFunc::kclvm_list_pop_first.name(), + &[self.current_runtime_ctx_ptr(), list], + ) } /// List clear value. #[inline] @@ -731,12 +857,18 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// Return number of occurrences of the list value. #[inline] fn list_count(&self, list: Self::Value, item: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_list_count.name(), &[list, item]) + self.build_call( + &ApiFunc::kclvm_list_count.name(), + &[self.current_runtime_ctx_ptr(), list, item], + ) } /// Return first index of the list value. Panic if the value is not present. #[inline] fn list_find(&self, list: Self::Value, item: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_list_find.name(), &[list, item]) + self.build_call( + &ApiFunc::kclvm_list_find.name(), + &[self.current_runtime_ctx_ptr(), list, item], + ) } /// Insert object before index of the list value. #[inline] @@ -751,27 +883,42 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { /// Dict get the value of the key. #[inline] fn dict_get(&self, dict: Self::Value, key: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_dict_get_value.name(), &[dict, key]) + self.build_call( + &ApiFunc::kclvm_dict_get_value.name(), + &[self.current_runtime_ctx_ptr(), dict, key], + ) } /// Dict set the value of the key. #[inline] fn dict_set(&self, dict: Self::Value, key: Self::Value, value: Self::Value) { - self.build_void_call(&ApiFunc::kclvm_dict_set_value.name(), &[dict, key, value]) + self.build_void_call( + &ApiFunc::kclvm_dict_set_value.name(), + &[self.current_runtime_ctx_ptr(), dict, key, value], + ) } /// Return all dict keys. #[inline] fn dict_keys(&self, dict: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_dict_keys.name(), &[dict]) + self.build_call( + &ApiFunc::kclvm_dict_keys.name(), + &[self.current_runtime_ctx_ptr(), dict], + ) } /// Return all dict values. #[inline] fn dict_values(&self, dict: Self::Value) -> Self::Value { - self.build_call(&ApiFunc::kclvm_dict_values.name(), &[dict]) + self.build_call( + &ApiFunc::kclvm_dict_values.name(), + &[self.current_runtime_ctx_ptr(), dict], + ) } /// Dict clear value. #[inline] fn dict_clear(&self, dict: Self::Value) { - self.build_void_call(&ApiFunc::kclvm_dict_insert_value.name(), &[dict]) + self.build_void_call( + &ApiFunc::kclvm_dict_insert_value.name(), + &[self.current_runtime_ctx_ptr(), dict], + ) } /// Dict pop the value of the key. #[inline] @@ -799,7 +946,14 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { let insert_index = self.native_int_value(insert_index); self.build_void_call( &ApiFunc::kclvm_dict_insert.name(), - &[dict, name, value, op, insert_index], + &[ + self.current_runtime_ctx_ptr(), + dict, + name, + value, + op, + insert_index, + ], ); } @@ -818,7 +972,14 @@ impl<'ctx> DerivedValueCalculationMethods for LLVMCodeGenContext<'ctx> { let insert_index = self.native_int_value(insert_index); self.build_void_call( &ApiFunc::kclvm_dict_insert_value.name(), - &[dict, key, value, op, insert_index], + &[ + self.current_runtime_ctx_ptr(), + dict, + key, + value, + op, + insert_index, + ], ); } } @@ -1061,6 +1222,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { program: &'ctx ast::Program, import_names: IndexMap>, no_link: bool, + workdir: String, ) -> LLVMCodeGenContext<'ctx> { LLVMCodeGenContext { context, @@ -1072,7 +1234,8 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { imported: RefCell::new(HashSet::new()), local_vars: RefCell::new(HashSet::new()), schema_stack: RefCell::new(vec![]), - lambda_stack: RefCell::new(vec![false]), + // 0 denotes the top global main function lambda. + lambda_stack: RefCell::new(vec![0]), schema_expr_stack: RefCell::new(vec![]), pkgpath_stack: RefCell::new(vec![String::from(MAIN_PKG_PATH)]), filename_stack: RefCell::new(vec![String::from("")]), @@ -1086,6 +1249,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { import_names, no_link, modules: RefCell::new(HashMap::new()), + workdir, } } @@ -1159,6 +1323,22 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.pkgpath_stack.borrow_mut().push(pkgpath.clone()); } } + // Set the kcl module path to the runtime context + self.build_void_call( + &ApiFunc::kclvm_context_set_kcl_modpath.name(), + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(&self.program.root), + ], + ); + // Set the kcl workdir to the runtime context + self.build_void_call( + &ApiFunc::kclvm_context_set_kcl_workdir.name(), + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(&self.workdir), + ], + ); if !self.import_names.is_empty() { let import_names = self.dict_value(); for (k, v) in &self.import_names { @@ -1177,18 +1357,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { &[ctx_value, import_names], ); } - // Store the runtime context to global - if !self.no_link { - let global_ctx = self.module.add_global( - context_ptr_type, - Some(AddressSpace::default()), - KCL_CONTEXT_VAR_NAME, - ); - global_ctx.set_alignment(GLOBAL_VAL_ALIGNMENT); - global_ctx.set_initializer(&context_ptr_type.const_zero()); - self.builder - .build_store(global_ctx.as_pointer_value(), ctx_value); - } + // Main package if self.no_link && !has_main_pkg { // When compiling a pkgpath separately, only one pkgpath is required in the AST Program assert!(self.program.pkgs.len() == 1); @@ -1198,24 +1367,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.pkgpath_stack.borrow_mut().push(pkgpath.clone()); // Init all builtin functions. self.init_scope(pkgpath.as_str()); - // Compile the ast module in the pkgpath. - for ast_module in modules { - { - self.filename_stack - .borrow_mut() - .push(ast_module.filename.clone()); - } - self.compile_module_import_and_types(ast_module) - } - for ast_module in modules { - { - self.filename_stack - .borrow_mut() - .push(ast_module.filename.clone()); - } - self.walk_stmts_except_import(&ast_module.body) - .expect(kcl_error::COMPILE_ERROR_MSG); - } + self.compile_ast_modules(modules); } self.ret_void(); } else { @@ -1226,16 +1378,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { .pkgs .get(MAIN_PKG_PATH) .expect(kcl_error::INTERNAL_ERROR_MSG); - // Compile the AST Program to LLVM IR - for ast_module in main_pkg_modules { - { - self.filename_stack - .borrow_mut() - .push(ast_module.filename.clone()); - } - self.walk_module(ast_module) - .expect(kcl_error::COMPILE_ERROR_MSG); - } + self.compile_ast_modules(main_pkg_modules); // Get the JSON string including all global variables let json_str_value = self.globals_to_json_str(); // Build a return in the current block @@ -1265,6 +1408,51 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { Ok(()) } + /// Compile AST Modules, which requires traversing three times. + /// 1. scan all possible global variables and allocate undefined values to global pointers. + /// 2. build all user-defined schema/rule types. + /// 3. generate all LLVM IR codes for the third time. + fn compile_ast_modules(&self, modules: &'ctx [ast::Module]) { + // Scan global variables + for ast_module in modules { + { + self.filename_stack + .borrow_mut() + .push(ast_module.filename.clone()); + } + // Pre define global variables with undefined values + self.predefine_global_vars(ast_module); + { + self.filename_stack.borrow_mut().pop(); + } + } + // Scan global types + for ast_module in modules { + { + self.filename_stack + .borrow_mut() + .push(ast_module.filename.clone()); + } + self.compile_module_import_and_types(ast_module); + { + self.filename_stack.borrow_mut().pop(); + } + } + // Compile the ast module in the pkgpath. + for ast_module in modules { + { + self.filename_stack + .borrow_mut() + .push(ast_module.filename.clone()); + } + self.walk_module(ast_module) + .expect(kcl_error::COMPILE_ERROR_MSG); + { + self.filename_stack.borrow_mut().pop(); + } + } + } + /// Build LLVM module to a `.o` object file. /// /// TODO: WASM and cross platform build. @@ -1398,7 +1586,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let mut pkg_scopes = self.pkg_scopes.borrow_mut(); let scopes = pkg_scopes .get_mut(¤t_pkgpath) - .expect(&format!("pkgpath {} is not found", current_pkgpath)); + .unwrap_or_else(|| panic!("pkgpath {} is not found", current_pkgpath)); if let Some(last) = scopes.last_mut() { let mut scalars = last.scalars.borrow_mut(); // TODO: To avoid conflicts, only the last schema scalar expressions are allowed. @@ -1447,12 +1635,12 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { pub fn store_variable_in_current_scope(&self, name: &str, value: BasicValueEnum<'ctx>) -> bool { // Find argument name in the scope let current_pkgpath = self.current_pkgpath(); - let mut pkg_scopes = self.pkg_scopes.borrow_mut(); + let pkg_scopes = self.pkg_scopes.borrow(); let msg = format!("pkgpath {} is not found", current_pkgpath); - let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); + let scopes = pkg_scopes.get(¤t_pkgpath).expect(&msg); let index = scopes.len() - 1; - let variables_mut = scopes[index].variables.borrow_mut(); - if let Some(var) = variables_mut.get(&name.to_string()) { + let variables = scopes[index].variables.borrow(); + if let Some(var) = variables.get(&name.to_string()) { self.builder.build_store(*var, value); return true; } @@ -1463,13 +1651,13 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { pub fn store_variable(&self, name: &str, value: BasicValueEnum<'ctx>) -> bool { // Find argument name in the scope let current_pkgpath = self.current_pkgpath(); - let mut pkg_scopes = self.pkg_scopes.borrow_mut(); + let pkg_scopes = self.pkg_scopes.borrow(); let msg = format!("pkgpath {} is not found", current_pkgpath); - let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); + let scopes = pkg_scopes.get(¤t_pkgpath).expect(&msg); for i in 0..scopes.len() { let index = scopes.len() - i - 1; - let variables_mut = scopes[index].variables.borrow_mut(); - if let Some(var) = variables_mut.get(&name.to_string()) { + let variables = scopes[index].variables.borrow(); + if let Some(var) = variables.get(&name.to_string()) { self.builder.build_store(*var, value); return true; } @@ -1481,14 +1669,14 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { pub fn resolve_variable(&self, name: &str) -> bool { // Find argument name in the scope let current_pkgpath = self.current_pkgpath(); - let mut pkg_scopes = self.pkg_scopes.borrow_mut(); + let pkg_scopes = self.pkg_scopes.borrow(); let msg = format!("pkgpath {} is not found", current_pkgpath); - let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); + let scopes = pkg_scopes.get(¤t_pkgpath).expect(&msg); let mut existed = false; for i in 0..scopes.len() { let index = scopes.len() - i - 1; - let variables_mut = scopes[index].variables.borrow_mut(); - if variables_mut.get(&name.to_string()).is_some() { + let variables = scopes[index].variables.borrow(); + if variables.get(&name.to_string()).is_some() { existed = true; break; } @@ -1542,8 +1730,8 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); let mut existed = false; if let Some(last) = scopes.last_mut() { - let variables_mut = last.variables.borrow_mut(); - if let Some(var) = variables_mut.get(&name.to_string()) { + let variables = last.variables.borrow(); + if let Some(var) = variables.get(&name.to_string()) { self.builder.build_store(*var, value); existed = true; } @@ -1604,7 +1792,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.builder.position_at_end(then_block); let target_attr = self .target_vars - .borrow_mut() + .borrow() .last() .expect(kcl_error::INTERNAL_ERROR_MSG) .clone(); @@ -1631,6 +1819,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.build_call( &ApiFunc::kclvm_schema_get_value.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, string_ptr_value, config, @@ -1663,7 +1852,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { /// Get the variable value named `name` from the scope named `pkgpath`, return Err when not found pub fn get_variable_in_pkgpath(&self, name: &str, pkgpath: &str) -> CompileResult<'ctx> { - let pkg_scopes = self.pkg_scopes.borrow_mut(); + let pkg_scopes = self.pkg_scopes.borrow(); let pkgpath = if !pkgpath.starts_with(kclvm_runtime::PKG_PATH_PREFIX) && pkgpath != MAIN_PKG_PATH { format!("{}{}", kclvm_runtime::PKG_PATH_PREFIX, pkgpath) @@ -1674,6 +1863,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { message: format!("name '{}' is not defined", name), ty: kcl_error::KCLErrorType::Compile, }); + let is_in_schema = self.schema_stack.borrow().len() > 0; // System module if builtin::STANDARD_SYSTEM_MODULE_NAMES_WITH_AT.contains(&pkgpath.as_str()) { let pkgpath = &pkgpath[1..]; @@ -1707,6 +1897,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.build_call( &ApiFunc::kclvm_value_Function.name(), &[ + self.current_runtime_ctx_ptr(), lambda_fn_ptr, none_value, func_name_ptr, @@ -1729,37 +1920,54 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let none_value = self.none_value(); return Ok(self.build_call( &ApiFunc::kclvm_value_Function.name(), - &[null_fn_ptr, none_value, name, self.native_i8(1).into()], + &[ + self.current_runtime_ctx_ptr(), + null_fn_ptr, + none_value, + name, + self.native_i8(1).into(), + ], )); // User pkgpath } else { + // Global or local variables. let scopes = pkg_scopes .get(&pkgpath) .unwrap_or_else(|| panic!("package {} is not found", pkgpath)); // Scopes 0 is builtin scope, Scopes 1 is the global scope, Scopes 2~ are the local scopes let scopes_len = scopes.len(); - let last_scopes = scopes.last().expect(kcl_error::INTERNAL_ERROR_MSG); - let mut closures_mut = last_scopes.closures.borrow_mut(); for i in 0..scopes_len { let index = scopes_len - i - 1; - let variables_mut = scopes[index].variables.borrow_mut(); - if let Some(var) = variables_mut.get(&name.to_string()) { - // Closure vars, 2 denotes the builtin scope and the global scope + let variables = scopes[index].variables.borrow(); + if let Some(var) = variables.get(&name.to_string()) { + // Closure vars, 2 denotes the builtin scope and the global scope, here is a closure scope. let value = if i >= 1 && i < scopes_len - 2 { - closures_mut.insert(name.to_string(), *var); - let variables = last_scopes.variables.borrow(); - let ptr = variables.get(value::LAMBDA_CLOSURE); - // Lambda closure - match ptr { - Some(ptr) => { - let closure_map = self.builder.build_load(*ptr, ""); - let string_ptr_value = self.native_global_string(name, "").into(); - self.build_call( - &ApiFunc::kclvm_dict_get_value.name(), - &[closure_map, string_ptr_value], - ) + let last_lambda_scope = self.last_lambda_scope(); + // Local scope variable + if index >= last_lambda_scope { + self.builder.build_load(*var, name) + } else { + // Outer lamba closure + let variables = scopes[last_lambda_scope].variables.borrow(); + let ptr = variables.get(value::LAMBDA_CLOSURE); + // Lambda closure + match ptr { + Some(ptr) => { + let closure_map = self.builder.build_load(*ptr, ""); + let string_ptr_value = + self.native_global_string(name, "").into(); + // Not a closure, mapbe a local variale + self.build_call( + &ApiFunc::kclvm_dict_get_value.name(), + &[ + self.current_runtime_ctx_ptr(), + closure_map, + string_ptr_value, + ], + ) + } + None => self.builder.build_load(*var, name), } - None => self.builder.build_load(*var, name), } } else { self.builder.build_load(*var, name) @@ -1771,17 +1979,14 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { match result { Ok(_) => result, Err(ref err) => { - let is_in_schema = self.schema_stack.borrow().len() > 0; if !is_in_schema { let mut handler = self.handler.borrow_mut(); - handler.add_compile_error( - &err.message, - Position { - filename: self.current_filename(), - line: *self.current_line.borrow(), - column: None, - }, - ); + let pos = Position { + filename: self.current_filename(), + line: *self.current_line.borrow(), + column: None, + }; + handler.add_compile_error(&err.message, (pos.clone(), pos)); handler.abort_if_any_errors() } result @@ -1812,9 +2017,9 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { // User module external variable let external_var_name = format!("${}.${}", pkgpath_without_prefix!(ext_pkgpath), name); let current_pkgpath = self.current_pkgpath(); - let modules = self.modules.borrow_mut(); + let modules = self.modules.borrow(); let msg = format!("pkgpath {} is not found", current_pkgpath); - let module = modules.get(¤t_pkgpath).expect(&msg).borrow_mut(); + let module = modules.get(¤t_pkgpath).expect(&msg).borrow(); let tpe = self.value_ptr_type(); let mut global_var_maps = self.global_vars.borrow_mut(); let pkgpath = self.current_pkgpath(); @@ -1838,11 +2043,11 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { Ok(value) } - /// Get closure map in the current scope. - pub(crate) fn get_closure_map(&self) -> BasicValueEnum<'ctx> { - // Get closures in the current scope. - let closure_map = self.dict_value(); - { + /// Get closure map in the current inner scope. + pub(crate) fn get_current_inner_scope_variable_map(&self) -> BasicValueEnum<'ctx> { + let var_map = { + let last_lambda_scope = self.last_lambda_scope(); + // Get variable map in the current scope. let pkgpath = self.current_pkgpath(); let pkgpath = if !pkgpath.starts_with(PKG_PATH_PREFIX) && pkgpath != MAIN_PKG_PATH { format!("{}{}", PKG_PATH_PREFIX, pkgpath) @@ -1853,28 +2058,35 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let scopes = pkg_scopes .get(&pkgpath) .unwrap_or_else(|| panic!("package {} is not found", pkgpath)); - // Clouure variable must be inner of the global scope. - if scopes.len() > INNER_LEVEL { - let closures = scopes - .last() - .expect(kcl_error::INTERNAL_ERROR_MSG) - .closures - .borrow(); - // Curret scope vaiable. - let variables = scopes - .get(scopes.len() - INNER_LEVEL) - .expect(kcl_error::INTERNAL_ERROR_MSG) - .variables - .borrow(); - // Transverse all scope and capture closures except the builtin amd global scope. - for (key, ptr) in &*closures { - if variables.contains_key(key) { - let value = self.builder.build_load(*ptr, ""); - self.dict_insert_override_item(closure_map, key.as_str(), value); + let current_scope = scopes.len() - 1; + // Get last closure map. + let var_map = if current_scope >= last_lambda_scope && last_lambda_scope > 0 { + let variables = scopes[last_lambda_scope].variables.borrow(); + let ptr = variables.get(value::LAMBDA_CLOSURE); + let var_map = match ptr { + Some(ptr) => self.builder.build_load(*ptr, ""), + None => self.dict_value(), + }; + // Get variable map including schema in the current scope. + for i in last_lambda_scope..current_scope + 1 { + let variables = scopes + .get(i) + .expect(kcl_error::INTERNAL_ERROR_MSG) + .variables + .borrow(); + for (key, ptr) in &*variables { + if key != value::LAMBDA_CLOSURE { + let value = self.builder.build_load(*ptr, ""); + self.dict_insert_override_item(var_map, key.as_str(), value); + } } - } // Curret scope vaiable. - } - } + } + var_map + } else { + self.dict_value() + }; + var_map + }; // Capture schema `self` closure. let is_in_schema = self.schema_stack.borrow().len() > 0; if is_in_schema { @@ -1882,10 +2094,41 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let value = self .get_variable(shcmea_closure_name) .expect(kcl_error::INTERNAL_ERROR_MSG); - self.dict_insert_override_item(closure_map, shcmea_closure_name, value); + self.dict_insert_override_item(var_map, shcmea_closure_name, value); } } - closure_map + var_map + } + + /// Push a lambda definition scope into the lambda stack + #[inline] + pub fn push_lambda(&self, scope: usize) { + self.lambda_stack.borrow_mut().push(scope); + } + + /// Pop a lambda definition scope. + #[inline] + pub fn pop_lambda(&self) { + self.lambda_stack.borrow_mut().pop(); + } + + #[inline] + pub fn is_in_lambda(&self) -> bool { + *self + .lambda_stack + .borrow() + .last() + .expect(kcl_error::INTERNAL_ERROR_MSG) + > 0 + } + + #[inline] + pub fn last_lambda_scope(&self) -> usize { + *self + .lambda_stack + .borrow() + .last() + .expect(kcl_error::INTERNAL_ERROR_MSG) } /// Push a function call frame into the function stack @@ -1913,26 +2156,29 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { /// Plan globals to a json string pub fn globals_to_json_str(&self) -> BasicValueEnum<'ctx> { let current_pkgpath = self.current_pkgpath(); - let mut pkg_scopes = self.pkg_scopes.borrow_mut(); + let pkg_scopes = self.pkg_scopes.borrow(); let scopes = pkg_scopes - .get_mut(¤t_pkgpath) - .expect(&format!("pkgpath {} is not found", current_pkgpath)); + .get(¤t_pkgpath) + .unwrap_or_else(|| panic!("pkgpath {} is not found", current_pkgpath)); // The global scope. let scope = scopes.last().expect(kcl_error::INTERNAL_ERROR_MSG); let scalars = scope.scalars.borrow(); let globals = scope.variables.borrow(); // Construct a plan object. let global_dict = self.dict_value(); + // Plan empty dict result. + if scalars.is_empty() && globals.is_empty() { + return self.build_call( + &ApiFunc::kclvm_value_plan_to_json.name(), + &[self.current_runtime_ctx_ptr(), global_dict], + ); + } // Deal scalars for scalar in scalars.iter() { - self.dict_safe_insert(global_dict, SCALAR_KEY, scalar.clone(), 0, -1); + self.dict_safe_insert(global_dict, SCALAR_KEY, *scalar, 0, -1); } // Deal global variables for (name, ptr) in globals.iter() { - // Omit private variables and function variables - if name.starts_with(kclvm_runtime::KCL_PRIVATE_VAR_PREFIX) { - continue; - } let value = self.builder.build_load(*ptr, ""); let value_dict = self.dict_value(); self.dict_safe_insert(value_dict, name.as_str(), value, 0, -1); @@ -1941,10 +2187,13 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { // Plan result to json string. self.build_call( &ApiFunc::kclvm_value_plan_to_json.name(), - &[self.dict_get( - global_dict, - self.native_global_string(SCALAR_KEY, "").into(), - )], + &[ + self.current_runtime_ctx_ptr(), + self.dict_get( + global_dict, + self.native_global_string(SCALAR_KEY, "").into(), + ), + ], ) } @@ -1963,7 +2212,14 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let insert_index = self.native_int_value(insert_index); self.build_void_call( &ApiFunc::kclvm_dict_safe_insert.name(), - &[dict, name, value, op, insert_index], + &[ + self.current_runtime_ctx_ptr(), + dict, + name, + value, + op, + insert_index, + ], ); } @@ -1983,7 +2239,14 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let insert_index = self.native_int_value(insert_index); self.build_void_call( &ApiFunc::kclvm_dict_merge.name(), - &[dict, name, value, op, insert_index], + &[ + self.current_runtime_ctx_ptr(), + dict, + name, + value, + op, + insert_index, + ], ); } diff --git a/kclvm/compiler/src/codegen/llvm/emit.rs b/kclvm/compiler/src/codegen/llvm/emit.rs index 90397abd0..6b6aa9681 100644 --- a/kclvm/compiler/src/codegen/llvm/emit.rs +++ b/kclvm/compiler/src/codegen/llvm/emit.rs @@ -23,27 +23,37 @@ fn load_runtime(context: &'_ Context) -> Module<'_> { /// Generate LLVM IR of KCL ast module. pub fn emit_code( program: &ast::Program, + workdir: String, import_names: IndexMap>, - opt: &EmitOptions, + opts: &EmitOptions, ) -> Result<(), Box> { // Init LLVM targets LLVM_INIT.get_or_init(|| { - // TODO: linux arm and WASM target. + // TODO: WASM target. #[cfg(target_os = "linux")] inkwell::targets::Target::initialize_x86(&Default::default()); + #[cfg(all(target_os = "linux", target_arch = "aarch64"))] + inkwell::targets::Target::initialize_aarch64(&Default::default()); #[cfg(not(target_os = "linux"))] inkwell::targets::Target::initialize_all(&Default::default()); }); // Create a LLVM context let context = Context::create(); // Create a LLVM module using an exist LLVM bitcode file - let module = if let Some(path) = &opt.from_path { + let module = if let Some(path) = &opts.from_path { Module::parse_bitcode_from_path(std::path::Path::new(path), &context).unwrap() } else { load_runtime(&context) }; // Create a KCL LLVM code generator using the KCL AST and the LLVM module - let ctx = LLVMCodeGenContext::new(&context, module, program, import_names, opt.no_link); + let ctx = LLVMCodeGenContext::new( + &context, + module, + program, + import_names, + opts.no_link, + workdir, + ); // Generate user KCL code LLVM IR - crate::codegen::emit_code(ctx, opt) + crate::codegen::emit_code(ctx, opts) } diff --git a/kclvm/compiler/src/codegen/llvm/module.rs b/kclvm/compiler/src/codegen/llvm/module.rs index b1339374d..2f16de940 100644 --- a/kclvm/compiler/src/codegen/llvm/module.rs +++ b/kclvm/compiler/src/codegen/llvm/module.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. use kclvm_ast::ast; use kclvm_ast::walker::TypedResultWalker; @@ -9,7 +9,6 @@ use std::str; impl<'ctx> LLVMCodeGenContext<'ctx> { pub fn compile_module_import_and_types(&self, module: &'ctx ast::Module) { - self.predefine_global_vars(module); for stmt in &module.body { match &stmt.node { ast::Stmt::Import(import_stmt) => { @@ -17,11 +16,13 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { .expect(kcl_error::COMPILE_ERROR_MSG); } ast::Stmt::Schema(schema_stmt) => { + // Pre define global types with undefined values self.predefine_global_types(&schema_stmt.name.node); self.walk_schema_stmt(schema_stmt) .expect(kcl_error::COMPILE_ERROR_MSG); } ast::Stmt::Rule(rule_stmt) => { + // Pre define global types with undefined values self.predefine_global_types(&rule_stmt.name.node); self.walk_rule_stmt(rule_stmt) .expect(kcl_error::COMPILE_ERROR_MSG); @@ -30,6 +31,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { }; } } + pub fn predefine_global_types(&self, name: &str) { // Store or add the variable in the scope let function = self.undefined_value(); @@ -39,16 +41,38 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.add_variable(name, global_var_ptr); } } + /// Predefine all global variables. + #[inline] pub(crate) fn predefine_global_vars(&self, module: &'ctx ast::Module) { - for stmt in &module.body { - if let ast::Stmt::Assign(assign_stmt) = &stmt.node { - for target in &assign_stmt.targets { - let names = &target.node.names; + self.emit_global_vars(&module.body); + } + + fn emit_global_vars(&self, body: &'ctx [Box>]) { + for stmt in body { + match &stmt.node { + ast::Stmt::Unification(unification_stmt) => { + let names = &unification_stmt.target.node.names; if names.len() == 1 { - self.add_or_update_global_variable(&names[0], self.undefined_value()); + self.add_or_update_global_variable(&names[0].node, self.undefined_value()); + } + } + ast::Stmt::Assign(assign_stmt) => { + for target in &assign_stmt.targets { + let names = &target.node.names; + if names.len() == 1 { + self.add_or_update_global_variable( + &names[0].node, + self.undefined_value(), + ); + } } } + ast::Stmt::If(if_stmt) => { + self.emit_global_vars(&if_stmt.body); + self.emit_global_vars(&if_stmt.orelse); + } + _ => {} } } } diff --git a/kclvm/compiler/src/codegen/llvm/node.rs b/kclvm/compiler/src/codegen/llvm/node.rs index 23398cc5f..c1beeedf6 100644 --- a/kclvm/compiler/src/codegen/llvm/node.rs +++ b/kclvm/compiler/src/codegen/llvm/node.rs @@ -11,13 +11,15 @@ use inkwell::{AddressSpace, IntPredicate}; use kclvm_ast::ast::{self, CallExpr, ConfigEntry, NodeRef}; use kclvm_ast::walker::TypedResultWalker; use kclvm_runtime::{ApiFunc, PKG_PATH_PREFIX}; +use kclvm_sema::pkgpath_without_prefix; +use kclvm_sema::ty::{ANY_TYPE_STR, STR_TYPE_STR}; +use crate::check_backtrack_stop; use crate::codegen::error as kcl_error; use crate::codegen::llvm::context::BacktrackMeta; use crate::codegen::llvm::utils; use crate::codegen::traits::*; use crate::codegen::{ENTRY_NAME, GLOBAL_LEVEL, INNER_LEVEL, PKG_INIT_FUNCTION_SUFFIX}; -use crate::{check_backtrack_stop, pkgpath_without_prefix}; use super::context::{CompileResult, LLVMCodeGenContext}; use crate::value; @@ -72,19 +74,13 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { fn walk_unification_stmt(&self, unification_stmt: &'ctx ast::UnificationStmt) -> Self::Result { check_backtrack_stop!(self); self.local_vars.borrow_mut().clear(); - let name = &unification_stmt.target.node.names[0]; + let name = &unification_stmt.target.node.names[0].node; self.target_vars.borrow_mut().push(name.clone()); // The right value of the unification_stmt is a schema_expr. let value = self .walk_schema_expr(&unification_stmt.value.node) .expect(kcl_error::COMPILE_ERROR_MSG); - if self.scope_level() == GLOBAL_LEVEL - || *self - .lambda_stack - .borrow_mut() - .last() - .expect(kcl_error::INTERNAL_ERROR_MSG) - { + if self.scope_level() == GLOBAL_LEVEL || self.is_in_lambda() { if self.resolve_variable(name) { let org_value = self .walk_identifier_with_ctx( @@ -94,7 +90,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ) .expect(kcl_error::COMPILE_ERROR_MSG); let fn_name = ApiFunc::kclvm_value_op_aug_bit_or; - let value = self.build_call(&fn_name.name(), &[org_value, value]); + let value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), org_value, value], + ); // Store the identifier value self.walk_identifier_with_ctx( &unification_stmt.target.node, @@ -123,7 +122,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ) .expect(kcl_error::COMPILE_ERROR_MSG); let fn_name = ApiFunc::kclvm_value_op_bit_or; - let value = self.build_call(&fn_name.name(), &[org_value, value]); + let value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), org_value, value], + ); // Store the identifier value self.walk_identifier_with_ctx( &unification_stmt.target.node, @@ -147,19 +149,24 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { for name in &assign_stmt.targets { self.target_vars .borrow_mut() - .push(name.node.names[0].clone()); + .push(name.node.names[0].node.clone()); } // Load the right value let mut value = self .walk_expr(&assign_stmt.value) .expect(kcl_error::COMPILE_ERROR_MSG); - if let Some(type_annotation) = &assign_stmt.type_annotation { - let type_annotation = self.native_global_string_value(&type_annotation.node); + if let Some(ty) = &assign_stmt.ty { + let type_annotation = self.native_global_string_value(&ty.node.to_string()); let is_in_schema = self.schema_stack.borrow().len() > 0 || self.schema_expr_stack.borrow().len() > 0; value = self.build_call( &ApiFunc::kclvm_convert_collection_value.name(), - &[value, type_annotation, self.bool_value(is_in_schema)], + &[ + self.current_runtime_ctx_ptr(), + value, + type_annotation, + self.bool_value(is_in_schema), + ], ); } if assign_stmt.targets.len() == 1 { @@ -181,7 +188,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { check_backtrack_stop!(self); self.target_vars .borrow_mut() - .push(aug_assign_stmt.target.node.names[0].clone()); + .push(aug_assign_stmt.target.node.names[0].node.clone()); // Load the right value let right_value = self .walk_expr(&aug_assign_stmt.value) @@ -207,7 +214,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { return Err(kcl_error::KCLError::new(kcl_error::INVALID_OPERATOR_MSG)); } }; - let value = self.build_call(&fn_name.name(), &[org_value, right_value]); + let value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), org_value, right_value], + ); // Store the identifier value self.walk_identifier_with_ctx( &aug_assign_stmt.target.node, @@ -240,10 +250,13 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.string_value("") } }; - self.build_void_call(&ApiFunc::kclvm_assert.name(), &[assert_result, msg]); + self.build_void_call( + &ApiFunc::kclvm_assert.name(), + &[self.current_runtime_ctx_ptr(), assert_result, msg], + ); self.br(end_block); self.builder.position_at_end(end_block); - self.ok_result() + Ok(self.undefined_value()) } fn walk_if_stmt(&self, if_stmt: &'ctx ast::IfStmt) -> Self::Result { @@ -269,7 +282,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } fn walk_import_stmt(&self, import_stmt: &'ctx ast::ImportStmt) -> Self::Result { check_backtrack_stop!(self); - let pkgpath = import_stmt.path.as_str(); + let pkgpath = import_stmt.path.node.as_str(); { let imported = self.imported.borrow_mut(); if imported.contains(pkgpath) { @@ -283,10 +296,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { // Nothing to do on the builtin system module import because the check has been done. return self.ok_result(); } else { - let pkgpath = format!("{}{}", PKG_PATH_PREFIX, import_stmt.path); + let pkgpath = format!("{}{}", PKG_PATH_PREFIX, import_stmt.path.node); self.pkgpath_stack.borrow_mut().push(pkgpath); - let pkgpath = format!("{}{}", PKG_PATH_PREFIX, import_stmt.path); - let has_pkgpath = self.program.pkgs.contains_key(&import_stmt.path); + let pkgpath = format!("{}{}", PKG_PATH_PREFIX, import_stmt.path.node); + let has_pkgpath = self.program.pkgs.contains_key(&import_stmt.path.node); let func_before_block = if self.no_link { if has_pkgpath { let func_before_block = self.append_block(""); @@ -327,7 +340,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { for ast_module in self .program .pkgs - .get(&import_stmt.path) + .get(&import_stmt.path.node) .expect(kcl_error::INTERNAL_ERROR_MSG) { { @@ -343,7 +356,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { for ast_module in self .program .pkgs - .get(&import_stmt.path) + .get(&import_stmt.path.node) .expect(kcl_error::INTERNAL_ERROR_MSG) { { @@ -381,12 +394,12 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let fn_type = tpe.fn_type(&[self.context_ptr_type().into()], false); module.add_function(&name, fn_type, Some(Linkage::External)) }; - let ctx = self.global_ctx_ptr(); + let ctx = self.current_runtime_ctx_ptr(); let pkgpath_value = self.native_global_string_value(&name); let is_imported = self .build_call( &ApiFunc::kclvm_context_pkgpath_is_imported.name(), - &[pkgpath_value], + &[self.current_runtime_ctx_ptr(), pkgpath_value], ) .into_int_value(); let is_not_imported = self.builder.build_int_compare( @@ -443,7 +456,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder.position_at_end(block); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); utils::update_ctx_pkgpath(self, schema_pkgpath); let args = function @@ -514,7 +530,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -529,13 +545,17 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { if schema_stmt.parent_name.is_some() { self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); } self.schema_stack.borrow_mut().push(schema); add_variable(value::SCHEMA_SELF_NAME, schema_value); - self.emit_schema_left_identifiers( + self.emit_left_identifiers( &schema_stmt.body, + &schema_stmt.index_signature, cal_map, &runtime_type, false, @@ -557,12 +577,14 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.walk_decorator_with_name(&decorator.node, Some(schema_name), true) .expect(kcl_error::COMPILE_ERROR_MSG); } - // Append schema default settings + // Append schema default settings, args, kwargs and runtime type. self.build_void_call( &ApiFunc::kclvm_schema_default_settings.name(), &[ schema_value, schema_config, + args, + kwargs, self.native_global_string_value(&runtime_type), ], ); @@ -596,7 +618,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -604,7 +626,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); } // Schema Attribute optional check @@ -648,7 +673,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder.build_call( check_function, &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -667,7 +692,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .name() .as_str(), &[ - self.global_ctx_ptr(), + self.current_runtime_ctx_ptr(), list_value, dict_value, check_lambda_fn_ptr, @@ -682,6 +707,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let schema_value = self.build_call( &ApiFunc::kclvm_value_schema_with_config.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, schema_config, schema_config_meta, @@ -691,6 +717,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { record_instance, instance_pkgpath, attr_optional_mapping, + args, + kwargs, ], ); // Schema constructor function returns a schema @@ -743,16 +771,20 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_schema_value_check.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, schema_config, schema_config_meta, schema_name_native_str, index_sign_value, key_name_str_ptr.into(), - self.native_global_string(index_signature.node.key_type.node.as_str(), "") - .into(), self.native_global_string( - index_signature.node.value_type.node.as_str(), + index_signature.node.key_ty.node.to_string().as_str(), + "", + ) + .into(), + self.native_global_string( + index_signature.node.value_ty.node.to_string().as_str(), "", ) .into(), @@ -763,6 +795,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_schema_value_check.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, schema_config, schema_config_meta, @@ -800,7 +833,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -808,7 +841,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); } // Call self check function @@ -841,7 +877,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -849,7 +885,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); } self.builder.build_return(Some(&schema_value)); @@ -858,8 +897,11 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } // Build schema attr backtrack functions { - for (k, functions) in place_holder_map { - let stmt_list = body_map.get(&k).expect(kcl_error::INTERNAL_ERROR_MSG); + for (k, functions) in &place_holder_map { + if k == kclvm_runtime::CAL_MAP_INDEX_SIGNATURE { + continue; + } + let stmt_list = body_map.get(k).expect(kcl_error::INTERNAL_ERROR_MSG); let mut if_level = 0; for (attr_func, stmt) in functions.iter().zip(stmt_list) { let function = *attr_func; @@ -898,7 +940,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { add_variable(value::SCHEMA_RUNTIME_TYPE, self.string_value(&runtime_type)); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); let schema = self .schema_stack @@ -919,7 +964,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } else { if_level = 0; } - self.walk_stmt(*stmt).expect(kcl_error::COMPILE_ERROR_MSG); + self.walk_stmt(stmt).expect(kcl_error::COMPILE_ERROR_MSG); // Backtrack meta end if matches!(&stmt.node, ast::Stmt::If(..)) { *self.backtrack_meta.borrow_mut() = None @@ -933,7 +978,11 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } } } - let function = self.struct_function_value(&[function, check_function], &runtime_type); + let function = self.struct_function_value( + &[function, check_function], + &place_holder_map, + &runtime_type, + ); self.leave_scope(); self.pop_function(); self.schema_stack.borrow_mut().pop(); @@ -974,7 +1023,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder.position_at_end(block); self.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[self.native_global_string_value(filename)], + &[ + self.current_runtime_ctx_ptr(), + self.native_global_string_value(filename), + ], ); let args = function .get_nth_param(1) @@ -1037,12 +1089,13 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ); let fn_ty = self.function_type().ptr_type(AddressSpace::default()); let func_ptr_cast = self.builder.build_bitcast(func_ptr, fn_ty, ""); - self.builder + let schema_value = self + .builder .build_call( CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -1050,7 +1103,25 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ) .try_as_basic_value() .left() - .expect(kcl_error::FUNCTION_RETURN_VALUE_NOT_FOUND_MSG) + .expect(kcl_error::FUNCTION_RETURN_VALUE_NOT_FOUND_MSG); + let protocol_name_native_str = + self.native_global_string_value(&for_host_name.node.get_name()); + self.build_void_call( + &ApiFunc::kclvm_schema_value_check.name(), + &[ + self.current_runtime_ctx_ptr(), + schema_value, + schema_config, + schema_config_meta, + protocol_name_native_str, + self.undefined_value(), + self.native_global_string("", "").into(), + self.native_global_string(STR_TYPE_STR, "").into(), + self.native_global_string(ANY_TYPE_STR, "").into(), + self.native_i8(1).into(), + ], + ); + schema_value } else { schema_value }; @@ -1086,7 +1157,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder.build_call( check_function, &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -1155,7 +1226,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { CallableValue::try_from(func_ptr_cast.into_pointer_value()) .expect(kcl_error::INTERNAL_ERROR_MSG), &[ - self.global_ctx_ptr().into(), + self.current_runtime_ctx_ptr().into(), list_value.into(), dict_value.into(), ], @@ -1171,7 +1242,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder.position_at_end(func_before_block); self.pop_function(); } - let function = self.struct_function_value(&[function, check_function], &runtime_type); + let function = + self.struct_function_value(&[function, check_function], &HashMap::new(), &runtime_type); self.leave_scope(); self.pop_function(); self.schema_stack.borrow_mut().pop(); @@ -1281,14 +1353,14 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { { let mut local_vars = self.local_vars.borrow_mut(); for v in variables { - let name = &v.node.names[0]; + let name = &v.node.names[0].node; local_vars.insert(name.clone()); } } if variables.len() == 1 { // Store the target self.walk_identifier_with_ctx( - &variables.get(0).expect(kcl_error::INTERNAL_ERROR_MSG).node, + &variables.first().expect(kcl_error::INTERNAL_ERROR_MSG).node, &ast::ExprContext::Store, Some(next_value), ) @@ -1297,7 +1369,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let value = self.build_call(&ApiFunc::kclvm_iterator_cur_value.name(), &[iter_value]); // Store the target self.walk_identifier_with_ctx( - &variables.get(0).expect(kcl_error::INTERNAL_ERROR_MSG).node, + &variables.first().expect(kcl_error::INTERNAL_ERROR_MSG).node, &ast::ExprContext::Store, Some(key), ) @@ -1382,10 +1454,6 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.walk_decorator_with_name(&decorator.node, Some(name), false) .expect(kcl_error::COMPILE_ERROR_MSG); } - let value = match &schema_attr.value { - Some(value) => self.walk_expr(value).expect(kcl_error::COMPILE_ERROR_MSG), - None => self.undefined_value(), - }; let config_value = self .get_variable(value::SCHEMA_CONFIG_NAME) .expect(kcl_error::INTERNAL_ERROR_MSG); @@ -1394,28 +1462,12 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .expect(kcl_error::INTERNAL_ERROR_MSG); let string_ptr_value = self.native_global_string(name, "").into(); let type_str_ptr_value = self - .native_global_string(&schema_attr.type_str.node, "") + .native_global_string(&schema_attr.ty.node.to_string(), "") .into(); self.build_void_call( &ApiFunc::kclvm_config_attr_map.name(), &[schema_value, string_ptr_value, type_str_ptr_value], ); - if let Some(op) = &schema_attr.op { - match op { - // Union - ast::BinOrAugOp::Aug(ast::AugOp::BitOr) => { - let org_value = self.build_call( - &ApiFunc::kclvm_dict_get_value.name(), - &[schema_value, string_ptr_value], - ); - let fn_name = ApiFunc::kclvm_value_op_bit_or; - let value = self.build_call(&fn_name.name(), &[org_value, value]); - self.dict_merge(schema_value, name, value, 1, -1); - } - // Assign - _ => self.dict_merge(schema_value, name, value, 1, -1), - } - } let has_key = self .build_call( &ApiFunc::kclvm_dict_has_value.name(), @@ -1427,13 +1479,69 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .build_int_compare(IntPredicate::NE, has_key, self.native_i8_zero(), ""); let then_block = self.append_block(""); let else_block = self.append_block(""); + let end_block = self.append_block(""); self.builder .build_conditional_branch(has_key, then_block, else_block); self.builder.position_at_end(then_block); let config_attr_value = self.build_call( &ApiFunc::kclvm_dict_get_entry.name(), - &[config_value, string_ptr_value], + &[ + self.current_runtime_ctx_ptr(), + config_value, + string_ptr_value, + ], + ); + // If the attribute operator is not `=`, eval the schema attribute value. + // if is_not_override: + let is_override_attr = self + .build_call( + &ApiFunc::kclvm_dict_is_override_attr.name(), + &[config_value, string_ptr_value], + ) + .into_int_value(); + let is_not_override_attr = self.builder.build_int_compare( + IntPredicate::EQ, + is_override_attr, + self.native_i8_zero(), + "", + ); + let is_not_override_then_block = self.append_block(""); + let is_not_override_else_block = self.append_block(""); + self.builder.build_conditional_branch( + is_not_override_attr, + is_not_override_then_block, + is_not_override_else_block, ); + self.builder.position_at_end(is_not_override_then_block); + let value = match &schema_attr.value { + Some(value) => self.walk_expr(value).expect(kcl_error::COMPILE_ERROR_MSG), + None => self.undefined_value(), + }; + if let Some(op) = &schema_attr.op { + match op { + // Union + ast::AugOp::BitOr => { + let org_value = self.build_call( + &ApiFunc::kclvm_dict_get_value.name(), + &[ + self.current_runtime_ctx_ptr(), + schema_value, + string_ptr_value, + ], + ); + let fn_name = ApiFunc::kclvm_value_op_bit_or; + let value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), org_value, value], + ); + self.dict_merge(schema_value, name, value, 1, -1); + } + // Assign + _ => self.dict_merge(schema_value, name, value, 1, -1), + } + } + self.br(is_not_override_else_block); + self.builder.position_at_end(is_not_override_else_block); self.value_union(schema_value, config_attr_value); let cal_map = self .get_variable(value::SCHEMA_CAL_MAP) @@ -1447,6 +1555,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_schema_backtrack_cache.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, backtrack_cache, cal_map, @@ -1467,8 +1576,38 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } } } - self.br(else_block); + self.br(end_block); self.builder.position_at_end(else_block); + // Lazy eval for the schema attribute. + let value = match &schema_attr.value { + Some(value) => self.walk_expr(value).expect(kcl_error::COMPILE_ERROR_MSG), + None => self.undefined_value(), + }; + if let Some(op) = &schema_attr.op { + match op { + // Union + ast::AugOp::BitOr => { + let org_value = self.build_call( + &ApiFunc::kclvm_dict_get_value.name(), + &[ + self.current_runtime_ctx_ptr(), + schema_value, + string_ptr_value, + ], + ); + let fn_name = ApiFunc::kclvm_value_op_bit_or; + let value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), org_value, value], + ); + self.dict_merge(schema_value, name, value, 1, -1); + } + // Assign + _ => self.dict_merge(schema_value, name, value, 1, -1), + } + } + self.br(end_block); + self.builder.position_at_end(end_block); Ok(schema_value) } @@ -1522,16 +1661,13 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ast::UnaryOp::Invert => ApiFunc::kclvm_value_unary_not, ast::UnaryOp::Not => ApiFunc::kclvm_value_unary_l_not, }; - Ok(self.build_call(&fn_name.name(), &[value])) + Ok(self.build_call(&fn_name.name(), &[self.current_runtime_ctx_ptr(), value])) } fn walk_binary_expr(&self, binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { check_backtrack_stop!(self); - let is_logic_op = matches!( - binary_expr.op, - ast::BinOrCmpOp::Bin(ast::BinOp::And) | ast::BinOrCmpOp::Bin(ast::BinOp::Or) - ); - let is_membership_as_op = matches!(binary_expr.op, ast::BinOrCmpOp::Bin(ast::BinOp::As)); + let is_logic_op = matches!(binary_expr.op, ast::BinOp::And | ast::BinOp::Or); + let is_membership_as_op = matches!(binary_expr.op, ast::BinOp::As); if !is_logic_op { let left_value = self .walk_expr(&binary_expr.left) @@ -1539,7 +1675,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let right_value = if is_membership_as_op { match &binary_expr.right.node { ast::Expr::Identifier(id) => { - let name = id.names.join("."); + let name = id.get_names().join("."); self.string_value(&name) } _ => self.none_value(), @@ -1549,50 +1685,25 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .expect(kcl_error::COMPILE_ERROR_MSG) }; let value = match binary_expr.op { - ast::BinOrCmpOp::Bin(ast::BinOp::Add) => self.add(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::Sub) => self.sub(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::Mul) => self.mul(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::Div) => self.div(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::FloorDiv) => { - self.floor_div(left_value, right_value) - } - ast::BinOrCmpOp::Bin(ast::BinOp::Mod) => self.r#mod(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::Pow) => self.pow(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::LShift) => { - self.bit_lshift(left_value, right_value) - } - ast::BinOrCmpOp::Bin(ast::BinOp::RShift) => { - self.bit_rshift(left_value, right_value) - } - ast::BinOrCmpOp::Bin(ast::BinOp::BitAnd) => self.bit_and(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::BitOr) => self.bit_or(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::BitXor) => self.bit_xor(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::And) => self.logic_and(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::Or) => self.logic_or(left_value, right_value), - ast::BinOrCmpOp::Bin(ast::BinOp::As) => self.r#as(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::Eq) => self.cmp_equal_to(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::NotEq) => { - self.cmp_not_equal_to(left_value, right_value) - } - ast::BinOrCmpOp::Cmp(ast::CmpOp::Gt) => { - self.cmp_greater_than(left_value, right_value) - } - ast::BinOrCmpOp::Cmp(ast::CmpOp::GtE) => { - self.cmp_greater_than_or_equal(left_value, right_value) - } - ast::BinOrCmpOp::Cmp(ast::CmpOp::Lt) => self.cmp_less_than(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::LtE) => { - self.cmp_less_than_or_equal(left_value, right_value) - } - ast::BinOrCmpOp::Cmp(ast::CmpOp::Is) => self.is(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::IsNot) => self.is_not(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::Not) => self.is_not(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::NotIn) => self.not_in(left_value, right_value), - ast::BinOrCmpOp::Cmp(ast::CmpOp::In) => self.r#in(left_value, right_value), + ast::BinOp::Add => self.add(left_value, right_value), + ast::BinOp::Sub => self.sub(left_value, right_value), + ast::BinOp::Mul => self.mul(left_value, right_value), + ast::BinOp::Div => self.div(left_value, right_value), + ast::BinOp::FloorDiv => self.floor_div(left_value, right_value), + ast::BinOp::Mod => self.r#mod(left_value, right_value), + ast::BinOp::Pow => self.pow(left_value, right_value), + ast::BinOp::LShift => self.bit_lshift(left_value, right_value), + ast::BinOp::RShift => self.bit_rshift(left_value, right_value), + ast::BinOp::BitAnd => self.bit_and(left_value, right_value), + ast::BinOp::BitOr => self.bit_or(left_value, right_value), + ast::BinOp::BitXor => self.bit_xor(left_value, right_value), + ast::BinOp::And => self.logic_and(left_value, right_value), + ast::BinOp::Or => self.logic_or(left_value, right_value), + ast::BinOp::As => self.r#as(left_value, right_value), }; Ok(value) } else { - let jump_if_false = matches!(binary_expr.op, ast::BinOrCmpOp::Bin(ast::BinOp::And)); + let jump_if_false = matches!(binary_expr.op, ast::BinOp::And); let start_block = self.append_block(""); let value_block = self.append_block(""); let end_block = self.append_block(""); @@ -1634,19 +1745,22 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .walk_expr(&selector_expr.value) .expect(kcl_error::COMPILE_ERROR_MSG); let string_ptr_value = self - .native_global_string(selector_expr.attr.node.names[0].as_str(), "") + .native_global_string(selector_expr.attr.node.names[0].node.as_str(), "") .into(); let fn_name = if selector_expr.has_question { &ApiFunc::kclvm_value_load_attr_option } else { &ApiFunc::kclvm_value_load_attr }; - value = self.build_call(&fn_name.name(), &[value, string_ptr_value]); + value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), value, string_ptr_value], + ); for name in &selector_expr.attr.node.names[1..] { - let string_ptr_value = self.native_global_string(name, "").into(); + let string_ptr_value = self.native_global_string(&name.node, "").into(); value = self.build_call( &ApiFunc::kclvm_value_load_attr.name(), - &[value, string_ptr_value], + &[self.current_runtime_ctx_ptr(), value, string_ptr_value], ); } Ok(value) @@ -1672,7 +1786,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } else { self.none_value() }; - self.dict_insert(dict_value, name.as_str(), value, 0, -1); + self.dict_insert(dict_value, name.node.as_str(), value, 0, -1); } let pkgpath = self.native_global_string_value(&self.current_pkgpath()); let is_in_schema = @@ -1681,7 +1795,7 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { &ApiFunc::kclvm_value_function_invoke.name(), &[ func, - self.global_ctx_ptr(), + self.current_runtime_ctx_ptr(), list_value, dict_value, pkgpath, @@ -1703,7 +1817,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } else { &ApiFunc::kclvm_value_subscr }; - value = self.build_call(&fn_name.name(), &[value, index]); + value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), value, index], + ); } else { let lower = { if let Some(lower) = &subscript.lower { @@ -1731,7 +1848,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } else { &ApiFunc::kclvm_value_slice }; - value = self.build_call(&fn_name.name(), &[value, lower, upper, step]); + value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), value, lower, upper, step], + ); } Ok(value) } @@ -1933,13 +2053,13 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { } else { self.none_value() }; - self.dict_insert(dict_value, name.as_str(), value, 0, -1); + self.dict_insert(dict_value, name.node.as_str(), value, 0, -1); } let pkgpath = self.native_global_string_value(&self.current_pkgpath()); let schema = self.build_call( &ApiFunc::kclvm_schema_value_new.name(), &[ - self.global_ctx_ptr(), + self.current_runtime_ctx_ptr(), list_value, dict_value, schema_type, @@ -1949,7 +2069,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ], ); if !is_in_schema { - self.build_void_call(&ApiFunc::kclvm_schema_optional_check.name(), &[schema]); + self.build_void_call( + &ApiFunc::kclvm_schema_optional_check.name(), + &[self.current_runtime_ctx_ptr(), schema], + ); } utils::update_ctx_filename(self, &schema_expr.config); { @@ -1991,7 +2114,12 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { utils::update_ctx_current_line(self); self.build_void_call( &ApiFunc::kclvm_schema_assert.name(), - &[check_result, msg, schema_config_meta], + &[ + self.current_runtime_ctx_ptr(), + check_result, + msg, + schema_config_meta, + ], ); self.br(end_block); self.builder.position_at_end(end_block); @@ -2002,6 +2130,9 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { check_backtrack_stop!(self); let pkgpath = &self.current_pkgpath(); let is_in_schema = self.schema_stack.borrow().len() > 0; + // Higher-order lambda requires capturing the current lambda closure variable + // as well as the closure of a more external scope. + let last_closure_map = self.get_current_inner_scope_variable_map(); let func_before_block = self.append_block(""); self.br(func_before_block); // Use "pkgpath"+"kclvm_lambda" to name 'function' to prevent conflicts between lambdas with the same name in different packages @@ -2012,7 +2143,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { )); // Enter the function self.push_function(function); - self.lambda_stack.borrow_mut().push(true); + // Push the current lambda scope level in the lambda stack. + self.push_lambda(self.scope_level() + 1); // Lambda function body let block = self.context.append_basic_block(function, ENTRY_NAME); self.builder.position_at_end(block); @@ -2033,7 +2165,11 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let string_ptr_value = self.native_global_string(shcmea_closure_name, "").into(); let schema_value = self.build_call( &ApiFunc::kclvm_dict_get_value.name(), - &[closure_map, string_ptr_value], + &[ + self.current_runtime_ctx_ptr(), + closure_map, + string_ptr_value, + ], ); let value_ptr_type = self.value_ptr_type(); let var = self @@ -2053,11 +2189,11 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let closure = self.list_value(); // Use closure map in the laste scope to construct curret closure map. // The default value of the closure map is `{}`. - self.list_append(closure, self.get_closure_map()); + self.list_append(closure, last_closure_map); let function = self.closure_value(function, closure); self.leave_scope(); self.pop_function(); - self.lambda_stack.borrow_mut().pop(); + self.pop_lambda(); Ok(function) } @@ -2101,7 +2237,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ast::CmpOp::NotIn => ApiFunc::kclvm_value_not_in, ast::CmpOp::In => ApiFunc::kclvm_value_in, }; - let result_value = self.build_call(&fn_name.name(), &[left_value, right_value]); + let result_value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), left_value, right_value], + ); let is_truth = self.value_is_truthy(result_value); left_value = right_value; // Get next value using a store/load temp block @@ -2144,7 +2283,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ast::CmpOp::NotIn => ApiFunc::kclvm_value_not_in, ast::CmpOp::In => ApiFunc::kclvm_value_in, }; - left_value = self.build_call(&fn_name.name(), &[left_value, right_value]); + left_value = self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), left_value, right_value], + ); Ok(left_value) } } @@ -2174,7 +2316,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { let string_ptr_value = self .native_global_string(string_lit.value.as_str(), "") .into(); - Ok(self.build_call(&ApiFunc::kclvm_value_Str.name(), &[string_ptr_value])) + Ok(self.build_call( + &ApiFunc::kclvm_value_Str.name(), + &[self.current_runtime_ctx_ptr(), string_ptr_value], + )) } fn walk_name_constant_lit( @@ -2204,8 +2349,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { .expect(kcl_error::INTERNAL_ERROR_MSG), _ => panic!("{}", kcl_error::INVALID_JOINED_STR_MSG), }; - result_value = - self.build_call(&ApiFunc::kclvm_value_op_add.name(), &[result_value, value]); + result_value = self.build_call( + &ApiFunc::kclvm_value_op_add.name(), + &[self.current_runtime_ctx_ptr(), result_value, value], + ); } Ok(result_value) } @@ -2223,7 +2370,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { _ => panic!("{}", kcl_error::INVALID_STR_INTERPOLATION_SPEC_MSG), }; } - Ok(self.build_call(&fn_name.name(), &[formatted_expr_value])) + Ok(self.build_call( + &fn_name.name(), + &[self.current_runtime_ctx_ptr(), formatted_expr_value], + )) } fn walk_comment(&self, _comment: &'ctx ast::Comment) -> Self::Result { @@ -2239,11 +2389,6 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { fn walk_module(&self, module: &'ctx ast::Module) -> Self::Result { check_backtrack_stop!(self); - if !module.body.is_empty() { - utils::update_ctx_filename(self, &module.body[0]); - } - // Compile all schema and rule firstly - self.compile_module_import_and_types(module); // Compile all statements of the module self.walk_stmts_except_import(&module.body) } @@ -2285,7 +2430,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { match identifier_ctx { ast::ExprContext::Store => { if identifier.names.len() == 1 { - let name = identifier.names[0].as_str(); + let name = identifier.names[0].node.as_str(); let tpe = self.value_ptr_type(); // Global variables if self.scope_level() == GLOBAL_LEVEL { @@ -2294,12 +2439,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { right_value.expect(kcl_error::INTERNAL_ERROR_MSG), ); // Local variables including schema/rule/lambda - } else if *self - .lambda_stack - .borrow_mut() - .last() - .expect(kcl_error::INTERNAL_ERROR_MSG) - { + } else if self.is_in_lambda() { let value = right_value.expect(kcl_error::INTERNAL_ERROR_MSG); // If variable exists in the scope and update it, if not, add it to the scope. if !self.store_variable_in_current_scope(name, value) { @@ -2354,7 +2494,11 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.builder.position_at_end(then_block); let config_entry = self.build_call( &ApiFunc::kclvm_dict_get_entry.name(), - &[config_value, string_ptr_value], + &[ + self.current_runtime_ctx_ptr(), + config_value, + string_ptr_value, + ], ); self.br(else_block); self.builder.position_at_end(else_block); @@ -2381,6 +2525,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_schema_backtrack_cache.name(), &[ + self.current_runtime_ctx_ptr(), schema_value, backtrack_cache, cal_map, @@ -2416,7 +2561,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } } else { let names = &identifier.names; - let name = names[0].as_str(); + let name = names[0].node.as_str(); let mut value = if is_in_schema { self.get_variable_in_schema(name) .expect(kcl_error::INTERNAL_ERROR_MSG) @@ -2425,7 +2570,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { .expect(kcl_error::INTERNAL_ERROR_MSG) }; for i in 0..names.len() - 1 { - let attr = names[i + 1].as_str(); + let attr = names[i + 1].node.as_str(); let ctx = if matches!(identifier_ctx, ast::ExprContext::Store) && i != names.len() - 2 && names.len() > 2 @@ -2439,7 +2584,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let attr = self.native_global_string(attr, "").into(); value = self.build_call( &ApiFunc::kclvm_value_load_attr.name(), - &[value, attr], + &[self.current_runtime_ctx_ptr(), value, attr], ); } ast::ExprContext::Store => { @@ -2447,11 +2592,110 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_dict_set_value.name(), &[ + self.current_runtime_ctx_ptr(), value, attr, right_value.expect(kcl_error::INTERNAL_ERROR_MSG), ], ); + + let is_local_var = { + let local_vars = self.local_vars.borrow_mut(); + local_vars.contains(name) + }; + let is_in_lambda = self.is_in_lambda(); + // Set config value for the schema attribute if the attribute is in the schema and + // it is not a local variable in the lambda function. + if self.scope_level() >= INNER_LEVEL + && is_in_schema + && !is_in_lambda + && !is_local_var + { + let schema_value = self + .get_variable(value::SCHEMA_SELF_NAME) + .expect(kcl_error::INTERNAL_ERROR_MSG); + let config_value = self + .get_variable(value::SCHEMA_CONFIG_NAME) + .expect(kcl_error::INTERNAL_ERROR_MSG); + let string_ptr_value = + self.native_global_string(name, "").into(); + let has_key = self + .build_call( + &ApiFunc::kclvm_dict_has_value.name(), + &[config_value, string_ptr_value], + ) + .into_int_value(); + // The config has the attribute key? + let has_key = self.builder.build_int_compare( + IntPredicate::NE, + has_key, + self.native_i8_zero(), + "", + ); + let last_block = self.append_block(""); + let then_block = self.append_block(""); + let else_block = self.append_block(""); + self.br(last_block); + self.builder.position_at_end(last_block); + let none_value = self.none_value(); + self.builder + .build_conditional_branch(has_key, then_block, else_block); + self.builder.position_at_end(then_block); + let config_entry = self.build_call( + &ApiFunc::kclvm_dict_get_entry.name(), + &[ + self.current_runtime_ctx_ptr(), + config_value, + string_ptr_value, + ], + ); + self.br(else_block); + self.builder.position_at_end(else_block); + let tpe = self.value_ptr_type(); + let phi = self.builder.build_phi(tpe, ""); + phi.add_incoming(&[ + (&none_value, last_block), + (&config_entry, then_block), + ]); + let config_value = phi.as_basic_value(); + self.value_union(schema_value, config_value); + let cal_map = self + .get_variable(value::SCHEMA_CAL_MAP) + .expect(kcl_error::INTERNAL_ERROR_MSG); + let backtrack_cache = self + .get_variable(value::BACKTRACK_CACHE) + .expect(kcl_error::INTERNAL_ERROR_MSG); + let runtime_type = self + .get_variable(value::SCHEMA_RUNTIME_TYPE) + .expect(kcl_error::INTERNAL_ERROR_MSG); + let name_native_str = self.native_global_string_value(name); + self.build_void_call( + &ApiFunc::kclvm_schema_backtrack_cache.name(), + &[ + self.current_runtime_ctx_ptr(), + schema_value, + backtrack_cache, + cal_map, + name_native_str, + runtime_type, + ], + ); + // Update backtrack meta + { + if let Some(backtrack_meta) = + self.backtrack_meta.borrow_mut().as_mut() + { + if name == backtrack_meta.target { + backtrack_meta.count += 1; + if backtrack_meta.count == backtrack_meta.level { + backtrack_meta.stop = true; + self.ret(schema_value); + return Ok(schema_value); + } + } + } + } + } } } } @@ -2459,7 +2703,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { Ok(right_value.expect(kcl_error::INTERNAL_ERROR_MSG)) } ast::ExprContext::Load => { - let name = identifier.names[0].as_str(); + let name = identifier.names[0].node.as_str(); let is_local_var = { let local_vars = self.local_vars.borrow_mut(); local_vars.contains(name) @@ -2472,7 +2716,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } } else { let names = &identifier.names; - let name = names[0].as_str(); + let name = names[0].node.as_str(); let mut value = if identifier.pkgpath.is_empty() { if is_in_schema && !is_local_var { self.get_variable_in_schema(name) @@ -2485,7 +2729,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.ok_result().expect(kcl_error::INTERNAL_ERROR_MSG) }; for i in 0..names.len() - 1 { - let attr = names[i + 1].as_str(); + let attr = names[i + 1].node.as_str(); let ctx = if matches!(identifier_ctx, ast::ExprContext::Store) && i != names.len() - 2 && names.len() > 2 @@ -2511,7 +2755,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let attr = self.native_global_string(attr, "").into(); value = self.build_call( &ApiFunc::kclvm_value_load_attr.name(), - &[value, attr], + &[self.current_runtime_ctx_ptr(), value, attr], ); } } @@ -2520,6 +2764,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.build_void_call( &ApiFunc::kclvm_dict_set_value.name(), &[ + self.current_runtime_ctx_ptr(), value, attr, right_value.expect(kcl_error::INTERNAL_ERROR_MSG), @@ -2560,7 +2805,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } else { self.none_value() }; - self.dict_insert(dict_value, name.as_str(), value, 0, -1); + self.dict_insert(dict_value, name.node.as_str(), value, 0, -1); } let name = match &decorator.func.node { ast::Expr::Identifier(ident) if ident.names.len() == 1 => ident.names[0].clone(), @@ -2571,7 +2816,8 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { Ok(self.build_call( &ApiFunc::kclvm_value_Decorator.name(), &[ - self.native_global_string_value(name.as_str()), + self.current_runtime_ctx_ptr(), + self.native_global_string_value(name.node.as_str()), list_value, dict_value, schema_config_meta, @@ -2627,16 +2873,20 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.builder.position_at_end(next_block); let arg_value = self.build_call( &ApiFunc::kclvm_list_get_option.name(), - &[args, self.native_int_value(i as i32)], + &[ + self.current_runtime_ctx_ptr(), + args, + self.native_int_value(i as i32), + ], ); - self.store_variable(&arg_name.names[0], arg_value); + self.store_variable(&arg_name.names[0].node, arg_value); } // for loop in 0..argument_len in LLVM end self.br(end_block); self.builder.position_at_end(end_block); // Keyword arguments for arg_name in arg_names.iter() { - let name = &arg_name.names[0]; + let name = &arg_name.names[0].node; let string_ptr_value = self.native_global_string(name.as_str(), "").into(); let has_key = self .build_call( @@ -2657,10 +2907,10 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.builder.position_at_end(then_block); let arg = self.build_call( &ApiFunc::kclvm_dict_get_value.name(), - &[kwargs, string_ptr_value], + &[self.current_runtime_ctx_ptr(), kwargs, string_ptr_value], ); // Find argument name in the scope - self.store_variable(&arg_name.names[0], arg); + self.store_variable(&arg_name.names[0].node, arg); self.br(else_block); self.builder.position_at_end(else_block); } @@ -2704,14 +2954,14 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { { let mut local_vars = self.local_vars.borrow_mut(); for v in targets { - let name = &v.node.names[0]; + let name = &v.node.names[0].node; local_vars.insert(name.clone()); } } if targets.len() == 1 { // Store the target self.walk_identifier_with_ctx( - &targets.get(0).expect(kcl_error::INTERNAL_ERROR_MSG).node, + &targets.first().expect(kcl_error::INTERNAL_ERROR_MSG).node, &ast::ExprContext::Store, Some(next_value), ) @@ -2721,7 +2971,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let value = self.build_call(&ApiFunc::kclvm_iterator_cur_value.name(), &[iter_value]); // Store the target self.walk_identifier_with_ctx( - &targets.get(0).expect(kcl_error::INTERNAL_ERROR_MSG).node, + &targets.first().expect(kcl_error::INTERNAL_ERROR_MSG).node, &ast::ExprContext::Store, Some(key), ) @@ -2780,7 +3030,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { { let mut local_vars = self.local_vars.borrow_mut(); for v in targets { - let name = &v.node.names[0]; + let name = &v.node.names[0].node; local_vars.remove(name); } } @@ -2797,7 +3047,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { if let Some(key) = &item.node.key { let mut insert_index = -1; let optional_name = match &key.node { - ast::Expr::Identifier(identifier) => Some(identifier.names[0].clone()), + ast::Expr::Identifier(identifier) => Some(identifier.names[0].node.clone()), ast::Expr::StringLit(string_lit) => Some(string_lit.value.clone()), ast::Expr::Subscript(subscript) => { let mut name = None; @@ -2806,7 +3056,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { if let ast::Expr::NumberLit(number) = &index_node.node { if let ast::NumberLitValue::Int(v) = number.value { insert_index = v; - name = Some(identifier.names[0].clone()) + name = Some(identifier.names[0].node.clone()) } } } @@ -2816,12 +3066,11 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { _ => None, }; // Store a local variable for every entry key. - let key = match optional_name { - Some(name) => { - self.add_or_update_local_variable(&name, value); - self.string_value(&name) + let key = match &optional_name { + Some(name) if !self.local_vars.borrow().contains(name) => { + self.string_value(name) } - None => self.walk_expr(key)?, + _ => self.walk_expr(key)?, }; self.dict_insert_with_key_value( config_value, @@ -2830,11 +3079,16 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { item.node.operation.value(), insert_index as i32, ); + if let Some(name) = &optional_name { + let value = + self.dict_get(config_value, self.native_global_string(name, "").into()); + self.add_or_update_local_variable(name, value); + } } else { // If the key does not exist, execute the logic of unpacking expression `**expr` here. self.build_void_call( &ApiFunc::kclvm_dict_insert_unpack.name(), - &[config_value, value], + &[self.current_runtime_ctx_ptr(), config_value, value], ); } } diff --git a/kclvm/compiler/src/codegen/llvm/schema.rs b/kclvm/compiler/src/codegen/llvm/schema.rs index ad0510e0d..797906603 100644 --- a/kclvm/compiler/src/codegen/llvm/schema.rs +++ b/kclvm/compiler/src/codegen/llvm/schema.rs @@ -3,6 +3,7 @@ use inkwell::values::{BasicValueEnum, FunctionValue}; use inkwell::AddressSpace; use kclvm_ast::ast; +use kclvm_sema::pkgpath_without_prefix; use std::collections::HashMap; use std::str; @@ -11,13 +12,12 @@ use crate::codegen::error as kcl_error; use crate::codegen::traits::{BuilderMethods, DerivedValueCalculationMethods, ValueMethods}; use crate::value; -use crate::pkgpath_without_prefix; - impl<'ctx> LLVMCodeGenContext<'ctx> { - /// Emit all schema left identifiers because all the schema attribute can be forward referenced - pub fn emit_schema_left_identifiers( + /// Emit all left identifiers because all the attribute can be forward referenced. + pub fn emit_left_identifiers( &self, body: &'ctx [Box>], + index_signature: &'ctx Option>, cal_map: BasicValueEnum<'ctx>, runtime_type: &str, is_in_if: bool, @@ -69,10 +69,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let body_vec = body_map.get_mut(name).expect(kcl_error::INTERNAL_ERROR_MSG); body_vec.push(stmt); }; + if let Some(index_signature) = index_signature { + self.default_collection_insert_value( + cal_map, + kclvm_runtime::CAL_MAP_INDEX_SIGNATURE, + self.int_value(index_signature.line as i64), + ); + place_holder_map.insert(kclvm_runtime::CAL_MAP_INDEX_SIGNATURE.to_string(), vec![]); + } for stmt in body { match &stmt.node { ast::Stmt::Unification(unification_stmt) => { - let name = &unification_stmt.target.node.names[0]; + let name = &unification_stmt.target.node.names[0].node; self.dict_merge(schema_value, name, value, 0, -1); if is_in_if { in_if_names.push(name.to_string()); @@ -82,7 +90,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } ast::Stmt::Assign(assign_stmt) => { for target in &assign_stmt.targets { - let name = &target.node.names[0]; + let name = &target.node.names[0].node; self.dict_merge(schema_value, name, value, 0, -1); if is_in_if { in_if_names.push(name.to_string()); @@ -93,7 +101,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } ast::Stmt::AugAssign(aug_assign_stmt) => { let target = &aug_assign_stmt.target; - let name = &target.node.names[0]; + let name = &target.node.names[0].node; self.dict_merge(schema_value, name, value, 0, -1); if is_in_if { in_if_names.push(name.to_string()); @@ -103,8 +111,9 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } ast::Stmt::If(if_stmt) => { let mut names: Vec = vec![]; - self.emit_schema_left_identifiers( + self.emit_left_identifiers( &if_stmt.body, + &None, cal_map, runtime_type, true, @@ -122,8 +131,9 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } names.clear(); } - self.emit_schema_left_identifiers( + self.emit_left_identifiers( &if_stmt.orelse, + &None, cal_map, runtime_type, true, @@ -173,7 +183,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { for item in &t.items { if let Some(key) = &item.node.key { let name = match &key.node { - ast::Expr::Identifier(t) => t.names[0].clone(), + ast::Expr::Identifier(t) => t.names[0].node.clone(), ast::Expr::NumberLit(t) => match t.value { ast::NumberLitValue::Int(i) => i.to_string(), ast::NumberLitValue::Float(f) => f.to_string(), diff --git a/kclvm/compiler/src/codegen/llvm/utils.rs b/kclvm/compiler/src/codegen/llvm/utils.rs index c77b75dde..b6c1cd11f 100644 --- a/kclvm/compiler/src/codegen/llvm/utils.rs +++ b/kclvm/compiler/src/codegen/llvm/utils.rs @@ -13,11 +13,11 @@ use super::context::LLVMCodeGenContext; */ /// Update runtime context pkgpath -pub fn update_ctx_pkgpath<'ctx>(gen: &'ctx LLVMCodeGenContext, pkgpath: &str) { +pub fn update_ctx_pkgpath(gen: &LLVMCodeGenContext, pkgpath: &str) { gen.build_void_call( &ApiFunc::kclvm_context_set_kcl_pkgpath.name(), &[ - gen.global_ctx_ptr(), + gen.current_runtime_ctx_ptr(), gen.native_global_string_value(pkgpath), ], ); @@ -28,7 +28,10 @@ pub fn update_ctx_filename<'ctx, T>(gen: &'ctx LLVMCodeGenContext, node: &'ctx a if !node.filename.is_empty() { gen.build_void_call( &ApiFunc::kclvm_context_set_kcl_filename.name(), - &[gen.native_global_string_value(&node.filename)], + &[ + gen.current_runtime_ctx_ptr(), + gen.native_global_string_value(&node.filename), + ], ); } } @@ -41,6 +44,7 @@ pub fn update_ctx_line_col<'ctx, T>(gen: &'ctx LLVMCodeGenContext, node: &'ctx a gen.build_void_call( &ApiFunc::kclvm_context_set_kcl_line_col.name(), &[ + gen.current_runtime_ctx_ptr(), gen.native_int_value(node.line as i32), gen.native_int_value(0), ], @@ -54,6 +58,7 @@ pub fn update_ctx_current_line(gen: &LLVMCodeGenContext) { gen.build_void_call( &ApiFunc::kclvm_context_set_kcl_line_col.name(), &[ + gen.current_runtime_ctx_ptr(), gen.native_int_value(*current_line as i32), gen.native_int_value(0), ], diff --git a/kclvm/compiler/src/codegen/mod.rs b/kclvm/compiler/src/codegen/mod.rs index f2fe2b6e9..5af50df0d 100644 --- a/kclvm/compiler/src/codegen/mod.rs +++ b/kclvm/compiler/src/codegen/mod.rs @@ -13,8 +13,6 @@ pub(crate) const ENTRY_NAME: &str = "entry"; pub(crate) const VALUE_TYPE_NAME: &str = "kclvm_value_ref_t"; /// The kclvm runtime context type name. pub(crate) const CONTEXT_TYPE_NAME: &str = "kclvm_context_t"; -/// The kclvm context variable name. -pub(crate) const KCL_CONTEXT_VAR_NAME: &str = "context"; /// Package init function name suffix pub(crate) const PKG_INIT_FUNCTION_SUFFIX: &str = "init"; /// Global level diff --git a/kclvm/compiler/src/codegen/traits/value.rs b/kclvm/compiler/src/codegen/traits/value.rs index 72f808eeb..476ce5a66 100644 --- a/kclvm/compiler/src/codegen/traits/value.rs +++ b/kclvm/compiler/src/codegen/traits/value.rs @@ -1,4 +1,6 @@ -//! Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. + +use std::collections::HashMap; use super::BackendTypes; @@ -32,14 +34,15 @@ pub trait ValueMethods: BackendTypes { fn struct_function_value( &self, functions: &[Self::Function], + attr_functions: &HashMap>, runtime_type: &str, ) -> Self::Value; /// Construct a builtin function value using the function name. fn builtin_function_value(&self, function_name: &str) -> Self::Value; /// Get a global value pointer named `name`. fn global_value_ptr(&self, name: &str) -> Self::Value; - /// Get the global runtime context pointer. - fn global_ctx_ptr(&self) -> Self::Value; + /// Get current runtime context pointer. + fn current_runtime_ctx_ptr(&self) -> Self::Value; } /// DerivedValueCalculationMethods defines all value base calculation APIs. diff --git a/kclvm/compiler/src/lib.rs b/kclvm/compiler/src/lib.rs index 949b320cd..446c83911 100644 --- a/kclvm/compiler/src/lib.rs +++ b/kclvm/compiler/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod codegen; pub mod value; diff --git a/kclvm/compiler/src/macros.rs b/kclvm/compiler/src/macros.rs index cc47ea8c4..31cd1e64d 100644 --- a/kclvm/compiler/src/macros.rs +++ b/kclvm/compiler/src/macros.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #[macro_export] macro_rules! check_backtrack_stop { @@ -10,13 +10,3 @@ macro_rules! check_backtrack_stop { } }; } - -#[macro_export] -macro_rules! pkgpath_without_prefix { - ($pkgpath: expr) => { - match $pkgpath.strip_prefix('@') { - Some(v) => v.to_string(), - None => $pkgpath.to_string(), - } - }; -} diff --git a/kclvm/compiler/src/value/lambda.rs b/kclvm/compiler/src/value/lambda.rs index 5948071d2..4e7c84440 100644 --- a/kclvm/compiler/src/value/lambda.rs +++ b/kclvm/compiler/src/value/lambda.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub const LAMBDA_NAME: &str = "kclvm_lambda"; pub const LAMBDA_CLOSURE: &str = "$lambda_closure"; diff --git a/kclvm/compiler/src/value/mod.rs b/kclvm/compiler/src/value/mod.rs index 3d10ce495..1578aef2e 100644 --- a/kclvm/compiler/src/value/mod.rs +++ b/kclvm/compiler/src/value/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. mod lambda; pub use self::lambda::*; diff --git a/kclvm/compiler/src/value/schema.rs b/kclvm/compiler/src/value/schema.rs index 3f2cf46b0..019a121cc 100644 --- a/kclvm/compiler/src/value/schema.rs +++ b/kclvm/compiler/src/value/schema.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub const SCHEMA_NAME: &str = "$kclvm_schema"; pub const SCHEMA_ATTR_NAME: &str = "$kclvm_schema_attr"; diff --git a/kclvm/config/Cargo.toml b/kclvm/config/Cargo.toml index 2471cbe70..08b741542 100644 --- a/kclvm/config/Cargo.toml +++ b/kclvm/config/Cargo.toml @@ -1,20 +1,19 @@ [package] name = "kclvm-config" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde = { version = "1", features = ["derive"] } -serde_yaml = "0.8.7" +serde_yaml = "0.9.32" serde_json = "1.0" indexmap = "1.0" ahash = "0.7.2" toml = "0.5.8" ron = "0.7.0" chrono = "0.4.19" -rust-crypto = "0.2.36" glob = "0.3.0" fslock = "0.2.1" pathdiff = "0.2.1" @@ -24,3 +23,5 @@ kclvm-version = {path = "../version"} kclvm-utils = {path = "../utils"} kclvm-ast = {path = "../ast"} dirs = "5.0.0" +pcre2 = "0.2.4" +md-5 = "0.8.0" diff --git a/kclvm/config/src/cache.rs b/kclvm/config/src/cache.rs index cd8774cc8..f83e6e391 100644 --- a/kclvm/config/src/cache.rs +++ b/kclvm/config/src/cache.rs @@ -1,10 +1,10 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. extern crate chrono; use super::modfile::KCL_FILE_SUFFIX; -use crypto::digest::Digest; -use crypto::md5::Md5; +use anyhow::Result; use fslock::LockFile; -use kclvm_utils::pkgpath::parse_external_pkg_name; +use kclvm_utils::pkgpath::{parse_external_pkg_name, rm_external_pkg_name}; +use md5::{Digest, Md5}; use serde::{de::DeserializeOwned, Serialize}; use std::collections::HashMap; use std::error; @@ -18,8 +18,9 @@ const LOCK_SUFFIX: &str = ".lock"; const DEFAULT_CACHE_DIR: &str = ".kclvm/cache"; const CACHE_INFO_FILENAME: &str = "info"; const KCL_SUFFIX_PATTERN: &str = "*.k"; +pub const KCL_CACHE_PATH_ENV_VAR: &str = "KCL_CACHE_PATH"; -pub type CacheInfo = String; +pub type CacheInfo = Vec; pub type Cache = HashMap; #[allow(dead_code)] @@ -49,6 +50,7 @@ where if root.is_empty() || pkgpath.is_empty() { None } else { + // The cache file path let filename = get_cache_filename(root, target, pkgpath, Some(&option.cache_dir)); if !Path::new(&filename).exists() { None @@ -58,49 +60,88 @@ where // If the file exists and it is an internal package or an external package, // Check the cache info. let pkg_name = parse_external_pkg_name(pkgpath).ok()?; - if Path::new(&real_path).exists() - || (external_pkgs.get(&pkg_name).is_some() - && Path::new(external_pkgs.get(&pkg_name)?).exists()) + + // If it is an internal package + let real_path = if Path::new(&real_path).exists() { + real_path + // If it is an external package + } else if external_pkgs.get(&pkg_name).is_some() + && Path::new(external_pkgs.get(&pkg_name)?).exists() { - let cache_info = read_info_cache(root, target, Some(&option.cache_dir)); - let relative_path = real_path.replacen(root, ".", 1); - match cache_info.get(&relative_path) { - Some(path_info_in_cache) => { - if get_cache_info(&real_path).ne(path_info_in_cache) { - return None; - } + get_pkg_realpath_from_pkgpath( + external_pkgs.get(&pkg_name)?, + &rm_external_pkg_name(pkgpath).ok()?, + ) + } else { + return None; + }; + + // get the cache info from cache file "info" + let cache_info = read_info_cache(root, target, Some(&option.cache_dir)); + let relative_path = real_path.replacen(root, ".", 1); + match cache_info.get(&relative_path) { + Some(path_info_in_cache) => { + // calculate the md5 of the file and compare it with the cache info + if get_cache_info(&real_path).ne(path_info_in_cache) { + return None; } - None => return None, - }; - } + } + None => return None, + }; + // If the md5 is the same, load the cache file load_data_from_file(&filename) } } } /// Save pkg cache. -pub fn save_pkg_cache(root: &str, target: &str, pkgpath: &str, data: T, option: CacheOption) +pub fn save_pkg_cache( + root: &str, + target: &str, + pkgpath: &str, + data: T, + option: CacheOption, + external_pkgs: &HashMap, +) -> Result<()> where T: Serialize, { if root.is_empty() || pkgpath.is_empty() { - return; + return Err(anyhow::anyhow!( + "failed to save package cache {} to root {}", + pkgpath, + root + )); } let dst_filename = get_cache_filename(root, target, pkgpath, Some(&option.cache_dir)); let real_path = get_pkg_realpath_from_pkgpath(root, pkgpath); if Path::new(&real_path).exists() { write_info_cache(root, target, Some(&option.cache_dir), &real_path).unwrap(); + } else { + // If the file does not exist, it is an external package. + let pkg_name = parse_external_pkg_name(pkgpath)?; + let real_path = get_pkg_realpath_from_pkgpath( + external_pkgs + .get(&pkg_name) + .ok_or(anyhow::anyhow!("failed to save cache"))?, + &rm_external_pkg_name(pkgpath)?, + ); + if Path::new(&real_path).exists() { + write_info_cache(root, target, Some(&option.cache_dir), &real_path).unwrap(); + } } let cache_dir = get_cache_dir(root, Some(&option.cache_dir)); create_dir_all(&cache_dir).unwrap(); let tmp_filename = temp_file(&cache_dir, pkgpath); - save_data_to_file(&dst_filename, &tmp_filename, data) + save_data_to_file(&dst_filename, &tmp_filename, data); + Ok(()) } #[inline] fn get_cache_dir(root: &str, cache_dir: Option<&str>) -> String { let cache_dir = cache_dir.unwrap_or(DEFAULT_CACHE_DIR); - Path::new(root) + let root = std::env::var(KCL_CACHE_PATH_ENV_VAR).unwrap_or(root.to_string()); + Path::new(&root) .join(cache_dir) .join(format!("{}-{}", version::VERSION, version::CHECK_SUM)) .display() @@ -111,7 +152,8 @@ fn get_cache_dir(root: &str, cache_dir: Option<&str>) -> String { #[allow(dead_code)] fn get_cache_filename(root: &str, target: &str, pkgpath: &str, cache_dir: Option<&str>) -> String { let cache_dir = cache_dir.unwrap_or(DEFAULT_CACHE_DIR); - Path::new(root) + let root = std::env::var(KCL_CACHE_PATH_ENV_VAR).unwrap_or(root.to_string()); + Path::new(&root) .join(cache_dir) .join(format!("{}-{}", version::VERSION, version::CHECK_SUM)) .join(target) @@ -123,7 +165,8 @@ fn get_cache_filename(root: &str, target: &str, pkgpath: &str, cache_dir: Option #[inline] fn get_cache_info_filename(root: &str, target: &str, cache_dir: Option<&str>) -> String { let cache_dir = cache_dir.unwrap_or(DEFAULT_CACHE_DIR); - Path::new(root) + let root = std::env::var(KCL_CACHE_PATH_ENV_VAR).unwrap_or(root.to_string()); + Path::new(&root) .join(cache_dir) .join(format!("{}-{}", version::VERSION, version::CHECK_SUM)) .join(target) @@ -193,7 +236,7 @@ fn get_cache_info(path_str: &str) -> CacheInfo { md5.input(buf.as_slice()); } } - md5.result_str() + md5.result().to_vec() } pub fn get_pkg_realpath_from_pkgpath(root: &str, pkgpath: &str) -> String { diff --git a/kclvm/config/src/lib.rs b/kclvm/config/src/lib.rs index bf6e7db47..edeb16cb9 100644 --- a/kclvm/config/src/lib.rs +++ b/kclvm/config/src/lib.rs @@ -1,7 +1,8 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod cache; pub mod modfile; +pub mod path; pub mod settings; pub mod vfs; diff --git a/kclvm/config/src/modfile.rs b/kclvm/config/src/modfile.rs index 1c2b4293e..2f3a13d84 100644 --- a/kclvm/config/src/modfile.rs +++ b/kclvm/config/src/modfile.rs @@ -1,10 +1,13 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. +use anyhow::Result; use kclvm_utils::path::PathPrefix; use serde::Deserialize; use std::{env, fs, io::Read, path::PathBuf}; use toml; +use crate::path::ModRelativePath; + pub const KCL_MOD_FILE: &str = "kcl.mod"; pub const KCL_FILE_SUFFIX: &str = ".k"; pub const KCL_FILE_EXTENSION: &str = "k"; @@ -20,7 +23,7 @@ pub const DEFAULT_KPM_SUBDIR: &str = "kpm"; pub fn get_vendor_home() -> String { match env::var(KCL_PKG_PATH) { Ok(path) => path, - Err(_) => create_default_vendor_home().unwrap_or(String::default()), + Err(_) => create_default_vendor_home().unwrap_or_default(), } } @@ -81,7 +84,7 @@ pub struct KCLModFileExpectedSection { pub global_version: Option, } -pub fn get_pkg_root_from_paths(file_paths: &[String]) -> Result { +pub fn get_pkg_root_from_paths(file_paths: &[String], workdir: String) -> Result { if file_paths.is_empty() { return Err("No input KCL files or paths".to_string()); } @@ -89,9 +92,11 @@ pub fn get_pkg_root_from_paths(file_paths: &[String]) -> Result let mut m = std::collections::HashMap::::new(); let mut last_root = "".to_string(); for s in file_paths { - if s.contains(KCL_MOD_PATH_ENV) { + let path = ModRelativePath::from(s.to_string()); + if path.is_relative_path().map_err(|err| err.to_string())? { continue; } + if let Some(root) = get_pkg_root(s) { m.insert(root.clone(), root.clone()); last_root = root.clone(); @@ -101,10 +106,12 @@ pub fn get_pkg_root_from_paths(file_paths: &[String]) -> Result return Ok("".to_string()); } if m.len() == 1 { - return Ok(last_root); + Ok(last_root) + } else if !workdir.is_empty() { + return Ok(workdir); + } else { + return Ok("".to_string()); } - - Err(format!("conflict kcl.mod file paths: {:?}", m)) } pub fn get_pkg_root(k_file_path: &str) -> Option { @@ -157,17 +164,17 @@ mod modfile_test { #[test] fn test_get_pkg_root_from_paths() { assert_eq!( - get_pkg_root_from_paths(&[]), + get_pkg_root_from_paths(&[], "".to_string()), Err("No input KCL files or paths".to_string()) ); assert_eq!( - get_pkg_root_from_paths(&["wrong_path".to_string()]), + get_pkg_root_from_paths(&["wrong_path".to_string()], "".to_string()), Ok("".to_string()) ); let expected_root = std::path::Path::new(TEST_ROOT).canonicalize().unwrap(); let expected = expected_root.adjust_canonicalization(); assert_eq!( - get_pkg_root_from_paths(&[SETTINGS_FILE.to_string()]), + get_pkg_root_from_paths(&[SETTINGS_FILE.to_string()], "".to_string()), Ok(expected.to_string()) ); } diff --git a/kclvm/config/src/path.rs b/kclvm/config/src/path.rs new file mode 100644 index 000000000..652897175 --- /dev/null +++ b/kclvm/config/src/path.rs @@ -0,0 +1,205 @@ +//! The file provides the mod relative path type. +//! +//! The mod relative path is a path that is relative to the root package path. +//! The root package is can be specified by the prefix `${:KCL_MOD}`. +//! `` is the name of the root package. +//! If `` is omitted, the root package is the current package. +//! +//! # Examples +//! +//! `/usr/my_pkg` is the real path of the package `my_pkg`. +//! `${my_pkg:KCL_MOD}/sub/main.k` is a mod relative path. +//! The real path of `${my_pkg:KCL_MOD}/xxx/main.k` is `/usr/my_pkg/sub/main.k`. +use anyhow::Result; +use pcre2::bytes::Regex; +use std::path::PathBuf; + +#[derive(Clone, Debug, Default)] +/// [`ModRelativePath`] is a path that is relative to the root package path. +/// The root package is can be specified by the prefix `${:KCL_MOD}`. +/// `` is the name of the root package. +/// If `` is omitted, the root package is the current package. +/// +/// # Examples +/// +/// `/usr/my_pkg` is the real path of the package `my_pkg`. +/// `${my_pkg:KCL_MOD}/sub/main.k` is a mod relative path. +/// The real path of `${my_pkg:KCL_MOD}/xxx/main.k` is `/usr/my_pkg/sub/main.k`. +pub struct ModRelativePath { + path: String, +} + +/// The regular expression to match the mod relative path preffix. +const RELATIVE_PATH_PREFFIX: &str = r#"\$\{((?P[a-zA-Z0-9_-]+):)?KCL_MOD\}/"#; + +/// The name of the root package. +const ROOT_PKG_NAME_FLAG: &str = "name"; + +impl From for ModRelativePath { + fn from(path: String) -> Self { + ModRelativePath::new(path) + } +} + +impl ModRelativePath { + /// [`new`] creates a new [`ModRelativePath`] instance. + pub fn new(path: String) -> ModRelativePath { + ModRelativePath { path } + } + + /// [`get_path`] returns the clone string of path of the [`ModRelativePath`]. + pub fn get_path(&self) -> String { + self.path.clone() + } + + /// [`is_relative_path`] returns true if the path is a mod relative path. + /// + /// # Examples + /// + /// ```rust + /// use kclvm_config::path::ModRelativePath; + /// let path = ModRelativePath::new("${my_pkg:KCL_MOD}/src/path.rs".to_string()); + /// assert_eq!(path.is_relative_path().unwrap(), true); + /// + /// let path = ModRelativePath::new("${KCL_MOD}/src/path.rs".to_string()); + /// assert_eq!(path.is_relative_path().unwrap(), true); + /// + /// let path = ModRelativePath::new("/usr/${my_pkg:KCL_MOD}/src/path.rs".to_string()); + /// assert_eq!(path.is_relative_path().unwrap(), false); + /// + /// let path = ModRelativePath::new("/src/path.rs".to_string()); + /// assert_eq!(path.is_relative_path().unwrap(), false); + /// ``` + pub fn is_relative_path(&self) -> Result { + Ok(Regex::new(RELATIVE_PATH_PREFFIX)? + .find(self.path.as_bytes())? + .map_or(false, |mat| mat.start() == 0)) + } + + /// [`get_root_pkg_name`] returns the name of the root package. + /// + /// # Examples + /// + /// ```rust + /// use kclvm_config::path::ModRelativePath; + /// let path = ModRelativePath::new("${my_pkg:KCL_MOD}/src/path.rs".to_string()); + /// assert_eq!(path.get_root_pkg_name().unwrap(), Some("my_pkg".to_string())); + /// + /// let path = ModRelativePath::new("${KCL_MOD}/src/path.rs".to_string()); + /// assert_eq!(path.get_root_pkg_name().unwrap(), None); + /// + /// let path = ModRelativePath::new("/src/path.rs".to_string()); + /// assert_eq!(path.get_root_pkg_name().unwrap(), None); + /// ``` + pub fn get_root_pkg_name(&self) -> Result> { + if !self.is_relative_path()? { + return Ok(None); + } + + Ok(Regex::new(RELATIVE_PATH_PREFFIX)? + .captures(self.path.as_bytes())? + .and_then(|caps| caps.name(ROOT_PKG_NAME_FLAG)) + .map(|mat| std::str::from_utf8(mat.as_bytes()).map(|s| s.to_string())) + .transpose()?) + } + + /// [`canonicalize_by_root_path`] returns the canonicalized path by the root path. + /// + /// # Examples + /// + /// ```rust + /// use kclvm_config::path::ModRelativePath; + /// let path = ModRelativePath::new("${name:KCL_MOD}/src/path".to_string()); + /// #[cfg(target_os = "windows")] + /// assert_eq!(path.canonicalize_by_root_path("/usr/my_pkg").unwrap(), "/usr/my_pkg\\src/path"); + /// #[cfg(not(target_os = "windows"))] + /// assert_eq!(path.canonicalize_by_root_path("/usr/my_pkg").unwrap(), "/usr/my_pkg/src/path"); + /// + /// let path = ModRelativePath::new("/src/path".to_string()); + /// assert_eq!(path.canonicalize_by_root_path("/usr/my_pkg").unwrap(), "/src/path"); + /// ``` + pub fn canonicalize_by_root_path(&self, root_path: &str) -> Result { + if !self.is_relative_path()? { + return Ok(self.get_path()); + } + + Ok(Regex::new(RELATIVE_PATH_PREFFIX)? + .captures(self.path.as_bytes())? + .map_or_else( + || self.get_path(), + |caps| { + // Due to the path format is different between windows and linux, + // Can not use the replace method directly + // by 'replace(std::str::from_utf8(caps.get(0).unwrap().as_bytes()).unwrap(), root_path)'. + let sub_path = self.get_path().replace( + std::str::from_utf8(caps.get(0).unwrap().as_bytes()).unwrap(), + "", + ); + let res = PathBuf::from(root_path) + .join(sub_path) + .display() + .to_string(); + + res + }, + )) + } +} + +#[cfg(test)] +mod test_relative_path { + use super::*; + + #[test] + fn test_is_relative_path() { + let path = ModRelativePath::new("${name:KCL_MOD}/src/path.rs".to_string()); + assert!(path.is_relative_path().unwrap()); + let path = ModRelativePath::new("${KCL_MOD}/src/path.rs".to_string()); + assert!(path.is_relative_path().unwrap()); + let path = ModRelativePath::new("/usr/${name:KCL_MOD}/src/path.rs".to_string()); + assert!(!path.is_relative_path().unwrap()); + let path = ModRelativePath::new("/src/path.rs".to_string()); + assert!(!path.is_relative_path().unwrap()); + let path = ModRelativePath::new("./src/path.rs".to_string()); + assert!(!path.is_relative_path().unwrap()); + let path = ModRelativePath::new("${K_MOD}/src/path.rs".to_string()); + assert!(!path.is_relative_path().unwrap()); + let path = ModRelativePath::new("${:KCL_MOD}/src/path.rs".to_string()); + assert!(!path.is_relative_path().unwrap()); + } + + #[test] + fn test_get_root_pkg_name() { + let path = ModRelativePath::new("${my_pkg:KCL_MOD}/src/path.rs".to_string()); + assert_eq!( + path.get_root_pkg_name().unwrap(), + Some("my_pkg".to_string()) + ); + + let path = ModRelativePath::new("${KCL_MOD}/src/path.rs".to_string()); + assert_eq!(path.get_root_pkg_name().unwrap(), None); + + let path = ModRelativePath::new("/src/path.rs".to_string()); + assert_eq!(path.get_root_pkg_name().unwrap(), None); + } + + #[test] + fn test_canonicalize_by_root_path() { + let path = ModRelativePath::new("${name:KCL_MOD}/src/path".to_string()); + #[cfg(target_os = "windows")] + assert_eq!( + path.canonicalize_by_root_path("C:\\usr\\my_pkg").unwrap(), + "C:\\usr\\my_pkg\\src/path" + ); + #[cfg(not(target_os = "windows"))] + assert_eq!( + path.canonicalize_by_root_path("/usr/my_pkg").unwrap(), + "/usr/my_pkg/src/path" + ); + let path = ModRelativePath::new("/src/path".to_string()); + assert_eq!( + path.canonicalize_by_root_path("/usr/my_pkg").unwrap(), + "/src/path" + ); + } +} diff --git a/kclvm/config/src/settings.rs b/kclvm/config/src/settings.rs index 04f29a6ce..bc0109287 100644 --- a/kclvm/config/src/settings.rs +++ b/kclvm/config/src/settings.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use anyhow::{Context, Result}; use serde::{ de::{DeserializeSeed, Error, MapAccess, SeqAccess, Unexpected, Visitor}, @@ -60,8 +60,11 @@ pub struct Config { pub verbose: Option, pub debug: Option, pub sort_keys: Option, - // kclvm needs a mapping between the package name and the package path - // to determine the source code path corresponding to different version package. + pub show_hidden: Option, + /// Whether including schema type in JSON/YAML result. + pub include_schema_type_path: Option, + /// kcl needs a mapping between the package name and the package path + /// to determine the source code path corresponding to different version package. pub package_maps: Option>, } @@ -79,6 +82,8 @@ impl SettingsFile { verbose: Some(0), debug: Some(false), sort_keys: Some(false), + show_hidden: Some(false), + include_schema_type_path: Some(false), package_maps: Some(HashMap::default()), }), kcl_options: Some(vec![]), @@ -378,6 +383,12 @@ pub fn merge_settings(settings: &[SettingsFile]) -> SettingsFile { set_if!(result_kcl_cli_configs, verbose, kcl_cli_configs); set_if!(result_kcl_cli_configs, debug, kcl_cli_configs); set_if!(result_kcl_cli_configs, sort_keys, kcl_cli_configs); + set_if!(result_kcl_cli_configs, show_hidden, kcl_cli_configs); + set_if!( + result_kcl_cli_configs, + include_schema_type_path, + kcl_cli_configs + ); set_if!(result_kcl_cli_configs, package_maps, kcl_cli_configs); } } @@ -395,6 +406,55 @@ pub fn merge_settings(settings: &[SettingsFile]) -> SettingsFile { result } +/// Build SettingsPathBuf from args. +pub fn build_settings_pathbuf( + files: &[&str], + setting_files: Option>, + setting_config: Option, +) -> Result { + let mut path = None; + let settings = if let Some(files) = setting_files { + let mut settings = vec![]; + for file in &files { + let s = load_file(file)?; + if !s.input().is_empty() { + path = Some( + PathBuf::from(file) + .parent() + .map(|p| p.to_path_buf()) + .ok_or(anyhow::anyhow!("The parent path of {file} is not found"))?, + ) + } + settings.push(s); + } + merge_settings(&settings) + // If exists default kcl.yaml, load it. + } else if std::fs::metadata(DEFAULT_SETTING_FILE).is_ok() { + path = Some( + PathBuf::from(DEFAULT_SETTING_FILE) + .parent() + .map(|p| p.to_path_buf()) + .ok_or(anyhow::anyhow!( + "The parent path of {DEFAULT_SETTING_FILE} is not found" + ))?, + ); + load_file(DEFAULT_SETTING_FILE)? + } else { + SettingsFile::default() + }; + let mut settings = if let Some(setting_config) = setting_config { + merge_settings(&[settings, setting_config]) + } else { + settings + }; + if let Some(config) = &mut settings.kcl_cli_configs { + if !files.is_empty() { + config.files = Some(files.iter().map(|f| f.to_string()).collect()); + } + } + Ok(SettingsPathBuf::new(path, settings)) +} + #[cfg(test)] mod settings_test { use crate::settings::*; @@ -419,6 +479,8 @@ mod settings_test { assert!(kcl_cli_configs.debug.is_some()); assert!(kcl_cli_configs.path_selector.is_none()); assert!(kcl_cli_configs.overrides.is_none()); + assert!(kcl_cli_configs.include_schema_type_path.is_none()); + assert!(kcl_cli_configs.show_hidden.is_none()); assert_eq!(kcl_cli_configs.sort_keys, Some(true)); if let Some(config_files) = kcl_cli_configs.files { assert!(config_files == files); @@ -457,52 +519,3 @@ mod settings_test { Ok(()) } } - -/// Build SettingsPathBuf from args. -pub fn build_settings_pathbuf( - files: &[&str], - setting_files: Option>, - setting_config: Option, -) -> Result { - let mut path = None; - let settings = if let Some(files) = setting_files { - let mut settings = vec![]; - for file in &files { - let s = load_file(file)?; - if !s.input().is_empty() { - path = Some( - PathBuf::from(file) - .parent() - .map(|p| p.to_path_buf()) - .ok_or(anyhow::anyhow!("The parent path of {file} is not found"))?, - ) - } - settings.push(s); - } - merge_settings(&settings) - // If exists default kcl.yaml, load it. - } else if std::fs::metadata(DEFAULT_SETTING_FILE).is_ok() { - path = Some( - PathBuf::from(DEFAULT_SETTING_FILE) - .parent() - .map(|p| p.to_path_buf()) - .ok_or(anyhow::anyhow!( - "The parent path of {DEFAULT_SETTING_FILE} is not found" - ))?, - ); - load_file(DEFAULT_SETTING_FILE)? - } else { - SettingsFile::default() - }; - let mut settings = if let Some(setting_config) = setting_config { - merge_settings(&[settings, setting_config]) - } else { - settings - }; - if let Some(config) = &mut settings.kcl_cli_configs { - if !files.is_empty() { - config.files = Some(files.iter().map(|f| f.to_string()).collect()); - } - } - Ok(SettingsPathBuf::new(path, settings)) -} diff --git a/kclvm/config/src/testdata/test_cache/kcl.mod b/kclvm/config/src/testdata/test_cache/kcl.mod new file mode 100644 index 000000000..0cb0782b7 --- /dev/null +++ b/kclvm/config/src/testdata/test_cache/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_cache" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/config/src/testdata/test_cache/main.k b/kclvm/config/src/testdata/test_cache/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/config/src/testdata/test_cache/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/config/src/testdata/test_vendor/kcl.mod b/kclvm/config/src/testdata/test_vendor/kcl.mod new file mode 100644 index 000000000..395df1caa --- /dev/null +++ b/kclvm/config/src/testdata/test_vendor/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "test_vendor" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/config/src/testdata/test_vendor/main.k b/kclvm/config/src/testdata/test_vendor/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/config/src/testdata/test_vendor/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/config/src/tests.rs b/kclvm/config/src/tests.rs index a9e952ba6..73f190a0e 100644 --- a/kclvm/config/src/tests.rs +++ b/kclvm/config/src/tests.rs @@ -1,6 +1,15 @@ -use std::{env, path::PathBuf}; +use kclvm_version as version; +use std::{ + collections::HashMap, + env, + fs::{self, File}, + path::{Path, PathBuf}, +}; -use crate::modfile::{get_vendor_home, KCL_PKG_PATH}; +use crate::{ + cache::{load_pkg_cache, save_pkg_cache, CacheOption}, + modfile::{get_vendor_home, KCL_PKG_PATH}, +}; #[test] fn test_vendor_home() { @@ -20,3 +29,46 @@ fn test_vendor_home() { .unwrap(); assert_eq!(get_vendor_home(), kpm_home.display().to_string()) } + +#[test] +fn test_pkg_cache() { + let root = PathBuf::from("./src/testdata/test_cache/") + .canonicalize() + .unwrap() + .display() + .to_string(); + let mut external_pkgs = HashMap::new(); + external_pkgs.insert( + "test_vendor".to_string(), + "./src/testdata/test_vendor".to_string(), + ); + + let lock_path = Path::new(&root) + .join(".kclvm/cache") + .join(format!("{}-{}", version::VERSION, version::CHECK_SUM)) + .join("test_target"); + + fs::create_dir_all(lock_path.clone()).unwrap(); + File::create(lock_path.join("test_vendor.lock")).unwrap(); + + save_pkg_cache( + &root, + "test_target", + "test_vendor", + "test_data", + CacheOption::default(), + &external_pkgs, + ) + .unwrap(); + + assert_eq!( + load_pkg_cache( + &root, + "test_target", + "test_vendor", + CacheOption::default(), + &external_pkgs, + ), + Some("test_data".to_string()) + ) +} diff --git a/kclvm/config/src/vfs.rs b/kclvm/config/src/vfs.rs index 70e4ea5e4..25018222a 100644 --- a/kclvm/config/src/vfs.rs +++ b/kclvm/config/src/vfs.rs @@ -38,9 +38,6 @@ pub fn fix_import_path(root: &str, filepath: &str, import_path: &str) -> String // abspath: import path.to.sub // FixImportPath(root, "path/to/app/file.k", "path.to.sub") => path.to.sub - debug_assert!(!filepath.is_empty()); - debug_assert!(!import_path.is_empty()); - if !import_path.starts_with('.') { return import_path.to_string(); } diff --git a/kclvm/docs/m1-mac-setup.md b/kclvm/docs/m1-mac-setup.md deleted file mode 100644 index 16230a60e..000000000 --- a/kclvm/docs/m1-mac-setup.md +++ /dev/null @@ -1,83 +0,0 @@ -## Env - -+ OS: MacOS Manterey 12.1 -+ CPU: Apple M1 pro, 10 cores -+ Mem: 16GB -+ Rust: cargo 1.59.0 (49d8809dc 2022-02-10) - -## Prerequirements - -1. Make sure you have arm64e-version homebrew installed @`/opt/homebrew`, otherwise install it ➡ - ``` - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - export PATH=/opt/homebrew/bin:$PATH - ``` -2. Install openssl@1.1 ➡ brew install openssl@1.1 -3. Check out openssl installed @`/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib` - -## Install LLVM - -You can install LLVM@12 from brew or build it from source - -### Install LLVM from brew - -1. Install llvm@12 ➡ brew install llvm@12 - -### Build LLVM from Source - -1. Go to the folder where you want to build the LLVM source -2. Download LLVM 12.0.0 source from [http://releases.llvm.org/download.html](http://releases.llvm.org/download.html) and unpack source .tar.xz with tar -xJf [archive] -3. Create a directory where you want to build LLVM files ➡ mkdir build-llvm-12.0.0 -4. Move into the build folder ➡ cd build-llvm-12.0.0; that's where you create `build.sh`. - -``` -#!usr/bin/env sh - -LLVMSRC="" -. "$HOME/.cargo/env" -LLVMTARGET="" - - -cmake \ - -G "Ninja" \ - -DCMAKE_INSTALL_PREFIX="$LLVMTARGET" \ - -DCMAKE_OSX_ARCHITECTURES='arm64' \ - -DCMAKE_C_COMPILER=`which clang` \ - -DCMAKE_CXX_COMPILER=`which clang++` \ - -DCMAKE_BUILD_TYPE="Release" \ - -DLLVM_TARGETS_TO_BUILD="AArch64" \ - -DLLVM_HOST_TRIPLE='aarch64-apple-darwin' \ - -DLLVM_DEFAULT_TARGET_TRIPLE='aarch64-apple-darwin' \ - -DLLVM_ENABLE_WERROR=FALSE \ - "$LLVMSRC" - -cmake --build . -cmake --build . --target install -``` - -5. You may not have ninja installed, so if you have brew installed, you need to install it ninja with ➡ brew install `ninja`. -6. Run the script ➡ sh build.sh -7. Took about 10-15mins. Check out @``. - -## Build KCLVM - -1. Build KCLVM according to `kclvm/README.md`. -2. Took about 5mins. -3. Done! - -## Notes - -1. If you've brew-updating and github brew-submodule-download issue, you'd better use a mirror to speed up. - ``` - cd "$(brew --repo)" - git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git - - cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core" - git remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-core.git - - cd "$(brew --repo)/Library/Taps/homebrew/homebrew-cask" -git remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-cask.git - - echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.aliyun.com/homebrew/homebrew-bottles' >> ~/.zshrc -source ~/.zshrc - ``` \ No newline at end of file diff --git a/kclvm/driver/Cargo.toml b/kclvm/driver/Cargo.toml index 7543b01e2..bbe86a719 100644 --- a/kclvm/driver/Cargo.toml +++ b/kclvm/driver/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-driver" -version = "0.5.0" +version = "0.8.1" edition = "2021" # # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,3 +17,4 @@ walkdir = "2" serde = { version = "1.0", features = ["derive"] } anyhow = { version = "1.0.70", features = ["backtrace"] } +glob = "0.3.1" diff --git a/kclvm/driver/src/kpm.rs b/kclvm/driver/src/kpm.rs new file mode 100644 index 000000000..1d0ec7a29 --- /dev/null +++ b/kclvm/driver/src/kpm.rs @@ -0,0 +1,109 @@ +use crate::kcl; +use crate::lookup_the_nearest_file_dir; +use anyhow::{bail, Result}; +use kclvm_config::modfile::KCL_MOD_FILE; +use kclvm_parser::LoadProgramOptions; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, path::PathBuf, process::Command}; + +/// [`fill_pkg_maps_for_k_file`] will call `kpm metadata` to obtain the metadata +/// of all dependent packages of the kcl package where the current file is located, +/// and fill the relevant information of the external packages into compilation option [`LoadProgramOptions`]. +pub(crate) fn fill_pkg_maps_for_k_file( + k_file_path: PathBuf, + opts: &mut LoadProgramOptions, +) -> Result<()> { + // 1. find the kcl.mod dir for the kcl package contains 'k_file_path'. + match lookup_the_nearest_file_dir(k_file_path, KCL_MOD_FILE) { + Some(mod_dir) => { + // 2. get the module metadata. + let metadata = fetch_metadata(mod_dir.canonicalize()?)?; + // 3. fill the external packages local paths into compilation option [`LoadProgramOptions`]. + let maps: HashMap = metadata + .packages + .into_iter() + .map(|(pname, pkg)| (pname, pkg.manifest_path.display().to_string())) + .collect(); + opts.package_maps.extend(maps); + } + None => return Ok(()), + }; + + Ok(()) +} + +#[derive(Deserialize, Serialize, Default, Debug, Clone)] +/// [`Metadata`] is the metadata of the current KCL module, +/// currently only the mapping between the name and path of the external dependent package is included. +pub struct Metadata { + pub packages: HashMap, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +/// [`Package`] is a kcl package. +pub struct Package { + /// Name as given in the `kcl.mod` + pub name: String, + /// Path containing the `kcl.mod` + pub manifest_path: PathBuf, +} + +impl Metadata { + /// [`parse`] will parse the json string into [`Metadata`]. + fn parse(data: String) -> Result { + let meta = serde_json::from_str(data.as_ref())?; + Ok(meta) + } +} + +/// [`fetch_metadata`] will call `kcl mod metadata` to obtain the metadata. +pub fn fetch_metadata(manifest_path: PathBuf) -> Result { + match Command::new(kcl()) + .arg("mod") + .arg("metadata") + .current_dir(manifest_path) + .output() + { + Ok(output) => { + if !output.status.success() { + bail!( + "fetch metadata failed with error: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + Ok(Metadata::parse( + String::from_utf8_lossy(&output.stdout).to_string(), + )?) + } + Err(err) => bail!("fetch metadata failed with error: {}", err), + } +} + +/// [`update_dependencies`] will call `kcl mod update` to update the dependencies. +pub fn update_dependencies(work_dir: PathBuf) -> Result<()> { + match lookup_the_nearest_file_dir(work_dir.clone(), KCL_MOD_FILE) { + Some(mod_dir) => { + match Command::new(kcl()) + .arg("mod") + .arg("update") + .current_dir(mod_dir) + .output() + { + Ok(output) => { + if !output.status.success() { + bail!( + "update failed with error: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + Ok(()) + } + Err(err) => bail!("update failed with error: {}", err), + } + } + None => bail!( + "Manifest file '{}' not found in directory hierarchy", + KCL_MOD_FILE + ), + } +} diff --git a/kclvm/driver/src/kpm_metadata.rs b/kclvm/driver/src/kpm_metadata.rs deleted file mode 100644 index a8d615fa2..000000000 --- a/kclvm/driver/src/kpm_metadata.rs +++ /dev/null @@ -1,143 +0,0 @@ -use anyhow::{bail, Ok, Result}; -use kclvm_parser::LoadProgramOptions; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, env, iter, path::PathBuf, process::Command}; - -const MANIFEST_FILE: &str = "kcl.mod"; - -/// [`fill_pkg_maps_for_k_file`] will call `kpm metadata` to obtain the metadata -/// of all dependent packages of the kcl package where the current file is located, -/// and fill the relevant information of the external packages into compilation option [`LoadProgramOptions`]. -pub(crate) fn fill_pkg_maps_for_k_file( - k_file_path: PathBuf, - opts: &mut LoadProgramOptions, -) -> Result<()> { - // 1. find the kcl.mod dir for the kcl package contains 'k_file_path'. - match lookup_the_nearest_file_dir(k_file_path, MANIFEST_FILE) { - Some(mod_dir) => { - // 2. call `kpm metadata`. - let metadata = fetch_metadata(mod_dir.canonicalize()?)?; - // 3. fill the external packages local paths into compilation option [`LoadProgramOptions`]. - let maps: HashMap = metadata - .packages - .into_iter() - .map(|(pname, pkg)| (pname, pkg.manifest_path.display().to_string())) - .collect(); - opts.package_maps.extend(maps); - } - None => return Ok(()), - }; - - return Ok(()); -} - -#[derive(Deserialize, Serialize, Default, Debug, Clone)] -/// [`Metadata`] is the metadata of the current KCL package, -/// currently only the mapping between the name and path of the external dependent package is included. -pub struct Metadata { - pub packages: HashMap, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -/// [`Package`] is a kcl package. -pub struct Package { - /// Name as given in the `kcl.mod` - pub name: String, - /// Path containing the `kcl.mod` - pub manifest_path: PathBuf, -} - -impl Metadata { - /// [`parse`] will parse the json string into [`Metadata`]. - fn parse(data: String) -> Result { - let meta = serde_json::from_str(data.as_ref())?; - Ok(meta) - } -} - -/// [`fetch_metadata`] will call `kpm metadata` to obtain the metadata. -pub fn fetch_metadata(manifest_path: PathBuf) -> Result { - use std::result::Result::Ok; - match Command::new(kpm()) - .arg("metadata") - .current_dir(manifest_path) - .output() - { - Ok(output) => { - if !output.status.success() { - bail!( - "fetch metadata failed with error: {}", - String::from_utf8_lossy(&output.stderr) - ); - } - Ok(Metadata::parse( - String::from_utf8_lossy(&output.stdout).to_string(), - )?) - } - Err(err) => bail!("fetch metadata failed with error: {}", err), - } -} - -/// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. -/// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] -pub(crate) fn lookup_the_nearest_file_dir( - from: PathBuf, - the_nearest_file: &str, -) -> Option { - let mut current_dir = from; - - loop { - let found_path = current_dir.join(the_nearest_file); - if found_path.is_file() { - return Some(current_dir.canonicalize().ok()?); - } - - match current_dir.parent() { - Some(parent) => current_dir = parent.to_path_buf(), - None => return None, - } - } -} - -/// [`kpm`] will return the path for executable kpm binary. -pub fn kpm() -> PathBuf { - get_path_for_executable("kpm") -} - -/// [`get_path_for_executable`] will return the path for [`executable_name`]. -pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { - // The current implementation checks $PATH for an executable to use: - // `` - // example: for kpm, this tries just `kpm`, which will succeed if `kpm` is on the $PATH - - if lookup_in_path(executable_name) { - return executable_name.into(); - } - - executable_name.into() -} - -/// [`lookup_in_path`] will search for an executable file [`exec`] in the environment variable ‘PATH’. -/// If found, return true, otherwise return false. -fn lookup_in_path(exec: &str) -> bool { - let paths = env::var_os("PATH").unwrap_or_default(); - env::split_paths(&paths) - .map(|path| path.join(exec)) - .find_map(probe) - .is_some() -} - -/// [`probe`] check if the given path points to a file. -/// If it does, return [`Some`] of the path. -/// If not, check if adding the current operating system's executable file extension (if any) to the path points to a file. -/// If it does, return [`Some`] of the path with the extension added. -/// If neither, return [`None`]. -fn probe(path: PathBuf) -> Option { - let with_extension = match env::consts::EXE_EXTENSION { - "" => None, - it => Some(path.with_extension(it)), - }; - iter::once(path) - .chain(with_extension) - .find(|it| it.is_file()) -} diff --git a/kclvm/driver/src/lib.rs b/kclvm/driver/src/lib.rs index b2de64d93..99559f214 100644 --- a/kclvm/driver/src/lib.rs +++ b/kclvm/driver/src/lib.rs @@ -1,26 +1,58 @@ use anyhow::Result; pub mod arguments; -pub mod kpm_metadata; +pub mod kpm; pub const DEFAULT_PROJECT_FILE: &str = "project.yaml"; #[cfg(test)] mod tests; -use kclvm_ast::ast; +use glob::glob; use kclvm_config::{ - modfile::{KCL_FILE_EXTENSION, KCL_FILE_SUFFIX, KCL_MOD_PATH_ENV}, + modfile::{get_pkg_root, KCL_FILE_EXTENSION, KCL_FILE_SUFFIX, KCL_MOD_PATH_ENV}, + path::ModRelativePath, settings::{build_settings_pathbuf, DEFAULT_SETTING_FILE}, }; use kclvm_parser::LoadProgramOptions; use kclvm_utils::path::PathPrefix; -use kpm_metadata::fill_pkg_maps_for_k_file; +use kpm::fill_pkg_maps_for_k_file; +use std::env; +use std::iter; use std::{ - fs::{self, read_dir}, + collections::HashSet, + fs::read_dir, io::{self, ErrorKind}, path::{Path, PathBuf}, }; use walkdir::WalkDir; +/// Expand the file pattern to a list of files. +pub fn expand_if_file_pattern(file_pattern: String) -> Result, String> { + let paths = glob(&file_pattern).map_err(|_| format!("invalid file pattern {file_pattern}"))?; + let mut matched_files = vec![]; + + for path in paths.flatten() { + matched_files.push(path.to_string_lossy().to_string()); + } + + Ok(matched_files) +} + +pub fn expand_input_files(k_files: &[String]) -> Vec { + let mut res = vec![]; + for file in k_files { + if let Ok(files) = expand_if_file_pattern(file.to_string()) { + if !files.is_empty() { + res.extend(files); + } else { + res.push(file.to_string()) + } + } else { + res.push(file.to_string()) + } + } + res +} + /// Normalize input files with the working directory and replace ${KCL_MOD} with the module root path. pub fn canonicalize_input_files( k_files: &[String], @@ -28,23 +60,23 @@ pub fn canonicalize_input_files( check_exist: bool, ) -> Result, String> { let mut kcl_paths = Vec::::new(); - // The first traversal changes the relative path to an absolute path - for (_, file) in k_files.iter().enumerate() { + for file in k_files.iter() { let path = Path::new(file); + let is_absolute = path.is_absolute(); let is_exist_maybe_symlink = path.exists(); // If the input file or path is a relative path and it is not a absolute path in the KCL module VFS, // join with the work directory path and convert it to a absolute path. - - let abs_path = if !is_absolute && !file.starts_with(KCL_MOD_PATH_ENV) { + let path = ModRelativePath::from(file.to_string()); + let abs_path = if !is_absolute && !path.is_relative_path().map_err(|err| err.to_string())? { let filepath = Path::new(&work_dir).join(file); match filepath.canonicalize() { Ok(path) => Some(path.adjust_canonicalization()), Err(_) => { if check_exist { return Err(format!( - "Cannot find the kcl file, please check whether the file path {}", + "Cannot find the kcl file, please check the file path {}", file )); } @@ -56,12 +88,12 @@ pub fn canonicalize_input_files( }; // If the input file or path is a symlink, convert it to a real path. let real_path = if is_exist_maybe_symlink { - match PathBuf::from(file).canonicalize() { + match PathBuf::from(file.to_string()).canonicalize() { Ok(real_path) => Some(String::from(real_path.to_str().unwrap())), Err(_) => { if check_exist { return Err(format!( - "Cannot find the kcl file, please check whether the file path {}", + "Cannot find the kcl file, please check the file path {}", file )); } @@ -76,7 +108,7 @@ pub fn canonicalize_input_files( } // Get the root path of the project - let pkgroot = kclvm_config::modfile::get_pkg_root_from_paths(&kcl_paths)?; + let pkgroot = kclvm_config::modfile::get_pkg_root_from_paths(&kcl_paths, work_dir)?; // The second traversal replaces ${KCL_MOD} with the project root path kcl_paths = kcl_paths @@ -129,17 +161,6 @@ pub fn lookup_compile_unit( let mut load_opt = kclvm_parser::LoadProgramOptions { work_dir: work_dir.clone(), - cmd_args: if let Some(options) = setting.clone().kcl_options { - options - .iter() - .map(|o| ast::CmdArgSpec { - name: o.key.to_string(), - value: o.value.to_string(), - }) - .collect() - } else { - vec![] - }, ..Default::default() }; match canonicalize_input_files(&files, work_dir, true) { @@ -170,12 +191,12 @@ pub fn lookup_compile_unit( } } } - return (vec![file.to_string()], Some(load_opt)); + (vec![file.to_string()], Some(load_opt)) } } } -pub fn lookup_setting_files(dir: &PathBuf) -> Vec { +pub fn lookup_setting_files(dir: &Path) -> Vec { let mut settings = vec![]; if let Ok(p) = lookup_kcl_yaml(dir) { settings.push(p); @@ -183,8 +204,8 @@ pub fn lookup_setting_files(dir: &PathBuf) -> Vec { settings } -pub fn lookup_kcl_yaml(dir: &PathBuf) -> io::Result { - let mut path = dir.clone(); +pub fn lookup_kcl_yaml(dir: &Path) -> io::Result { + let mut path = dir.to_path_buf(); path.push(DEFAULT_SETTING_FILE); if path.is_file() { Ok(path) @@ -201,7 +222,6 @@ pub fn lookup_kcl_yaml(dir: &PathBuf) -> io::Result { /// to find a `compile unit` that contains all definitions /// Given a file path, search for the nearest "kcl.yaml" file or the nearest "project.yaml" file. /// If a "kcl.yaml" file is found, return the path of the directory containing the file. -/// If a "project.yaml" file is found, return the path of the first directory containing a "kcl.yaml" file in that project. /// If none of these files are found, return an error indicating that the files were not found. /// /// Example: @@ -218,7 +238,6 @@ pub fn lookup_kcl_yaml(dir: &PathBuf) -> io::Result { /// | | +-- stack.yaml /// | +-- project.yaml /// -/// If the input file is project/base/base.k, it will return Path("project/prod") /// If the input file is project/prod/main.k or project/test/main.k, it will return /// Path("project/prod") or Path("project/test") pub fn lookup_compile_unit_path(file: &str) -> io::Result { @@ -232,19 +251,6 @@ pub fn lookup_compile_unit_path(file: &str) -> io::Result { // If find "kcl.yaml", the input file is in a stack, return the // path of this stack return Ok(PathBuf::from(p)); - } else if entry.file_name() == DEFAULT_PROJECT_FILE { - // If find "project.yaml", the input file may be in the `base` - // directory of a project, return the path of the first stack - // of this project - let project_path = PathBuf::from(p); - for e in read_dir(project_path)? { - if let Ok(entry) = e { - let path = entry.path(); - if path.is_dir() && lookup_kcl_yaml(&path).is_ok() { - return Ok(path); - } - } - } } } } @@ -257,11 +263,16 @@ pub fn lookup_compile_unit_path(file: &str) -> io::Result { /// Get kcl files from path. pub fn get_kcl_files>(path: P, recursively: bool) -> Result> { let mut files = vec![]; - for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) { + let walkdir = if recursively { + WalkDir::new(path) + } else { + WalkDir::new(path).max_depth(1) + }; + for entry in walkdir.into_iter().filter_map(|e| e.ok()) { let path = entry.path(); if path.is_file() { let file = path.to_str().unwrap(); - if file.ends_with(KCL_FILE_SUFFIX) && (recursively || entry.depth() == 1) { + if file.ends_with(KCL_FILE_SUFFIX) { files.push(file.to_string()) } } @@ -269,3 +280,145 @@ pub fn get_kcl_files>(path: P, recursively: bool) -> Result Result> { + let mut dir_list: Vec = Vec::new(); + let mut dir_map: HashSet = HashSet::new(); + let cwd = std::env::current_dir()?; + + let pkgpath = if pkgpath.is_empty() { + cwd.to_string_lossy().to_string() + } else { + pkgpath.to_string() + }; + + let include_sub_pkg = pkgpath.ends_with("/..."); + let pkgpath = if include_sub_pkg { + pkgpath.trim_end_matches("/...").to_string() + } else { + pkgpath + }; + + if pkgpath != "." && pkgpath.ends_with('.') { + return Ok(Vec::new()); + } + + if pkgpath.is_empty() { + return Ok(Vec::new()); + } + + match pkgpath.chars().next() { + Some('.') => { + let pkgpath = Path::new(&cwd).join(&pkgpath); + pkgpath.to_string_lossy().to_string() + } + _ => { + if Path::new(&pkgpath).is_absolute() { + pkgpath.clone() + } else if !pkgpath.contains('/') && !pkgpath.contains('\\') { + pkgpath.replace('.', "/") + } else { + let pkgroot = + get_pkg_root(cwd.to_str().ok_or(anyhow::anyhow!("cwd path not found"))?) + .unwrap_or_default(); + if !pkgroot.is_empty() { + PathBuf::from(pkgroot) + .join(&pkgpath) + .to_string_lossy() + .to_string() + } else { + Path::new(&cwd).join(&pkgpath).to_string_lossy().to_string() + } + } + } + }; + + if !include_sub_pkg { + return Ok(vec![pkgpath]); + } + + for entry in WalkDir::new(&pkgpath).into_iter().filter_map(|e| e.ok()) { + let path = entry.path(); + if !path.is_dir() + && path.extension().and_then(|ext| ext.to_str()) == Some(KCL_FILE_EXTENSION) + && !path + .file_name() + .map(|name| name.to_string_lossy().starts_with('_')) + .unwrap_or(false) + { + if let Some(dir) = path.parent().map(|p| p.to_string_lossy().to_string()) { + if !dir_map.contains(&dir) { + dir_list.push(dir.clone()); + dir_map.insert(dir); + } + } + } + } + + Ok(dir_list) +} + +/// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. +/// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] +pub(crate) fn lookup_the_nearest_file_dir( + from: PathBuf, + the_nearest_file: &str, +) -> Option { + let mut current_dir = from; + + loop { + let found_path = current_dir.join(the_nearest_file); + if found_path.is_file() { + return current_dir.canonicalize().ok(); + } + + match current_dir.parent() { + Some(parent) => current_dir = parent.to_path_buf(), + None => return None, + } + } +} + +/// [`kcl`] will return the path for executable kcl binary. +pub fn kcl() -> PathBuf { + get_path_for_executable("kcl") +} + +/// [`get_path_for_executable`] will return the path for [`executable_name`]. +pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { + // The current implementation checks $PATH for an executable to use: + // `` + // example: for , this tries just , which will succeed if is on the $PATH + + if lookup_in_path(executable_name) { + return executable_name.into(); + } + + executable_name.into() +} + +/// [`lookup_in_path`] will search for an executable file [`exec`] in the environment variable ‘PATH’. +/// If found, return true, otherwise return false. +fn lookup_in_path(exec: &str) -> bool { + let paths = env::var_os("PATH").unwrap_or_default(); + env::split_paths(&paths) + .map(|path| path.join(exec)) + .find_map(probe) + .is_some() +} + +/// [`probe`] check if the given path points to a file. +/// If it does, return [`Some`] of the path. +/// If not, check if adding the current operating system's executable file extension (if any) to the path points to a file. +/// If it does, return [`Some`] of the path with the extension added. +/// If neither, return [`None`]. +fn probe(path: PathBuf) -> Option { + let with_extension = match env::consts::EXE_EXTENSION { + "" => None, + it => Some(path.with_extension(it)), + }; + iter::once(path) + .chain(with_extension) + .find(|it| it.is_file()) +} diff --git a/kclvm/driver/src/test_data/expand_file_pattern/KCL_MOD b/kclvm/driver/src/test_data/expand_file_pattern/KCL_MOD new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl.mod b/kclvm/driver/src/test_data/expand_file_pattern/kcl.mod new file mode 100644 index 000000000..f647ff5c5 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "expand_file_pattern" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl.mod b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl.mod new file mode 100644 index 000000000..ab572545d --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl1" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/kcl.mod b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/kcl.mod new file mode 100644 index 000000000..5fb058acd --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl2" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/main.k b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl2/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/kcl.mod b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/kcl.mod new file mode 100644 index 000000000..98f429002 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl4" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/main.k b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/kcl4/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl1/main.k b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl1/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl3/kcl.mod b/kclvm/driver/src/test_data/expand_file_pattern/kcl3/kcl.mod new file mode 100644 index 000000000..b99124970 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl3/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl3" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/expand_file_pattern/kcl3/main.k b/kclvm/driver/src/test_data/expand_file_pattern/kcl3/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/kcl3/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/expand_file_pattern/main.k b/kclvm/driver/src/test_data/expand_file_pattern/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/expand_file_pattern/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/kpm_metadata/kcl.mod b/kclvm/driver/src/test_data/kpm_metadata/kcl.mod index 86da3d75b..c8325a3b6 100644 --- a/kclvm/driver/src/test_data/kpm_metadata/kcl.mod +++ b/kclvm/driver/src/test_data/kpm_metadata/kcl.mod @@ -4,4 +4,4 @@ edition = "0.0.1" version = "0.0.4" [dependencies] -kcl4 = { git = "", tag = "v0.0.1" } \ No newline at end of file +kcl4 = { git = "test_url", tag = "v0.0.1" } diff --git a/kclvm/driver/src/test_data/kpm_metadata/kcl.mod.lock b/kclvm/driver/src/test_data/kpm_metadata/kcl.mod.lock index b1f5f282c..64e81ba70 100644 --- a/kclvm/driver/src/test_data/kpm_metadata/kcl.mod.lock +++ b/kclvm/driver/src/test_data/kpm_metadata/kcl.mod.lock @@ -4,5 +4,4 @@ full_name = "kcl4_v0.0.1" version = "v0.0.1" sum = "cpyqJwwjqCvast6QNAiYuevgAIEH1p72OqctwGHU79Q=" - url = "" - tag = "v0.0.1" + url = "test_url" diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/kcl.mod b/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/kcl.mod new file mode 100644 index 000000000..2f4e3935d --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "dep-with-line" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/kcl.mod.lock b/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/kcl.mod.lock new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/main.k b/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/main.k new file mode 100644 index 000000000..bfdcb0932 --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_metadata_with_line/dep-with-line/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World dep-with-line!' \ No newline at end of file diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod new file mode 100644 index 000000000..34b4be7eb --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "main_pkg" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +dep-with-line = { path = "../dep-with-line" } diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod.lock b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod.lock new file mode 100644 index 000000000..9c32b8db3 --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/kcl.mod.lock @@ -0,0 +1,6 @@ +[dependencies] + [dependencies.dep-with-line] + name = "dep-with-line" + full_name = "dep-with-line_" + sum = "O2Z1djaB1lC38kNfhwUUYAlqGKE7seUqqys3DPcJfEw=" + path = "../dep-with-line" diff --git a/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/main.k b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/main.k new file mode 100644 index 000000000..e78a5fba4 --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_metadata_with_line/main_pkg/main.k @@ -0,0 +1,3 @@ +import dep_with_line as dwl + +The_first_kcl_program = dwl.The_first_kcl_program \ No newline at end of file diff --git a/kclvm/driver/src/test_data/kpm_update/kcl.mod b/kclvm/driver/src/test_data/kpm_update/kcl.mod new file mode 100644 index 000000000..59b31b49a --- /dev/null +++ b/kclvm/driver/src/test_data/kpm_update/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "kpm_update" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +helloworld = "0.1.0" diff --git a/kclvm/driver/src/test_data/pkg_list/pkg1/pkg.k b/kclvm/driver/src/test_data/pkg_list/pkg1/pkg.k new file mode 100644 index 000000000..d25d49e0f --- /dev/null +++ b/kclvm/driver/src/test_data/pkg_list/pkg1/pkg.k @@ -0,0 +1 @@ +a = 1 \ No newline at end of file diff --git a/kclvm/driver/src/test_data/pkg_list/pkg1/sub_pkg1/pkg.k b/kclvm/driver/src/test_data/pkg_list/pkg1/sub_pkg1/pkg.k new file mode 100644 index 000000000..d25d49e0f --- /dev/null +++ b/kclvm/driver/src/test_data/pkg_list/pkg1/sub_pkg1/pkg.k @@ -0,0 +1 @@ +a = 1 \ No newline at end of file diff --git a/kclvm/driver/src/test_data/pkg_list/pkg2/pkg.k b/kclvm/driver/src/test_data/pkg_list/pkg2/pkg.k new file mode 100644 index 000000000..a668ca34b --- /dev/null +++ b/kclvm/driver/src/test_data/pkg_list/pkg2/pkg.k @@ -0,0 +1 @@ +a = 2 \ No newline at end of file diff --git a/kclvm/driver/src/test_data/test_vendor/.kpm/config/kpm.json b/kclvm/driver/src/test_data/test_vendor/.kpm/config/kpm.json new file mode 100644 index 000000000..7c459d9c7 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/.kpm/config/kpm.json @@ -0,0 +1 @@ +{"DefaultOciRegistry":"ghcr.io","DefaultOciRepo":"kcl-lang","DefaultOciPlainHttp":false} \ No newline at end of file diff --git a/kclvm/driver/src/test_data/test_vendor/.kpm/config/package-cache b/kclvm/driver/src/test_data/test_vendor/.kpm/config/package-cache new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/README.md b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/README.md new file mode 100644 index 000000000..4d63fef38 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/README.md @@ -0,0 +1,2 @@ +## Introduction +This is a kcl package named helloworld. diff --git a/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/artifacthub-pkg.yaml b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/artifacthub-pkg.yaml new file mode 100644 index 000000000..b8a9ecf50 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/0.0.1/artifacthub-pkg.yaml @@ -0,0 +1,25 @@ +version: 0.0.1 +name: helloworld +displayName: helloworld +createdAt: "2023-10-24T12:25:12Z" +description: "This is a KCL package" +links: +- name: KCL homepage + url: https://kcl-lang.io/ +- name: KCL repo + url: https://github.com/kcl-lang/kcl +install: | + #### Add `helloworld` with tag `0.0.1` as dependency + ``` + kpm add helloworld:0.0.1 + ``` + + #### Pull `helloworld` with tag `0.0.1` to local + ``` + kpm pull helloworld:0.0.1 + ``` +maintainers: +- name: kcl-lang.io + email: kcl-lang.io@domainsbyproxy.com +provider: + name: kcl-lang.io diff --git a/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/README.md b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/README.md new file mode 100644 index 000000000..4d63fef38 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/README.md @@ -0,0 +1,2 @@ +## Introduction +This is a kcl package named helloworld. diff --git a/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/kcl.mod b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/kcl.mod new file mode 100644 index 000000000..d71c44407 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "helloworld" +edition = "*" +version = "0.1.0" + diff --git a/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/main.k b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/driver/src/test_data/test_vendor/helloworld_0.1.0/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/driver/src/tests.rs b/kclvm/driver/src/tests.rs index 80c125c5e..d98d30c8c 100644 --- a/kclvm/driver/src/tests.rs +++ b/kclvm/driver/src/tests.rs @@ -1,13 +1,15 @@ use std::path::{Path, PathBuf}; -use std::{env, panic}; +use std::{env, fs, panic}; use kclvm_config::modfile::get_vendor_home; use kclvm_config::settings::KeyValuePair; use kclvm_parser::LoadProgramOptions; +use walkdir::WalkDir; use crate::arguments::parse_key_value_pair; -use crate::canonicalize_input_files; -use crate::kpm_metadata::{fetch_metadata, fill_pkg_maps_for_k_file, lookup_the_nearest_file_dir}; +use crate::kpm::{fetch_metadata, fill_pkg_maps_for_k_file, update_dependencies}; +use crate::lookup_the_nearest_file_dir; +use crate::{canonicalize_input_files, expand_input_files, get_pkg_list}; #[test] fn test_canonicalize_input_files() { @@ -24,6 +26,88 @@ fn test_canonicalize_input_files() { assert!(canonicalize_input_files(&input_files, work_dir, true).is_err()); } +#[test] +fn test_expand_input_files_with_kcl_mod() { + let path = PathBuf::from("src/test_data/expand_file_pattern"); + let input_files = vec![ + path.join("**").join("main.k").to_string_lossy().to_string(), + "${KCL_MOD}/src/test_data/expand_file_pattern/KCL_MOD".to_string(), + ]; + let expected_files = vec![ + path.join("kcl1/kcl2/main.k").to_string_lossy().to_string(), + path.join("kcl1/kcl4/main.k").to_string_lossy().to_string(), + path.join("kcl1/main.k").to_string_lossy().to_string(), + path.join("kcl3/main.k").to_string_lossy().to_string(), + path.join("main.k").to_string_lossy().to_string(), + "${KCL_MOD}/src/test_data/expand_file_pattern/KCL_MOD".to_string(), + ]; + let got_paths: Vec = expand_input_files(&input_files) + .iter() + .map(|s| s.replace(['/', '\\'], "")) + .collect(); + let expect_paths: Vec = expected_files + .iter() + .map(|s| s.replace(['/', '\\'], "")) + .collect(); + assert_eq!(got_paths, expect_paths); +} + +#[test] +#[cfg(not(windows))] +fn test_expand_input_files() { + let input_files = vec!["./src/test_data/expand_file_pattern/**/main.k".to_string()]; + let mut expected_files = vec![ + Path::new("src/test_data/expand_file_pattern/kcl1/kcl2/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl3/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl1/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl1/kcl4/main.k") + .to_string_lossy() + .to_string(), + ]; + expected_files.sort(); + let mut input = expand_input_files(&input_files); + input.sort(); + assert_eq!(input, expected_files); + + let input_files = vec![ + "./src/test_data/expand_file_pattern/kcl1/main.k".to_string(), + "./src/test_data/expand_file_pattern/**/main.k".to_string(), + ]; + let mut expected_files = vec![ + Path::new("src/test_data/expand_file_pattern/kcl1/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl1/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl1/kcl2/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl1/kcl4/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/kcl3/main.k") + .to_string_lossy() + .to_string(), + Path::new("src/test_data/expand_file_pattern/main.k") + .to_string_lossy() + .to_string(), + ]; + expected_files.sort(); + let mut input = expand_input_files(&input_files); + input.sort(); + assert_eq!(input, expected_files); +} + #[test] fn test_parse_key_value_pair() { let cases = [ @@ -78,12 +162,23 @@ fn test_parse_key_value_pair() { ), ]; for (value, pair) in cases { - let result = parse_key_value_pair(&value).unwrap(); + let result = parse_key_value_pair(value).unwrap(); assert_eq!(result.key, pair.key); assert_eq!(result.value, pair.value); } } +fn clear_path(path: PathBuf) { + WalkDir::new(path) + .into_iter() + .filter_map(|e| e.ok()) + .for_each(|e| { + fs::remove_file(e.path()) + .or_else(|_| fs::remove_dir(e.path())) + .ok(); + }); +} + #[test] fn test_parse_key_value_pair_fail() { let cases = ["=v", "k=", "="]; @@ -92,7 +187,39 @@ fn test_parse_key_value_pair_fail() { } } -#[test] +fn test_fill_pkg_maps_for_k_file_with_line() { + let root_path = PathBuf::from(".") + .join("src") + .join("test_data") + .join("kpm_metadata_with_line"); + + let main_pkg_path = root_path.join("main_pkg").join("main.k"); + let dep_with_line_path = root_path.join("dep-with-line"); + + let mut opts = LoadProgramOptions::default(); + assert_eq!(format!("{:?}", opts.package_maps), "{}"); + + let res = fill_pkg_maps_for_k_file(main_pkg_path.clone(), &mut opts); + assert!(res.is_ok()); + + let pkg_maps = opts.package_maps.clone(); + assert_eq!(pkg_maps.len(), 1); + assert!(pkg_maps.get("dep_with_line").is_some()); + + assert_eq!( + PathBuf::from(pkg_maps.get("dep_with_line").unwrap().clone()) + .canonicalize() + .unwrap() + .display() + .to_string(), + dep_with_line_path + .canonicalize() + .unwrap() + .display() + .to_string() + ); +} + fn test_fill_pkg_maps_for_k_file() { let path = PathBuf::from(".") .join("src") @@ -134,6 +261,8 @@ fn test_fill_pkg_maps_for_k_file() { .display() .to_string() ); + + clear_path(vendor_path.join(".kpm")) } #[test] @@ -143,7 +272,7 @@ fn test_lookup_the_nearest_file_dir() { .join("test_data") .join("kpm_metadata"); let result = lookup_the_nearest_file_dir(path.clone(), "kcl.mod"); - assert_eq!(result.is_some(), true); + assert!(result.is_some()); assert_eq!( result.unwrap().display().to_string(), path.canonicalize().unwrap().display().to_string() @@ -151,7 +280,7 @@ fn test_lookup_the_nearest_file_dir() { let main_path = path.join("subdir").join("main.k"); let result = lookup_the_nearest_file_dir(main_path, "kcl.mod"); - assert_eq!(result.is_some(), true); + assert!(result.is_some()); assert_eq!( result.unwrap().display().to_string(), path.canonicalize().unwrap().display().to_string() @@ -159,6 +288,17 @@ fn test_lookup_the_nearest_file_dir() { } #[test] +fn test_fetch_metadata_in_order() { + test_fetch_metadata(); + println!("test_fetch_metadata() passed"); + test_fill_pkg_maps_for_k_file(); + println!("test_fill_pkg_maps_for_k_file() passed"); + test_fill_pkg_maps_for_k_file_with_line(); + println!("test_fill_pkg_maps_for_k_file_with_line() passed"); + test_update_dependencies(); + println!("test_update_dependencies() passed"); +} + fn test_fetch_metadata() { let path = PathBuf::from(".") .join("src") @@ -177,13 +317,18 @@ fn test_fetch_metadata() { let vendor_home = get_vendor_home(); let metadata = fetch_metadata(path.clone()); - assert_eq!(metadata.is_err(), false); + // Show more information when the test fails. + println!("{:?}", metadata); + assert!(metadata.is_ok()); let pkgs = metadata.unwrap().packages.clone(); assert_eq!(pkgs.len(), 1); assert!(pkgs.get("kcl4").is_some()); - assert_eq!(pkgs.get("kcl4").clone().unwrap().name, "kcl4"); + assert_eq!(pkgs.get("kcl4").unwrap().name, "kcl4"); assert_eq!( - PathBuf::from(pkgs.get("kcl4").unwrap().manifest_path.clone()) + pkgs.get("kcl4") + .unwrap() + .manifest_path + .clone() .canonicalize() .unwrap() .display() @@ -195,6 +340,7 @@ fn test_fetch_metadata() { .display() .to_string() ); + clear_path(vendor_path.join(".kpm")) } #[test] @@ -216,3 +362,24 @@ fn test_fetch_metadata_invalid() { Err(e) => panic!("The method should not panic forever.: {:?}", e), } } + +#[test] +fn test_get_pkg_list() { + assert_eq!(get_pkg_list("./src/test_data/pkg_list/").unwrap().len(), 1); + assert_eq!( + get_pkg_list("./src/test_data/pkg_list/...").unwrap().len(), + 3 + ); +} + +fn test_update_dependencies() { + let path = PathBuf::from(".") + .join("src") + .join("test_data") + .join("kpm_update"); + + let update_mod = update_dependencies(path.clone()); + // Show more information when the test fails. + println!("{:?}", update_mod); + assert!(update_mod.is_ok()); +} diff --git a/kclvm/error/Cargo.toml b/kclvm/error/Cargo.toml index 097b0dcef..99d8a9181 100644 --- a/kclvm/error/Cargo.toml +++ b/kclvm/error/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-error" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,6 +16,7 @@ kclvm-runtime = {path = "../runtime"} anyhow = "1.0" tracing = "0.1" atty = "0.2" -annotate-snippets = { version = "0.9.0", default-features = false, features = ["color"] } +annotate-snippets = { version = "0.9.2", default-features = false, features = ["color"] } termize = "0.1.1" indexmap = "1.0" +serde_json = "1.0.86" diff --git a/kclvm/error/src/diagnostic.rs b/kclvm/error/src/diagnostic.rs index 2ba7fdd27..4d2a1cdc1 100644 --- a/kclvm/error/src/diagnostic.rs +++ b/kclvm/error/src/diagnostic.rs @@ -95,8 +95,8 @@ impl From for Position { } impl Diagnostic { - pub fn new(level: Level, message: &str, pos: Position) -> Self { - Diagnostic::new_with_code(level, message, None, pos, None) + pub fn new(level: Level, message: &str, range: Range) -> Self { + Diagnostic::new_with_code(level, message, None, range, None, None) } /// New a diagnostic with error code. @@ -104,16 +104,18 @@ impl Diagnostic { level: Level, message: &str, note: Option<&str>, - pos: Position, + range: Range, code: Option, + suggestions: Option>, ) -> Self { Diagnostic { level, messages: vec![Message { - pos, + range, style: Style::LineAndColumn, message: message.to_string(), - note: note.map(|s| s.to_string()), + note: note.map(String::from), + suggested_replacement: suggestions, }], code, } @@ -125,18 +127,22 @@ impl Diagnostic { } } +pub type Range = (Position, Position); + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Message { - pub pos: Position, + pub range: Range, pub style: Style, pub message: String, pub note: Option, + pub suggested_replacement: Option>, } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum DiagnosticId { Error(ErrorKind), Warning(WarningKind), + Suggestions, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -144,6 +150,7 @@ pub enum Level { Error, Warning, Note, + Suggestions, } impl Level { @@ -152,6 +159,7 @@ impl Level { Level::Error => "error", Level::Warning => "warning", Level::Note => "note", + Level::Suggestions => "suggestions", } } } diff --git a/kclvm/error/src/error.rs b/kclvm/error/src/error.rs index 10fdcdce6..f6d5df5c5 100644 --- a/kclvm/error/src/error.rs +++ b/kclvm/error/src/error.rs @@ -38,13 +38,19 @@ macro_rules! register_warnings { // Error messages for EXXXX errors. Each message should start and end with a // new line. register_errors! { + // E1XXX Syntax Errors E1001: ErrorKind::InvalidSyntax, include_str!("./error_codes/E1001.md"), + E1002: ErrorKind::TabError, include_str!("./error_codes/E1002.md"), + E1003: ErrorKind::IndentationError, include_str!("./error_codes/E1003.md"), + E1I37: ErrorKind::IllegalArgumentSyntax, include_str!("./error_codes/E1I37.md"), + // E2XXX Compile Errors E2G22: ErrorKind::TypeError, include_str!("./error_codes/E2G22.md"), E2F04: ErrorKind::CannotFindModule, include_str!("./error_codes/E2F04.md"), E2L23: ErrorKind::CompileError, include_str!("./error_codes/E2L23.md"), E2A31: ErrorKind::IllegalAttributeError, include_str!("./error_codes/E2A31.md"), E2L28: ErrorKind::UniqueKeyError, include_str!("./error_codes/E2L28.md"), E2D34: ErrorKind::IllegalInheritError, include_str!("./error_codes/E2D34.md"), + // E3XXX Runtime Errors E3M38: ErrorKind::EvaluationError, include_str!("./error_codes/E2D34.md"), } @@ -63,9 +69,12 @@ pub struct Error { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ErrorKind { + // Syntax Errors InvalidSyntax, TabError, - Indentation, + IndentationError, + IllegalArgumentSyntax, + // Compile Errors CannotFindModule, RecursiveLoad, FloatOverflow, @@ -83,6 +92,7 @@ pub enum ErrorKind { ValueError, KeyError, AttributeError, + // Runtime Errors AssertionError, ImmutableError, MultiInheritError, @@ -129,6 +139,7 @@ pub struct Warning { // Kind of KCL warning. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum WarningKind { + // Compile Warnings CompilerWarning, UnusedImportWarning, ReimportWarning, @@ -142,10 +153,11 @@ pub enum WarningKind { /// let mut handler = Handler::default(); /// handler.add_warning(WarningKind::UnusedImportWarning, &[ /// Message { -/// pos: Position::dummy_pos(), +/// range: (Position::dummy_pos(), Position::dummy_pos()), /// style: Style::LineAndColumn, /// message: "Module 'a' imported but unused.".to_string(), /// note: None, +/// suggested_replacement: None, /// }], /// ); /// for diag in &handler.diagnostics { @@ -168,10 +180,11 @@ impl std::fmt::Display for WarningKind { /// let mut handler = Handler::default(); /// handler.add_warning(WarningKind::UnusedImportWarning, &[ /// Message { -/// pos: Position::dummy_pos(), +/// range: (Position::dummy_pos(), Position::dummy_pos()), /// style: Style::LineAndColumn, /// message: "Module 'a' imported but unused.".to_string(), /// note: None, +/// suggested_replacement: None, /// }], /// ); /// for diag in &handler.diagnostics { diff --git a/kclvm/error/src/error_codes/E1001.md b/kclvm/error/src/error_codes/E1001.md index 30c1ae3ca..60b9c6f42 100644 --- a/kclvm/error/src/error_codes/E1001.md +++ b/kclvm/error/src/error_codes/E1001.md @@ -1,9 +1,26 @@ +### InvalidSyntaxError (E1001) -This error indicates that the compiler syntax error has occurred. +KCL will report InvalidSyntaxError when KCL has a syntax error. -Erroneous code example: +The error code of InvalidSyntaxError is E1001. -```kcl,E1001 -x = f( - 7 ^ -> Expected one of ['all', 'any', 'bin_number', 'dec_number', '**', 'False', 'filter', 'float_number','hex_number', 'lambda', '{', '[', '(', 'long_string', 'not', 'map', '-', '*', 'name', 'None', '~', 'oct_number', '+',')', 'string', 'True', 'Undefined'] +For example: + +``` +a, b = 1, 2 # Multiple assign is illegal in KCL syntax ``` + +The KCL program will cause the following error message. + +```kcl,e1001 +error[E1001]: InvalidSyntax + --> /syntax_error/general/multiple_assign/case0/main.k:1:2 + | +1 | a, b = 1, 2 # Multiple assign is illegal in KCL syntax + | ^ expected statement + | +``` + +Possible resolution: + +Check and fix KCL syntax errors based on the KCL Language Standard diff --git a/kclvm/error/src/error_codes/E1002.md b/kclvm/error/src/error_codes/E1002.md new file mode 100644 index 000000000..41a437c40 --- /dev/null +++ b/kclvm/error/src/error_codes/E1002.md @@ -0,0 +1,29 @@ +### KCLTabError (E1002) + +KCL will report `KCLTabError` when KCL has a tab and white space syntax error. + +In KCL, it is forbidden to mix tabs and four spaces in one indentation block. And we recommend only using white spaces or tabs for indentation in the entire KCL project, don’t mix them. + +For example: + +```python +schema Person: + name: str # begin with a tab + age: int # begin with four white spaces, + # and four white spaces != tab in the env +``` + +The KCL program will cause the following error message. + +```shell +error[E1001]: InvalidSyntax + --> File /syntax_error/tab/tab_error_0/main.k:6:5 + | +3 | age: int = 1 + | ^ inconsistent use of tabs and spaces in indentation + | +``` + +Possible resolution: + +- Only use a tab or four white spaces in KCL, do not mix them. diff --git a/kclvm/error/src/error_codes/E1003.md b/kclvm/error/src/error_codes/E1003.md new file mode 100644 index 000000000..13b8625aa --- /dev/null +++ b/kclvm/error/src/error_codes/E1003.md @@ -0,0 +1,29 @@ +### IndentationError (E1003) + +KCL will report `KCLIndentationError` when KCL has an indentation syntax error. + +The KCL syntax includes indentation. A tab or four white spaces in KCL represents an indentation. The other cases will be regarded as syntax errors by KCL. + +For example: + +```python +schema Person: + name: str # a tab or four white spaces is legal. + age: int # three white spaces are illegal + info: str # two white spaces is illegal +``` + +The KCL program will cause the following error message. + +```shell +error[E1001]: InvalidSyntax + --> /syntax_error/indent/indent_error_0/main.k:3:4 + | +3 | age: int # three white spaces are illegal + | ^ unindent 3 does not match any outer indentation level + | +``` + +Possible resolution: + +- Only use a tab or four white spaces in the KCL program for indentation. diff --git a/kclvm/error/src/error_codes/E1I37.md b/kclvm/error/src/error_codes/E1I37.md new file mode 100644 index 000000000..298ec5846 --- /dev/null +++ b/kclvm/error/src/error_codes/E1I37.md @@ -0,0 +1,28 @@ +### IllegalArgumentSyntaxError (E1I37) + +KCL will report `IllegalArgumentSyntaxError` when KCL has an illegal argument in KCL syntax. + +For example: + +```python +# Parameters without default values +# must be in front of parameters with default values. +a = option(type="list", default={"key": "value"}, "key1") +``` + +The KCL program will cause the following error message. + +```shell +error[E1001]: InvalidSyntax + --> /option/type_convert_fail_2/main.k:3:57 + | +3 | a = option(type="list", default={"key": "value"}, "key1") + | ^ positional argument follows keyword argument + | +``` + +Possible resolution: + +```python +func(input_1, ..., input_n, param_with_key_1 = input_with_key_1, ..., param_with_key_n = input_with_key_n) +``` diff --git a/kclvm/error/src/error_codes/E2A31.md b/kclvm/error/src/error_codes/E2A31.md index 6d1d8dac2..9091357b2 100644 --- a/kclvm/error/src/error_codes/E2A31.md +++ b/kclvm/error/src/error_codes/E2A31.md @@ -4,8 +4,10 @@ This error indicates that the illegal attribute error has occurred. Erroneous code example: ```kcl,E2A31 -KCL Compile Error[E2A31] : Illegal attribute -1 |x = {None: None} - 6 ^ -> Failure -type 'NoneType' +error[E2A31]: IllegalAttributeError + --> /path/to/file.k:1:6 + | +1 | x = {None: None} + | ^ A attribute must be string type, got 'NoneType' + | ``` diff --git a/kclvm/error/src/error_codes/E2D34.md b/kclvm/error/src/error_codes/E2D34.md index 6ebda5fee..c1b2f2c4c 100644 --- a/kclvm/error/src/error_codes/E2D34.md +++ b/kclvm/error/src/error_codes/E2D34.md @@ -1,20 +1,30 @@ +### IllegalInheritError (E2D34) -This error indicates that invalid inheritance structure has occurred. +KCL will report `IllegalInheritError` when an illegal inheritance occurs in the schema. -Erroneous code example: +The `ewcode` of `IllegalInheritError` is `E2D34`. -```kcl +For example: + +```python schema FullnameMixin: fullName = "{} {}".format(firstName, lastName) -schema Scholar(FullnameMixin): +schema Scholar(FullnameMixin): # mixin inheritance is illegal school: str ``` -```kcl,E2D34 -KCL Complier Error[E2D34] : Illegal inheritance ----> File /schema/inherit/inherit_mixin_fail/main.k:8:1 -8 |schema Scholar(FullnameMixin): - 1 ^ -> Failure -mixin inheritance FullnameMixin is prohibited +The KCL program will cause the following error message. + +```shell +error[E2D34]: IllegalInheritError + --> /schema/inherit/inherit_mixin_fail/main.k:4:16 + | +4 | schema Scholar(FullnameMixin): + | ^ invalid schema inherit object type, expect schema, got 'FullnameMixin' + | ``` + +Possible resolution: + +- Schema supports single inheritance of schema in KCL. diff --git a/kclvm/error/src/error_codes/E2F04.md b/kclvm/error/src/error_codes/E2F04.md index 29f438dfd..4817d1c6e 100644 --- a/kclvm/error/src/error_codes/E2F04.md +++ b/kclvm/error/src/error_codes/E2F04.md @@ -1,10 +1,24 @@ +## CannotFindModule (E2F04) -This error indicates that the import module is not found. +KCL will report `CannotFindModule` when KCL imports a module that does not exist. -Erroneous code example: +The `ewcode` of `CannotFindModule` is `E2F04`. -```kcl,E2F04 -1 |import not_existed_pkg - 1 ^^^^^^^^^^^^^^^^^^^^^^ -> Failure -Cannot find the module not_existed_pkg from ./not_existed_pkg +For example: + +```python +import .some0.pkg1 as some00 # some0 not found in package + +Name1 = some00.Name # some0.pkg1.name ``` + +The KCL program will cause the following error message. + +```shell +error[E2F04]: CannotFindModule + --> import_abs_fail_0/app-main/main.k:1:1 + | +1 | import .some0.pkg1 as some00 # some0 not found in package + | Cannot find the module .some0.pkg1 + | +``` \ No newline at end of file diff --git a/kclvm/error/src/error_codes/E2G22.md b/kclvm/error/src/error_codes/E2G22.md index 16b1e0b22..c48127374 100644 --- a/kclvm/error/src/error_codes/E2G22.md +++ b/kclvm/error/src/error_codes/E2G22.md @@ -1,10 +1,35 @@ +### TypeError (E2G22) -This error indicates that the compiler type error has occurred. +KCL will report `TypeError` when a type error occurs in compiling type check. -Erroneous code example: +The `ewcode` of `TypeError` is `E2G22`. -```kcl,E2G22 -1 |a: int = "1" - 1 ^ -> got str(1) -expected int, got str(1) +For example: + +```python +schema Person: + firstName: str + lastName: int + +JohnDoe = Person { + "firstName": "John", + "lastName": "Doe" # Type Error,lastName: int,“Doe” is a string. +} +``` + +The KCL program will cause the following error message. + +```shell +error[E2G22]: TypeError + --> type/type_fail_0/main.k:7:5 + | +7 | "lastName": "Doe" # Type Error,lastName: int,“Doe” is a string. + | ^ expected int, got str(Doe) + | + + --> type/type_fail_0/main.k:3:5 + | +3 | lastName: int + | ^ variable is defined here, its type is int, but got str(Doe) + | ``` diff --git a/kclvm/error/src/error_codes/E2H13.md b/kclvm/error/src/error_codes/E2H13.md new file mode 100644 index 000000000..4c4908174 --- /dev/null +++ b/kclvm/error/src/error_codes/E2H13.md @@ -0,0 +1,34 @@ +### UnKnownDecoratorError (E2H13) + +KCL will report `UnKnownDecoratorError` when an unknown decorator is used in KCL. + +The `ewcode` of `UnKnownDecoratorError` is `E2H13`. + +For example: + +```python +@err_deprecated # It is an unknown decorator +schema Person: + firstName: str = "John" + lastName: str + name: str + +JohnDoe = Person { + name: "deprecated" +} +``` + +The KCL program will cause the following error message. + +```shell +error[E2L23]: CompileError + --> deprecated/unknown_fail_1/main.k:1:2 + | +1 | @err_deprecated # This is a error decorator + | ^ UnKnown decorator err_deprecated + | +``` + +Possible resolution: + +- Check whether the decorator exists. diff --git a/kclvm/error/src/error_codes/E2L28.md b/kclvm/error/src/error_codes/E2L28.md index d0c7cc8a2..9461f4a9b 100644 --- a/kclvm/error/src/error_codes/E2L28.md +++ b/kclvm/error/src/error_codes/E2L28.md @@ -1,21 +1,40 @@ +### UniqueKeyError (E2L28) -This error indicates that variables with the same name or duplicate definitions. +KCL will report `UniqueKeyError` when duplicate names appear in the KCL code. -Erroneous code example: +The `ewcode` of `UniqueKeyError` is `E2L28`. -```kcl +For example: + +```python schema Person: name: str = "kcl" age: int = 1 schema Person: aa: int + +x0 = Person{} +x1 = Person{age:101} ``` -```kcl,E2L28 -KCL Complier Error[E2L28] : Unique key error ----> File /schema/same_name/main.k:5:1 -5 |schema Person: - 1 ^ -> Failure -Variable name 'Person' must be unique in package context +The KCL program will cause the following error message. + +```shell +error[E2L28]: UniqueKeyError + --> /schema/same_name/main.k:5:8 + | +5 | schema Person: + | ^ Unique key error name 'Person' + | + + --> /schema/same_name/main.k:1:8 + | +1 | schema Person: + | ^ The variable 'Person' is declared here + | ``` + +Possible resolution: + +- Check if the name with error has been used. diff --git a/kclvm/error/src/lib.rs b/kclvm/error/src/lib.rs index b0fdf8e48..a45797b2d 100644 --- a/kclvm/error/src/lib.rs +++ b/kclvm/error/src/lib.rs @@ -12,12 +12,15 @@ use annotate_snippets::{ snippet::{AnnotationType, Slice, Snippet, SourceAnnotation}, }; use anyhow::Result; +use compiler_base_error::errors::ComponentFormatError; +use compiler_base_error::StyledBuffer; use compiler_base_error::{ components::{CodeSnippet, Label}, - Diagnostic as DiagnosticTrait, DiagnosticStyle, + Component, Diagnostic as DiagnosticTrait, DiagnosticStyle, }; use compiler_base_session::{Session, SessionDiagnostic}; use compiler_base_span::{span::new_byte_pos, Span}; +use diagnostic::Range; use indexmap::IndexSet; use kclvm_runtime::PanicInfo; use std::{any::Any, sync::Arc}; @@ -91,14 +94,15 @@ impl Handler { } /// Construct a parse error and put it into the handler diagnostic buffer - pub fn add_syntex_error(&mut self, msg: &str, pos: Position) -> &mut Self { + pub fn add_syntex_error(&mut self, msg: &str, range: Range) -> &mut Self { let message = format!("Invalid syntax: {msg}"); let diag = Diagnostic::new_with_code( Level::Error, &message, None, - pos, + range, Some(DiagnosticId::Error(E1001.kind)), + None, ); self.add_diagnostic(diag); @@ -106,13 +110,14 @@ impl Handler { } /// Construct a type error and put it into the handler diagnostic buffer - pub fn add_type_error(&mut self, msg: &str, pos: Position) -> &mut Self { + pub fn add_type_error(&mut self, msg: &str, range: Range) -> &mut Self { let diag = Diagnostic::new_with_code( Level::Error, msg, None, - pos, + range, Some(DiagnosticId::Error(E2G22.kind)), + None, ); self.add_diagnostic(diag); @@ -120,13 +125,23 @@ impl Handler { } /// Construct a type error and put it into the handler diagnostic buffer - pub fn add_compile_error(&mut self, msg: &str, pos: Position) -> &mut Self { + pub fn add_compile_error(&mut self, msg: &str, range: Range) -> &mut Self { + self.add_compile_error_with_suggestions(msg, range, None) + } + + pub fn add_compile_error_with_suggestions( + &mut self, + msg: &str, + range: Range, + suggestions: Option>, + ) -> &mut Self { let diag = Diagnostic::new_with_code( Level::Error, msg, None, - pos, + range, Some(DiagnosticId::Error(E2L23.kind)), + suggestions, ); self.add_diagnostic(diag); @@ -146,10 +161,11 @@ impl Handler { /// let mut handler = Handler::default(); /// handler.add_error(ErrorKind::InvalidSyntax, &[ /// Message { - /// pos: Position::dummy_pos(), + /// range: (Position::dummy_pos(), Position::dummy_pos()), /// style: Style::LineAndColumn, /// message: "Invalid syntax: expected '+', got '-'".to_string(), /// note: None, + /// suggested_replacement: None, /// } /// ]); /// ``` @@ -164,16 +180,35 @@ impl Handler { self } + pub fn add_suggestions(&mut self, msgs: Vec) -> &mut Self { + msgs.iter().for_each(|s| { + self.add_diagnostic(Diagnostic { + level: Level::Suggestions, + messages: vec![Message { + range: Range::default(), + style: Style::Line, + message: s.to_string(), + note: None, + suggested_replacement: None, + }], + code: Some(DiagnosticId::Suggestions), + }); + }); + + self + } + /// Add an warning into the handler /// ``` /// use kclvm_error::*; /// let mut handler = Handler::default(); /// handler.add_warning(WarningKind::UnusedImportWarning, &[ /// Message { - /// pos: Position::dummy_pos(), + /// range: (Position::dummy_pos(), Position::dummy_pos()), /// style: Style::LineAndColumn, /// message: "Module 'a' imported but unused.".to_string(), /// note: None, + /// suggested_replacement: None, /// }], /// ); /// ``` @@ -192,7 +227,7 @@ impl Handler { pub fn classification(&self) -> (IndexSet, IndexSet) { let (mut errs, mut warnings) = (IndexSet::new(), IndexSet::new()); for diag in &self.diagnostics { - if diag.level == Level::Error { + if diag.level == Level::Error || diag.level == Level::Suggestions { errs.insert(diag.clone()); } else if diag.level == Level::Warning { warnings.insert(diag.clone()); @@ -210,7 +245,7 @@ impl Handler { /// ``` /// use kclvm_error::*; /// let mut handler = Handler::default(); - /// handler.add_diagnostic(Diagnostic::new_with_code(Level::Error, "error message", None, Position::dummy_pos(), Some(DiagnosticId::Error(E1001.kind)))); + /// handler.add_diagnostic(Diagnostic::new_with_code(Level::Error, "error message", None, (Position::dummy_pos(), Position::dummy_pos()), Some(DiagnosticId::Error(E1001.kind)), None)); /// ``` #[inline] pub fn add_diagnostic(&mut self, diagnostic: Diagnostic) -> &mut Self { @@ -229,15 +264,17 @@ impl From for Diagnostic { }; let mut diag = if panic_info.backtrace.is_empty() { + let pos = Position { + filename: panic_info.kcl_file.clone(), + line: panic_info.kcl_line as u64, + column: None, + }; Diagnostic::new_with_code( Level::Error, - &panic_msg, + panic_msg, + None, + (pos.clone(), pos), None, - Position { - filename: panic_info.kcl_file.clone(), - line: panic_info.kcl_line as u64, - column: None, - }, None, ) } else { @@ -252,17 +289,19 @@ impl From for Diagnostic { if frame.col != 0 { backtrace_msg.push_str(&format!(":{}", frame.col)) } - backtrace_msg.push_str("\n") + backtrace_msg.push('\n') } + let pos = Position { + filename: panic_info.kcl_file.clone(), + line: panic_info.kcl_line as u64, + column: None, + }; Diagnostic::new_with_code( Level::Error, - &panic_msg, + panic_msg, Some(&backtrace_msg), - Position { - filename: panic_info.kcl_file.clone(), - line: panic_info.kcl_line as u64, - column: None, - }, + (pos.clone(), pos), + None, None, ) }; @@ -270,15 +309,17 @@ impl From for Diagnostic { if panic_info.kcl_config_meta_file.is_empty() { return diag; } + let pos = Position { + filename: panic_info.kcl_config_meta_file.clone(), + line: panic_info.kcl_config_meta_line as u64, + column: Some(panic_info.kcl_config_meta_col as u64), + }; let mut config_meta_diag = Diagnostic::new_with_code( Level::Error, &panic_info.kcl_config_meta_arg_msg, None, - Position { - filename: panic_info.kcl_config_meta_file.clone(), - line: panic_info.kcl_config_meta_line as u64, - column: Some(panic_info.kcl_config_meta_col as u64), - }, + (pos.clone(), pos), + None, None, ); config_meta_diag.messages.append(&mut diag.messages); @@ -329,12 +370,14 @@ impl ParseError { ParseError::Message { span, .. } => span, }; let loc = sess.sm.lookup_char_pos(span.lo()); + let pos: Position = loc.into(); Ok(Diagnostic::new_with_code( Level::Error, &self.to_string(), None, - loc.into(), + (pos.clone(), pos), Some(DiagnosticId::Error(ErrorKind::InvalidSyntax)), + None, )) } } @@ -372,6 +415,15 @@ impl SessionDiagnostic for ParseError { } } +#[derive(Default)] +pub struct SuggestionsLabel; + +impl Component for SuggestionsLabel { + fn format(&self, sb: &mut StyledBuffer, _: &mut Vec) { + sb.appendl("suggestion: ", Some(DiagnosticStyle::NeedAttention)); + } +} + impl SessionDiagnostic for Diagnostic { fn into_diagnostic(self, _: &Session) -> Result> { let mut diag = DiagnosticTrait::::new(); @@ -385,6 +437,9 @@ impl SessionDiagnostic for Diagnostic { diag.append_component(Box::new(Label::Warning(warning.code()))); diag.append_component(Box::new(format!(": {}\n", warning.name()))); } + DiagnosticId::Suggestions => { + diag.append_component(Box::new(SuggestionsLabel)); + } }, None => match self.level { Level::Error => { @@ -396,30 +451,34 @@ impl SessionDiagnostic for Diagnostic { Level::Note => { diag.append_component(Box::new(Label::Note)); } + Level::Suggestions => { + diag.append_component(Box::new(SuggestionsLabel)); + } }, } for msg in &self.messages { - match Session::new_with_file_and_code(&msg.pos.filename, None) { + match Session::new_with_file_and_code(&msg.range.0.filename, None) { Ok(sess) => { let source = sess.sm.lookup_source_file(new_byte_pos(0)); - let line = source.get_line((msg.pos.line - 1) as usize); + let line = source.get_line((msg.range.0.line - 1) as usize); match line.as_ref() { Some(content) => { + let length = content.chars().count(); let snippet = Snippet { title: None, footer: vec![], slices: vec![Slice { source: content, - line_start: msg.pos.line as usize, - origin: Some(&msg.pos.filename), + line_start: msg.range.0.line as usize, + origin: Some(&msg.range.0.filename), annotations: vec![SourceAnnotation { - range: match msg.pos.column { - Some(column) if content.len() >= 1 => { + range: match msg.range.0.column { + Some(column) if length >= 1 => { let column = column as usize; // If the position exceeds the length of the content, // put the annotation at the end of the line. - if column >= content.len() { - (content.len() - 1, content.len()) + if column >= length { + (length - 1, length) } else { (column, column + 1) } diff --git a/kclvm/lexer/Cargo.toml b/kclvm/lexer/Cargo.toml index 832500e72..68a28263a 100644 --- a/kclvm/lexer/Cargo.toml +++ b/kclvm/lexer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-lexer" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/kclvm/lexer/src/kcl_cursor.rs b/kclvm/lexer/src/kcl_cursor.rs index 9326ad8ed..5731c1d07 100644 --- a/kclvm/lexer/src/kcl_cursor.rs +++ b/kclvm/lexer/src/kcl_cursor.rs @@ -10,7 +10,7 @@ use crate::cursor::EOF_CHAR; use crate::Cursor; use crate::DocStyle; use crate::ICommentCursor; -use crate::IIdentCurosr; +use crate::IIdentCursor; use crate::IStringCursor; use crate::Literal; use crate::LiteralKind::*; @@ -126,7 +126,7 @@ impl<'a> Cursor<'a> { } } -impl<'a> IIdentCurosr for Cursor<'a> { +impl<'a> IIdentCursor for Cursor<'a> { fn try_ident_magic(&self, c: char) -> bool { match c { DOLLAR_CHAR => rustc_lexer::is_id_start(self.peek()), diff --git a/kclvm/lexer/src/lib.rs b/kclvm/lexer/src/lib.rs index edf9ca2ea..a7f1fa17d 100644 --- a/kclvm/lexer/src/lib.rs +++ b/kclvm/lexer/src/lib.rs @@ -359,7 +359,7 @@ pub trait IStringCursor { // Cursor trait to read identifier. // Simple identifier, raw identifier, and more identifier cases should be considered here. -pub trait IIdentCurosr { +pub trait IIdentCursor { // If we encounter a identifier. // Returns true if exists, otherwise returns false. fn try_ident_magic(&self, _c: char) -> bool { @@ -367,8 +367,8 @@ pub trait IIdentCurosr { } // Eat it if so. - // This mehod **MUST** be called after 'try_ident_magic'. - // No gurantee to ensure the correctness if no identifier here, + // This method **MUST** be called after 'try_ident_magic'. + // No guarantee to ensure the correctness if no identifier here, // and return 'Unknown' if it happens. fn eat_ident(&mut self) -> TokenKind { Unknown diff --git a/kclvm/lexer/src/number.rs b/kclvm/lexer/src/number.rs index f9f7d9ab2..0458b1fd1 100644 --- a/kclvm/lexer/src/number.rs +++ b/kclvm/lexer/src/number.rs @@ -66,7 +66,7 @@ impl<'a> Cursor<'a> { // with a number self.bump(); let mut empty_exponent = false; - if self.peek().is_digit(10) { + if self.peek().is_ascii_digit() { self.eat_decimal_digits(); match self.peek() { 'e' | 'E' => { diff --git a/kclvm/lexer/src/tests.rs b/kclvm/lexer/src/tests.rs index 2bd614658..6b430f45e 100644 --- a/kclvm/lexer/src/tests.rs +++ b/kclvm/lexer/src/tests.rs @@ -1,10 +1,12 @@ use super::*; use expect_test::{expect, Expect}; +use std::fmt::Write; fn check_lexing(src: &str, expect: Expect) { - let actual: String = tokenize(src) - .map(|token| format!("{:?}\n", token)) - .collect(); + let actual: String = tokenize(src).fold(String::new(), |mut acc, token| { + writeln!(acc, "{:?}", token).expect("Failed to write to string"); + acc + }); expect.assert_eq(&actual) } diff --git a/kclvm/loader/Cargo.toml b/kclvm/loader/Cargo.toml new file mode 100644 index 000000000..8bdf3f9c6 --- /dev/null +++ b/kclvm/loader/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "kclvm-loader" +version = "0.8.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +indexmap = "1.0" +anyhow = "1.0" + +kclvm-ast = {path = "../ast"} +kclvm-parser = {path = "../parser"} +kclvm-sema = {path = "../sema"} +kclvm-error = {path = "../error"} + +[dev-dependencies] +insta = "1.8.0" diff --git a/kclvm/loader/src/lib.rs b/kclvm/loader/src/lib.rs new file mode 100644 index 000000000..27089fcd1 --- /dev/null +++ b/kclvm/loader/src/lib.rs @@ -0,0 +1,290 @@ +#[cfg(test)] +mod tests; + +use anyhow::Result; +use indexmap::{IndexMap, IndexSet}; +use kclvm_ast::ast::Program; +use kclvm_error::{diagnostic::Range, Diagnostic}; +use kclvm_parser::{load_program, KCLModuleCache, LoadProgramOptions, ParseSessionRef}; +use kclvm_sema::{ + advanced_resolver::AdvancedResolver, + core::{ + global_state::GlobalState, + scope::{LocalSymbolScopeKind, ScopeData, ScopeRef}, + symbol::{SymbolData, SymbolRef}, + }, + namer::Namer, + resolver::{ + resolve_program_with_opts, + scope::{KCLScopeCache, NodeKey}, + }, + ty::{Type, TypeRef}, +}; +use std::path::PathBuf; + +type Errors = IndexSet; + +#[derive(Debug, Clone)] +pub struct LoadPackageOptions { + pub paths: Vec, + pub load_opts: Option, + pub resolve_ast: bool, + pub load_builtin: bool, +} + +impl Default for LoadPackageOptions { + fn default() -> Self { + Self { + paths: Default::default(), + load_opts: Default::default(), + resolve_ast: true, + load_builtin: false, + } + } +} + +#[derive(Debug, Clone, Default)] +pub struct Packages { + /// AST Program + pub program: Program, + /// All compiled files in the package + pub paths: Vec, + /// All Parse errors + pub parse_errors: Errors, + /// Type errors + pub type_errors: Errors, + /// Symbol information + pub symbols: IndexMap, + /// Scope information + pub scopes: IndexMap, + /// AST Node-Symbol mapping + pub node_symbol_map: IndexMap, + /// - mapping + pub pkg_scope_map: IndexMap, + /// Symbol-AST Node mapping + pub symbol_node_map: IndexMap, + /// Fully qualified name mapping + pub fully_qualified_name_map: IndexMap, +} + +#[derive(Debug, Clone)] +pub struct SymbolInfo { + pub ty: TypeRef, + pub name: String, + pub range: Range, + pub owner: Option, + pub def: Option, + pub attrs: Vec, + pub is_global: bool, +} + +#[derive(Debug, Clone)] +pub struct ScopeInfo { + /// Scope kind + pub kind: ScopeKind, + /// Scope parent + pub parent: Option, + /// Scope owner + pub owner: Option, + /// Children scopes + pub children: Vec, + /// Definitions + pub defs: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ScopeKind { + Package, + Module, + List, + Dict, + Quant, + Lambda, + SchemaDef, + SchemaConfig, + Value, + Check, +} + +/// load_package provides users with the ability to parse kcl program and sematic model +/// information including symbols, types, definitions, etc. +pub fn load_packages(opts: &LoadPackageOptions) -> Result { + load_packages_with_cache( + opts, + KCLModuleCache::default(), + KCLScopeCache::default(), + GlobalState::default(), + ) +} + +/// load_package_with_cache provides users with the ability to parse kcl program and sematic model +/// information including symbols, types, definitions, etc. +pub fn load_packages_with_cache( + opts: &LoadPackageOptions, + module_cache: KCLModuleCache, + scope_cache: KCLScopeCache, + gs: GlobalState, +) -> Result { + let sess = ParseSessionRef::default(); + let paths: Vec<&str> = opts.paths.iter().map(|s| s.as_str()).collect(); + let parse_result = load_program( + sess.clone(), + &paths, + opts.load_opts.clone(), + Some(module_cache), + )?; + let parse_errors = parse_result.errors; + let (program, type_errors, gs) = if opts.resolve_ast { + let mut program = parse_result.program; + let prog_scope = resolve_program_with_opts( + &mut program, + kclvm_sema::resolver::Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + Some(scope_cache), + ); + let node_ty_map = prog_scope.node_ty_map; + let gs = Namer::find_symbols(&program, gs); + let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map.clone()); + (program, prog_scope.handler.diagnostics.clone(), gs) + } else { + (parse_result.program, IndexSet::default(), gs) + }; + let mut packages = Packages { + program, + paths: parse_result.paths, + parse_errors, + type_errors, + ..Default::default() + }; + if !opts.resolve_ast { + return Ok(packages); + } + let symbols = gs.get_symbols(); + if opts.load_builtin { + for (_, symbol_ref) in symbols.get_builtin_symbols() { + if let Some(symbol) = symbols.get_symbol(*symbol_ref) { + let def_ty = match symbol.get_definition() { + Some(def) => symbols + .get_symbol(def) + .unwrap() + .get_sema_info() + .ty + .clone() + .unwrap_or(Type::any_ref()), + None => symbol.get_sema_info().ty.clone().unwrap_or(Type::any_ref()), + }; + let info = SymbolInfo { + ty: def_ty, + range: symbol.get_range(), + name: symbol.get_name(), + owner: symbol.get_owner(), + def: symbol.get_definition(), + attrs: symbol.get_all_attributes(symbols, None), + is_global: symbol.is_global(), + }; + packages.symbols.insert(*symbol_ref, info); + } + } + } + for path in &packages.paths { + let path_str = path + .to_str() + .ok_or(anyhow::anyhow!("path {} to str failed", path.display()))?; + if let Some(files) = gs.get_sema_db().get_file_sema(path_str) { + for symbol_ref in files.get_symbols() { + if let Some(symbol) = symbols.get_symbol(*symbol_ref) { + let def_ty = match symbol.get_definition() { + Some(def) => symbols + .get_symbol(def) + .unwrap() + .get_sema_info() + .ty + .clone() + .unwrap_or(Type::any_ref()), + None => symbol.get_sema_info().ty.clone().unwrap_or(Type::any_ref()), + }; + let info = SymbolInfo { + ty: def_ty, + range: symbol.get_range(), + name: symbol.get_name(), + owner: symbol.get_owner(), + def: symbol.get_definition(), + attrs: symbol.get_all_attributes(symbols, None), + is_global: symbol.is_global(), + }; + packages.symbols.insert(*symbol_ref, info); + } + } + } + } + let scopes = gs.get_scopes(); + for (path, scope_ref) in scopes.get_root_scope_map() { + packages.pkg_scope_map.insert(path.clone(), *scope_ref); + // Root scopes + if let Some(scope_ref) = scopes.get_root_scope(path.clone()) { + collect_scope_info( + &mut packages.scopes, + &scope_ref, + scopes, + symbols, + ScopeKind::Package, + ); + } + } + // Update package semantic mappings + packages.node_symbol_map = symbols.get_node_symbol_map().clone(); + packages.symbol_node_map = symbols.get_symbol_node_map().clone(); + packages.fully_qualified_name_map = symbols.get_fully_qualified_name_map().clone(); + Ok(packages) +} + +impl From for ScopeKind { + fn from(value: LocalSymbolScopeKind) -> Self { + match value { + LocalSymbolScopeKind::List => ScopeKind::List, + LocalSymbolScopeKind::Dict => ScopeKind::Dict, + LocalSymbolScopeKind::Quant => ScopeKind::Quant, + LocalSymbolScopeKind::Lambda => ScopeKind::Lambda, + LocalSymbolScopeKind::SchemaDef => ScopeKind::SchemaDef, + LocalSymbolScopeKind::SchemaConfig => ScopeKind::SchemaConfig, + LocalSymbolScopeKind::Value => ScopeKind::Value, + LocalSymbolScopeKind::Check => ScopeKind::Check, + } + } +} + +fn collect_scope_info( + scopes: &mut IndexMap, + scope_ref: &ScopeRef, + scope_data: &ScopeData, + symbol_data: &SymbolData, + kind: ScopeKind, +) { + if let Some(scope) = scope_data.get_scope(scope_ref) { + let kind = if let Some(scope) = scope_data.try_get_local_scope(scope_ref) { + scope.get_kind().clone().into() + } else { + kind + }; + scopes.insert( + *scope_ref, + ScopeInfo { + kind, + parent: scope.get_parent(), + owner: scope.get_owner(), + children: scope.get_children(), + defs: scope + .get_all_defs(scope_data, symbol_data, None, false) + .values() + .copied() + .collect::>(), + }, + ); + for s in scope.get_children() { + collect_scope_info(scopes, &s, scope_data, symbol_data, ScopeKind::Module); + } + } +} diff --git a/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_0.snap b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_0.snap new file mode 100644 index 000000000..9d2df302e --- /dev/null +++ b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_0.snap @@ -0,0 +1,88 @@ +--- +source: loader/src/tests.rs +expression: "format!(\"{:#?}\", p.symbols.values())" +--- +[ + SymbolInfo { + ty: Type { + kind: Int, + is_type_alias: false, + flags: INT, + }, + name: "a", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 0, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 1, + ), + }, + ), + owner: Some( + SymbolRef { + id: Index { + index: 13, + generation: 0, + }, + kind: Package, + }, + ), + def: Some( + SymbolRef { + id: Index { + index: 153, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: true, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 1, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 5, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 5, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 0, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, +] diff --git a/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_1.snap b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_1.snap new file mode 100644 index 000000000..bea187443 --- /dev/null +++ b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_1.snap @@ -0,0 +1,126 @@ +--- +source: loader/src/tests.rs +expression: "format!(\"{:#?}\", p.symbols.values())" +--- +[ + SymbolInfo { + ty: Type { + kind: Int, + is_type_alias: false, + flags: INT, + }, + name: "a", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 0, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 1, + ), + }, + ), + owner: Some( + SymbolRef { + id: Index { + index: 13, + generation: 0, + }, + kind: Package, + }, + ), + def: Some( + SymbolRef { + id: Index { + index: 153, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: true, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 1, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 5, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 5, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 0, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 1, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 9, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 9, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 1, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, +] diff --git a/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_2.snap b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_2.snap new file mode 100644 index 000000000..e8a5af937 --- /dev/null +++ b/kclvm/loader/src/snapshots/kclvm_loader__tests__assign_stmt_2.snap @@ -0,0 +1,162 @@ +--- +source: loader/src/tests.rs +expression: "format!(\"{:#?}\", p.symbols.values())" +--- +[ + SymbolInfo { + ty: Type { + kind: Int, + is_type_alias: false, + flags: INT, + }, + name: "a", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 0, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 1, + ), + }, + ), + owner: Some( + SymbolRef { + id: Index { + index: 13, + generation: 0, + }, + kind: Package, + }, + ), + def: Some( + SymbolRef { + id: Index { + index: 153, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: true, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 1, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 6, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 6, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 0, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 1, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 10, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 10, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 1, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: Int, + is_type_alias: false, + flags: INT, + }, + name: "@ParenExpression", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 11, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 11, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 2, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, +] diff --git a/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_0.snap b/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_0.snap new file mode 100644 index 000000000..e83b6d570 --- /dev/null +++ b/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_0.snap @@ -0,0 +1,524 @@ +--- +source: loader/src/tests.rs +expression: "format!(\"{:#?}\", p.symbols.values())" +--- +[ + SymbolInfo { + ty: Type { + kind: Module( + ModuleType { + pkgpath: "math", + imported: [ + "test.k", + ], + kind: System, + }, + ), + is_type_alias: false, + flags: MODULE, + }, + name: "math", + range: ( + Position { + filename: "test.k", + line: 1, + column: Some( + 7, + ), + }, + Position { + filename: "test.k", + line: 1, + column: Some( + 11, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 3, + generation: 0, + }, + kind: Package, + }, + ), + attrs: [ + SymbolRef { + id: Index { + index: 45, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 46, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 47, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 48, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 49, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 50, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 51, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 52, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 53, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 54, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 55, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 56, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 57, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 58, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 59, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 60, + generation: 0, + }, + kind: Value, + }, + ], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: Float, + is_type_alias: false, + flags: FLOAT, + }, + name: "a", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 0, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 1, + ), + }, + ), + owner: Some( + SymbolRef { + id: Index { + index: 13, + generation: 0, + }, + kind: Package, + }, + ), + def: Some( + SymbolRef { + id: Index { + index: 153, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: true, + }, + SymbolInfo { + ty: Type { + kind: Module( + ModuleType { + pkgpath: "math", + imported: [ + "test.k", + ], + kind: System, + }, + ), + is_type_alias: false, + flags: MODULE, + }, + name: "math", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 4, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 8, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 3, + generation: 0, + }, + kind: Package, + }, + ), + attrs: [ + SymbolRef { + id: Index { + index: 45, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 46, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 47, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 48, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 49, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 50, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 51, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 52, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 53, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 54, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 55, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 56, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 57, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 58, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 59, + generation: 0, + }, + kind: Value, + }, + SymbolRef { + id: Index { + index: 60, + generation: 0, + }, + kind: Value, + }, + ], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: Function( + FunctionType { + doc: "Return the logarithm of `x` to the base `e`.", + params: [ + Parameter { + name: "x", + ty: Type { + kind: Union( + [ + Type { + kind: Int, + is_type_alias: false, + flags: INT, + }, + Type { + kind: Float, + is_type_alias: false, + flags: FLOAT, + }, + Type { + kind: Bool, + is_type_alias: false, + flags: BOOL, + }, + ], + ), + is_type_alias: false, + flags: UNION, + }, + has_default: false, + }, + Parameter { + name: "e", + ty: Type { + kind: Float, + is_type_alias: false, + flags: FLOAT, + }, + has_default: true, + }, + ], + self_ty: None, + return_ty: Type { + kind: Float, + is_type_alias: false, + flags: FLOAT, + }, + is_variadic: false, + kw_only_index: None, + }, + ), + is_type_alias: false, + flags: FUNCTION, + }, + name: "log", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 9, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 12, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 55, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: IntLit( + 10, + ), + is_type_alias: false, + flags: INT | LITERAL, + }, + name: "@NumberLitExpression", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 15, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 15, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 0, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, + SymbolInfo { + ty: Type { + kind: Float, + is_type_alias: false, + flags: FLOAT, + }, + name: "@CallExpression", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 16, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 16, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 1, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, +] diff --git a/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_1.snap b/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_1.snap new file mode 100644 index 000000000..9f068a42a --- /dev/null +++ b/kclvm/loader/src/snapshots/kclvm_loader__tests__import_stmt_1.snap @@ -0,0 +1,86 @@ +--- +source: loader/src/tests.rs +expression: "format!(\"{:#?}\", p.symbols.values())" +--- +[ + SymbolInfo { + ty: Type { + kind: Any, + is_type_alias: false, + flags: ANY, + }, + name: "a", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 0, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 1, + ), + }, + ), + owner: Some( + SymbolRef { + id: Index { + index: 13, + generation: 0, + }, + kind: Package, + }, + ), + def: Some( + SymbolRef { + id: Index { + index: 153, + generation: 0, + }, + kind: Value, + }, + ), + attrs: [], + is_global: true, + }, + SymbolInfo { + ty: Type { + kind: Any, + is_type_alias: false, + flags: ANY, + }, + name: "@IdentifierExpression", + range: ( + Position { + filename: "test.k", + line: 3, + column: Some( + 9, + ), + }, + Position { + filename: "test.k", + line: 3, + column: Some( + 9, + ), + }, + ), + owner: None, + def: Some( + SymbolRef { + id: Index { + index: 0, + generation: 0, + }, + kind: Expression, + }, + ), + attrs: [], + is_global: false, + }, +] diff --git a/kclvm/loader/src/tests.rs b/kclvm/loader/src/tests.rs new file mode 100644 index 000000000..9bffe903b --- /dev/null +++ b/kclvm/loader/src/tests.rs @@ -0,0 +1,35 @@ +use crate::{load_packages, LoadPackageOptions}; +use kclvm_parser::LoadProgramOptions; + +#[macro_export] +macro_rules! load_package_snapshot { + ($name:ident, $src:expr) => { + #[test] + fn $name() { + let p = load_packages(&LoadPackageOptions { + paths: vec!["test.k".to_string()], + load_opts: Some(LoadProgramOptions { + k_code_list: vec![$src.to_string()], + ..Default::default() + }), + load_builtin: false, + ..Default::default() + }) + .unwrap(); + insta::assert_snapshot!(format!("{:#?}", p.symbols.values())); + } + }; +} + +load_package_snapshot! {assign_stmt_0, "a = 1"} +load_package_snapshot! {assign_stmt_1, "a = 1 + 1"} +load_package_snapshot! {assign_stmt_2, "a = (1 + 1)"} + +load_package_snapshot! {import_stmt_0, r#"import math + +a = math.log(10) +"#} +load_package_snapshot! {import_stmt_1, r#"import pkg + +a = pkg.a +"#} diff --git a/kclvm/macros/Cargo.toml b/kclvm/macros/Cargo.toml index 863824829..b131e11bd 100644 --- a/kclvm/macros/Cargo.toml +++ b/kclvm/macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-macros" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/kclvm/macros/src/symbols.rs b/kclvm/macros/src/symbols.rs index f218f9f60..144f33b80 100644 --- a/kclvm/macros/src/symbols.rs +++ b/kclvm/macros/src/symbols.rs @@ -115,6 +115,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let mut keyword_stream = quote! {}; let mut symbols_stream = quote! {}; let mut prefill_stream = quote! {}; + let mut reserved_word_stream = quote! {}; let mut counter = 0u32; let mut keys = HashMap::::with_capacity(input.keywords.len() + input.symbols.len() + 10); @@ -151,6 +152,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let value = &keyword.value; let value_string = value.value(); check_dup(keyword.name.span(), &value_string, &mut errors); + reserved_word_stream.extend(quote! {#value_string,}); prefill_stream.extend(quote! { #value, }); @@ -170,6 +172,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { check_dup(symbol.name.span(), &value, &mut errors); check_order(symbol.name.span(), &name.to_string(), &mut errors); + reserved_word_stream.extend(quote! {#value,}); prefill_stream.extend(quote! { #value, }); @@ -178,6 +181,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { }); counter += 1; } + let reserved_count = counter as usize; // Generate symbols for the strings "0", "1", ..., "9". let digits_base = counter; @@ -208,6 +212,12 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { #symbols_stream } + #[doc(hidden)] + #[allow(non_upper_case_globals)] + pub mod reserved_word { + pub const reserved_words : [&str; #reserved_count] = [#reserved_word_stream]; + } + impl Interner { pub(crate) fn fresh() -> Self { Interner::prefill(&[ diff --git a/kclvm/makefile b/kclvm/makefile index 2e6754e4f..aa7e74a01 100644 --- a/kclvm/makefile +++ b/kclvm/makefile @@ -31,7 +31,7 @@ install-kclvm-py: # E2E compile and run run: cd .. && make build && cd kclvm - kcl ../samples/hello.k + kclvm_cli run ../samples/hello.k # Cargo check all packages check: @@ -55,7 +55,7 @@ fix: # Unit tests without code cov test: - cargo test -p kclvm-* -- --nocapture + cargo test --workspace -r -- --nocapture # Unit tests with code cov (Requires rust 1.60+) codecov: @@ -67,20 +67,21 @@ codecov: codecov-lcov: rustup component add llvm-tools-preview cargo install cargo-llvm-cov - mkdir $(PWD)/.kclvm - cargo llvm-cov --lcov --output-path $(PWD)/.kclvm/lcov.info --workspace --ignore-filename-regex gpyrpc.rs -- --nocapture + rm -rf $(PWD)/.kclvm_cov + mkdir $(PWD)/.kclvm_cov + cargo llvm-cov --lcov --output-path $(PWD)/.kclvm_cov/lcov.info -r --workspace --ignore-filename-regex gpyrpc.rs -- --nocapture # Test runtime libaries using python functions test-runtime: install-kclvm-py install-pytest - cd ./tests/test_units && PYTHONPATH=./../../plugin kclvm -m pytest -vv || { echo 'kclvm/tests/test_units failed' ; exit 1; } + cd ./tests/test_units && PYTHONPATH=./../../tests/test_units/runtime python3 -m pytest -vv || { echo 'kclvm/tests/test_units failed' ; exit 1; } # E2E grammar tests. test-grammar: install-kclvm-py install-pytest - cd tests/integration/grammar && kclvm -m pytest -v -n 5 + cd tests/integration/grammar && python3 -m pytest -v -n 5 # E2E konfig tests. test-konfig: install-kclvm-py install-pytest - cd tests/integration/konfig && kclvm -m pytest -v -n 5 + cd tests/integration/konfig && python3 -m pytest -v -n 5 # Parser fuzz. fuzz-parser: diff --git a/kclvm/parser/Cargo.toml b/kclvm/parser/Cargo.toml index 52fd51d92..56b9a8b5e 100644 --- a/kclvm/parser/Cargo.toml +++ b/kclvm/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-parser" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,6 +8,7 @@ edition = "2021" [dependencies] compiler_base_span = {path = "../../compiler_base/span"} compiler_base_session = {path = "../../compiler_base/session"} +compiler_base_error_dev = {package = "compiler_base_error", path = "../../compiler_base/error/"} compiler_base_error = "0.0.10" compiler_base_macros = "0.0.1" tracing = "0.1" @@ -18,6 +19,7 @@ either = "1.1.0" enquote = "1.1.0" unicode_names2 = "0.4" bstr = "0.2.16" +petgraph = "0.6.0" num-bigint = "0.4" regex = "1.7.0" anyhow = "1.0" @@ -29,10 +31,8 @@ kclvm-span = {path = "../span"} kclvm-error = {path = "../error"} kclvm-config = {path = "../config"} kclvm-sema = {path = "../sema"} -kclvm-runtime = {path = "../runtime"} kclvm-utils = {path = "../utils"} - [dev-dependencies] expect-test = "1.0" insta = "1.8.0" diff --git a/kclvm/parser/src/entry.rs b/kclvm/parser/src/entry.rs new file mode 100644 index 000000000..c607e8ae9 --- /dev/null +++ b/kclvm/parser/src/entry.rs @@ -0,0 +1,504 @@ +use anyhow::Result; +use kclvm_config::modfile::get_pkg_root; +use kclvm_config::modfile::KCL_FILE_SUFFIX; +use kclvm_config::path::ModRelativePath; +use kclvm_utils::path::PathPrefix; +use kclvm_utils::path::{is_absolute, is_dir, path_exist}; +use std::collections::VecDeque; +use std::fs; +use std::path::Path; + +use crate::LoadProgramOptions; + +/// [`Entries`] is a map of package name to package root path for one compilation +/// # note +/// +/// The [`entries`] in [`Entries`] is ordered, and the order of Entrys may affect the result of the compilation. +/// The reason why the [`Entries`] is not an [`IndexMap`] is that the [`entries`] is duplicable and ordered. +#[derive(Default, Debug)] +pub struct Entries { + root_path: String, + entries: VecDeque, +} + +impl Entries { + /// [`get_unique_normal_paths_by_name`] will return all the unique normal paths of [`Entry`] with the given name in [`Entries`]. + pub fn get_unique_normal_paths_by_name(&self, name: &str) -> Vec { + let paths = self + .get_unique_paths_by_name(name) + .iter() + .filter(|path| { + // All the paths contains the normal paths and the mod relative paths start with ${KCL_MOD}. + // If the number of 'kcl.mod' paths is 0, except for the mod relative paths start with ${KCL_MOD}, + // then use empty path "" as the default. + !ModRelativePath::new(path.to_string()) + .is_relative_path() + .unwrap_or(false) + }) + .map(|entry| entry.to_string()) + .collect::>(); + paths + } + + /// [`get_unique_paths_by_name`] will return all the unique paths of [`Entry`] with the given name in [`Entries`]. + pub fn get_unique_paths_by_name(&self, name: &str) -> Vec { + let mut paths = self + .entries + .iter() + .filter(|entry| entry.name() == name) + .map(|entry| entry.path().to_string()) + .collect::>(); + paths.sort(); + paths.dedup(); + paths + } + + /// [`push_entry`] will push a new [`Entry`] into [`Entries`]. + pub fn push_entry(&mut self, entry: Entry) { + self.entries.push_back(entry); + } + + /// [`push`] will push a new [`Entry`] into [`Entries`] with the given name and path. + pub fn push(&mut self, name: String, path: String) { + self.entries.push_back(Entry::new(name, path)); + } + + /// [`contains_pkg_name`] will return [`Option::Some`] if there is an [`Entry`] with the given name in [`Entries`]. + pub fn contains_pkg_name(&self, name: &String) -> Option<&Entry> { + self.entries.iter().find(|entry| entry.name() == name) + } + + /// [`iter`] will return an iterator of [`Entry`] in [`Entries`]. + pub fn iter(&self) -> std::collections::vec_deque::Iter { + self.entries.iter() + } + + /// [`len`] will return the length of [`Entries`]. + pub fn len(&self) -> usize { + self.entries.len() + } + + /// [`get_nth_entry`] will return the nth [`Entry`] in [`Entries`]. + #[allow(dead_code)] + pub fn get_nth_entry(&self, n: usize) -> Option<&Entry> { + if n >= self.len() { + return None; + } + let mut count = 0; + for entry in self.entries.iter() { + if count == n { + return Some(entry); + } + count += 1; + } + None + } + + /// [`get_nth_entry_by_name`] will return the nth [`Entry`] by name in [`Entries`]. + pub fn get_nth_entry_by_name(&self, n: usize, name: &str) -> Option<&Entry> { + self.entries + .iter() + .enumerate() + .filter(|(_, entry)| name == entry.name()) + .nth(n) + .map(|(_, entry)| entry) + } + + /// [`apply_to_all_entries`] will apply the given function to all [`Entry`] in [`Entries`]. + pub fn apply_to_all_entries(&mut self, f: F) -> Result<()> + where + F: FnMut(&mut Entry) -> Result<()>, + { + self.entries.iter_mut().try_for_each(f)?; + Ok(()) + } + + /// [`get_root_path`] will return the root path of [`Entries`]. + pub fn get_root_path(&self) -> &String { + &self.root_path + } +} + +/// [`Entry`] is a package name and package root path pair. +#[derive(Default, Debug)] +pub struct Entry { + name: String, + path: String, + k_files: Vec, + k_code_lists: Vec>, +} + +impl Entry { + /// [`new`] will create a new [`Entry`] with the given name and path. + pub fn new(name: String, path: String) -> Self { + Self { + name, + path, + k_files: vec![], + k_code_lists: vec![], + } + } + + /// [`name`] will return the name of [`Entry`]. + pub fn name(&self) -> &String { + &self.name + } + + /// [`path`] will return the path of [`Entry`]. + pub fn path(&self) -> &String { + &self.path + } + + /// [`set_path`] will set the path of [`Entry`] to the given path. + pub fn set_path(&mut self, path: String) { + self.path = path; + } + + /// [`extend_k_files`] will extend the k files of [`Entry`] to the given k file. + pub fn extend_k_files(&mut self, k_files: Vec) { + self.k_files.extend(k_files); + } + + /// [`extend_k_files_and_codes`] will extend the k files and k codes of [`Entry`] to the given k file and k code. + pub fn extend_k_files_and_codes( + &mut self, + k_files: Vec, + k_codes: &mut VecDeque, + ) { + for k_file in k_files.iter() { + self.k_code_lists.push(k_codes.pop_front()); + self.k_files.push(k_file.to_string()); + } + } + + /// [`push_k_code`] will push the k code of [`Entry`] to the given k code. + pub fn push_k_code(&mut self, k_code: Option) { + self.k_code_lists.push(k_code); + } + + /// [`get_k_files`] will return the k files of [`Entry`]. + pub fn get_k_files(&self) -> &Vec { + &self.k_files + } + + /// [`get_k_codes`] will return the k codes of [`Entry`]. + pub fn get_k_codes(&self) -> &Vec> { + &self.k_code_lists + } +} + +/// [`get_compile_entries_from_paths`] returns all the [`Entries`] for compilation from the given [`file_paths`]. +/// +/// # Note +/// If the path in [`file_paths`] is a normal path or a [`ModRelativePath`] with prefix `${KCL_MOD}`, the package will be named as `__main__`. +/// If the path in [`file_paths`] is a [`ModRelativePath`], the package will be named by the suffix of [`ModRelativePath`]. +/// +/// # Error +/// The package root path for package name `__main__` is only used once. If there are multiple +/// package root paths for `__main__`, an error `conflict kcl.mod file` is returned. +/// +/// # Example +/// +/// ```rust +/// use std::path::PathBuf; +/// use kclvm_parser::entry::get_compile_entries_from_paths; +/// use kclvm_parser::LoadProgramOptions; +/// let testpath = PathBuf::from("./src/testdata/multimods").canonicalize().unwrap(); +/// +/// // [`kcl1_path`] is a normal path of the package [`kcl1`] root directory. +/// // It looks like `/xxx/xxx/xxx`. +/// let kcl1_path = testpath.join("kcl1"); +/// +/// // [`kcl2_path`] is a mod relative path of the packege [`kcl2`] root directory. +/// // It looks like `${kcl2:KCL_MOD}/xxx/xxx` +/// let kcl2_path = PathBuf::from("${kcl2:KCL_MOD}/main.k"); +/// +/// // [`kcl3_path`] is a mod relative path of the [`__main__`] packege. +/// // It looks like `${KCL_MOD}/xxx/xxx` +/// let kcl3_path = PathBuf::from("${KCL_MOD}/main.k"); +/// +/// // [`package_maps`] is a map to show the real path of the mod relative path [`kcl2`]. +/// let mut opts = LoadProgramOptions::default(); +/// opts.package_maps.insert("kcl2".to_string(), testpath.join("kcl2").to_str().unwrap().to_string()); +/// +/// // [`get_compile_entries_from_paths`] will return the map of package name to package root real path. +/// let entries = get_compile_entries_from_paths( +/// &[ +/// kcl1_path.to_str().unwrap().to_string(), +/// kcl2_path.display().to_string(), +/// kcl3_path.display().to_string(), +/// ], +/// &opts, +/// ).unwrap(); +/// +/// // [`entries`] will contain 3 entries. +/// // <__main__, "/usr/xxx/src/testdata/multimods/kcl1"> +/// // +/// // <__main__, "/usr/xxx/src/testdata/multimods/kcl1"> +/// assert_eq!(entries.len(), 3); +/// +/// // <__main__, "/usr/xxx/src/testdata/multimods/kcl1"> +/// assert_eq!(entries.get_nth_entry(0).unwrap().name(), "__main__"); +/// assert_eq!( +/// PathBuf::from(entries.get_nth_entry(0).unwrap().path()) +/// .canonicalize() +/// .unwrap() +/// .display() +/// .to_string(), +/// kcl1_path.canonicalize().unwrap().to_str().unwrap() +/// ); +/// +/// // +/// assert_eq!(entries.get_nth_entry(1).unwrap().name(), "kcl2"); +/// assert_eq!( +/// PathBuf::from(entries.get_nth_entry(1).unwrap().path()) +/// .canonicalize() +/// .unwrap() +/// .display() +/// .to_string(), +/// testpath +/// .join("kcl2") +/// .canonicalize() +/// .unwrap() +/// .to_str() +/// .unwrap() +/// ); +/// +/// // <__main__, "/usr/xxx/src/testdata/multimods/kcl1"> +/// assert_eq!(entries.get_nth_entry(2).unwrap().name(), "__main__"); +/// assert_eq!( +/// PathBuf::from(entries.get_nth_entry(2).unwrap().path()) +/// .canonicalize() +/// .unwrap() +/// .to_str() +/// .unwrap(), +/// kcl1_path.canonicalize().unwrap().to_str().unwrap() +/// ); +/// ``` +pub fn get_compile_entries_from_paths( + file_paths: &[String], + opts: &LoadProgramOptions, +) -> Result { + if file_paths.is_empty() { + return Err(anyhow::anyhow!("No input KCL files or paths")); + } + let mut result = Entries::default(); + let mut k_code_queue = VecDeque::from(opts.k_code_list.clone()); + for s in file_paths { + let path = ModRelativePath::from(s.to_string()); + + // If the path is a [`ModRelativePath`] with prefix '${:KCL_MOD}', + // calculate the real path and the package name. + if let Some((pkg_name, pkg_path)) = path.get_root_pkg_name()?.and_then(|name| { + opts.package_maps + .get(&name) + .map(|pkg_path: &String| (name, pkg_path)) + }) { + // Replace the mod relative path prefix '${:KCL_MOD}' with the real path. + let s = path.canonicalize_by_root_path(pkg_path)?; + if let Some(root) = get_pkg_root(&s) { + let mut entry: Entry = Entry::new(pkg_name.clone(), root.clone()); + entry.extend_k_files_and_codes( + get_main_files_from_pkg_path(&s, &root, &pkg_name, opts)?, + &mut k_code_queue, + ); + result.push_entry(entry); + continue; + } + // If the [`ModRelativePath`] with prefix '${KCL_MOD}' + } else if path.is_relative_path()? && path.get_root_pkg_name()?.is_none() { + // Push it into `result`, and deal it later. + let mut entry = Entry::new(kclvm_ast::MAIN_PKG.to_string(), path.get_path()); + entry.push_k_code(k_code_queue.pop_front()); + result.push_entry(entry); + continue; + } else if let Some(root) = get_pkg_root(s) { + // If the path is a normal path. + let mut entry: Entry = Entry::new(kclvm_ast::MAIN_PKG.to_string(), root.clone()); + entry.extend_k_files_and_codes( + get_main_files_from_pkg_path(s, &root, kclvm_ast::MAIN_PKG, opts)?, + &mut k_code_queue, + ); + result.push_entry(entry); + } + } + + // The main 'kcl.mod' can not be found, the empty path "" will be took by default. + if result + .get_unique_normal_paths_by_name(kclvm_ast::MAIN_PKG) + .is_empty() + { + let mut entry = Entry::new(kclvm_ast::MAIN_PKG.to_string(), "".to_string()); + for s in file_paths { + entry.extend_k_files_and_codes( + get_main_files_from_pkg_path(s, "", kclvm_ast::MAIN_PKG, opts)?, + &mut k_code_queue, + ); + } + result.push_entry(entry); + } + + let pkg_root = if result + .get_unique_normal_paths_by_name(kclvm_ast::MAIN_PKG) + .len() + == 1 + && opts.work_dir.is_empty() + { + // If the 'kcl.mod' can be found only once, the package root path will be the path of the 'kcl.mod'. + result + .get_unique_normal_paths_by_name(kclvm_ast::MAIN_PKG) + .get(0) + .unwrap() + .to_string() + } else if !opts.work_dir.is_empty() { + // If the 'kcl.mod' can be found more than once, the package root path will be the 'work_dir'. + if let Some(root_work_dir) = get_pkg_root(&opts.work_dir) { + root_work_dir + } else { + "".to_string() + } + } else { + "".to_string() + }; + result.root_path = pkg_root.clone(); + // Replace the '${KCL_MOD}' of all the paths with package name '__main__'. + result.apply_to_all_entries(|entry| { + let path = ModRelativePath::from(entry.path().to_string()); + if entry.name() == kclvm_ast::MAIN_PKG && path.is_relative_path()? { + entry.set_path(pkg_root.to_string()); + entry.extend_k_files(get_main_files_from_pkg_path( + &path.canonicalize_by_root_path(&pkg_root)?, + &pkg_root, + kclvm_ast::MAIN_PKG, + opts, + )?); + } + Ok(()) + })?; + + Ok(result) +} + +/// Get files in the main package with the package root. +fn get_main_files_from_pkg_path( + pkg_path: &str, + root: &str, + pkg_name: &str, + opts: &LoadProgramOptions, +) -> Result> { + // fix path + let mut path_list = Vec::new(); + let mut s = pkg_path.to_string(); + + let path = ModRelativePath::from(s.to_string()); + + if path.is_relative_path()? { + if let Some(name) = path.get_root_pkg_name()? { + if name == pkg_name { + s = path.canonicalize_by_root_path(root)?; + } + } else if path.is_relative_path()? { + return Err(anyhow::anyhow!("Can not find {} in the path: {}", s, root)); + } + } + if !root.is_empty() && !is_absolute(s.as_str()) { + let p = std::path::Path::new(s.as_str()); + if let Ok(x) = std::fs::canonicalize(p) { + s = x.adjust_canonicalization(); + } + } + + path_list.push(s); + + // get k files + let mut k_files: Vec = Vec::new(); + + for (i, path) in path_list.iter().enumerate() { + // read dir/*.k + if is_dir(path) { + if opts.k_code_list.len() > i { + return Err(anyhow::anyhow!("Invalid code list")); + } + // k_code_list + for s in get_dir_files(path, false)? { + k_files.push(s); + } + continue; + } else { + k_files.push(path.to_string()); + } + } + + if k_files.is_empty() { + return Err(anyhow::anyhow!("No input KCL files")); + } + + // check all file exists + for (i, filename) in k_files.iter().enumerate() { + if i < opts.k_code_list.len() { + continue; + } + + if !path_exist(filename.as_str()) { + return Err(anyhow::anyhow!( + "Cannot find the kcl file, please check the file path {}", + filename.as_str(), + )); + } + } + Ok(k_files) +} + +/// Get file list in the directory. +pub fn get_dir_files(dir: &str, is_recursive: bool) -> Result> { + if !std::path::Path::new(dir).exists() { + return Ok(Vec::new()); + } + + let mut list = Vec::new(); + let mut queue: VecDeque = VecDeque::new(); + queue.push_back(dir.to_string()); + // BFS all the files in the directory. + while let Some(path) = queue.pop_front() { + let path = Path::new(&path); + if path.is_dir() { + match fs::read_dir(path) { + Ok(entries) => { + for entry in entries { + if let Ok(entry) = entry { + let path = entry.path(); + if path.is_dir() && is_recursive { + queue.push_back(path.to_string_lossy().to_string()); + } else if !is_ignored_file(&path.display().to_string()) { + list.push(path.display().to_string()); + } + } + } + } + Err(err) => { + return Err(anyhow::anyhow!( + "Failed to read directory: {},{}", + path.display(), + err + )); + } + } + } else if !is_ignored_file(&path.display().to_string()) { + list.push(path.display().to_string()); + } + } + + list.sort(); + Ok(list) +} + +/// Check if the file is ignored. +/// The file is ignored if +/// it is not a kcl file (end with '*.k') +/// or it is a test file (end with '_test.k') +/// or it is a hidden file. (start with '_') +fn is_ignored_file(filename: &str) -> bool { + (!filename.ends_with(KCL_FILE_SUFFIX)) + || (filename.ends_with("_test.k")) + || (filename.starts_with('_')) +} diff --git a/kclvm/parser/src/file_graph.rs b/kclvm/parser/src/file_graph.rs new file mode 100644 index 000000000..9fdbe6301 --- /dev/null +++ b/kclvm/parser/src/file_graph.rs @@ -0,0 +1,103 @@ +use indexmap::IndexMap; +use petgraph::visit::EdgeRef; +use std::path::{Path, PathBuf}; + +/// A graph of files, where each file depends on zero or more other files. +#[derive(Default)] +pub struct FileGraph { + graph: petgraph::stable_graph::StableDiGraph, + path_to_node_index: IndexMap, +} + +impl FileGraph { + /// Sets a file to depend on the given other files. + /// + /// For example, if the current graph has file A depending on B, and + /// `update_file(pathA, &[pathC])` was called, then this function will remove the edge + /// from A to B, and add an edge from A to C. + pub fn update_file<'a, I: IntoIterator>( + &mut self, + from_path: &Path, + to_paths: I, + ) { + let from_node_index = self.get_or_insert_node_index(from_path); + + // remove all current out coming edges from this node + self.graph.retain_edges(|g, edge| { + if let Some((source, _)) = g.edge_endpoints(edge) { + if source == from_node_index { + return false; + } + } + true + }); + + for to_path in to_paths { + let to_node_index = self.get_or_insert_node_index(to_path); + self.graph.add_edge(from_node_index, to_node_index, ()); + } + } + + /// Returns true if the given file is in the graph + pub fn contains_file(&mut self, path: &Path) -> bool { + self.path_to_node_index.contains_key(path) + } + + /// Returns a list of the direct dependencies of the given file. + /// (does not include all transitive dependencies) + /// The file path must be relative to the root of the file graph. + pub fn dependencies_of(&self, path: &Path) -> Vec<&PathBuf> { + let node_index = self + .path_to_node_index + .get(path) + .expect("path not in graph"); + self.graph + .edges(*node_index) + .map(|edge| &self.graph[edge.target()]) + .collect::>() + } + + /// Returns a list of files in the order they should be compiled + /// Or a list of files that are part of a cycle, if one exists + pub fn toposort(&self) -> Result, Vec> { + match petgraph::algo::toposort(&self.graph, None) { + Ok(indices) => Ok(indices + .into_iter() + .rev() + .map(|n| self.graph[n].clone()) + .collect::>()), + Err(_) => { + // toposort function in the `petgraph` library doesn't return the cycle itself, + // so we need to use Tarjan's algorithm to find one instead + let strongly_connected_components = petgraph::algo::tarjan_scc(&self.graph); + + // a strongly connected component is a cycle if it has more than one node + // let's just return the first one we find + let cycle = strongly_connected_components + .into_iter() + .find(|component| component.len() > 1) + .unwrap(); + Err(cycle + .iter() + .map(|n| self.graph[*n].clone()) + .collect::>()) + } + } + } + + /// Returns all paths. + #[inline] + pub fn paths(&self) -> Vec { + self.path_to_node_index.keys().cloned().collect::>() + } + + fn get_or_insert_node_index(&mut self, path: &Path) -> petgraph::graph::NodeIndex { + if let Some(node_index) = self.path_to_node_index.get(path) { + return *node_index; + } + + let node_index = self.graph.add_node(path.to_owned()); + self.path_to_node_index.insert(path.to_owned(), node_index); + node_index + } +} diff --git a/kclvm/parser/src/lexer/indent.rs b/kclvm/parser/src/lexer/indent.rs index c506e4515..f53ee8ff3 100644 --- a/kclvm/parser/src/lexer/indent.rs +++ b/kclvm/parser/src/lexer/indent.rs @@ -1,10 +1,10 @@ //! KCL indent handling. -//! See details defined in KCL Grammar ['./spec/grammar']. use std::cmp::Ordering; use crate::lexer::IndentOrDedents; use crate::lexer::Lexer; +use kclvm_ast::token::VALID_SPACES_LENGTH; use kclvm_ast::token::{self, Token}; #[derive(Clone, Copy, PartialEq, Debug, Default)] @@ -88,11 +88,15 @@ impl<'a> Lexer<'a> { self.indent_cxt.indents.push(indent); // For indent token, we ignore the length - let indent = Token::new(token::Indent, self.span(self.pos, self.pos)); + let indent = Token::new( + token::Indent(VALID_SPACES_LENGTH), + self.span(self.pos, self.pos), + ); IndentOrDedents::Indent { token: indent } } Ordering::Less => { let mut dedents = Vec::new(); + let mut indents = Vec::new(); loop { match ordering { @@ -100,11 +104,13 @@ impl<'a> Lexer<'a> { match order { Ordering::Less => { // Pop indents util we find an equal ident level - self.indent_cxt.indents.pop(); + if let Some(indent) = self.indent_cxt.indents.pop() { + indents.push(indent); + } // update pos & collect dedent // For dedent token, we ignore the length let dedent = Token::new( - token::Dedent, + token::Dedent(VALID_SPACES_LENGTH), self.span(self.pos, self.pos), ); dedents.push(dedent); @@ -114,10 +120,15 @@ impl<'a> Lexer<'a> { break; } Ordering::Greater => { - self.sess.struct_span_error( - &format!("unindent {} does not match any outer indentation level", indent.spaces), - self.span(self.pos, self.pos), - ); + let spaces_diff = indent.spaces - cur_indent.spaces; + if let Some(indent) = indents.pop() { + self.indent_cxt.indents.push(indent); + } + dedents.pop(); + dedents.push(Token::new( + token::Dedent(spaces_diff), + self.span(self.pos, self.pos), + )); break; } } @@ -133,7 +144,6 @@ impl<'a> Lexer<'a> { } } } - IndentOrDedents::Dedents { tokens: dedents } } _ => return None, diff --git a/kclvm/parser/src/lexer/mod.rs b/kclvm/parser/src/lexer/mod.rs index bafb6f52f..187c124b4 100644 --- a/kclvm/parser/src/lexer/mod.rs +++ b/kclvm/parser/src/lexer/mod.rs @@ -1,7 +1,6 @@ //! A KCL lexer. //! -//! The lexer is built on the low level [`kclvm_lexer`], and works -//! based on the rules defined by the KCL grammar ['./spec/grammar']. +//! The lexer is built on the low level [`kclvm_lexer`] //! //! It's main responsibilities: //! 1. Mapping low level [`kclvm_lexer::Token`] tokens into [`kclvm_ast::Token`] tokens, @@ -24,7 +23,8 @@ mod tests; use compiler_base_macros::bug; use compiler_base_span::{self, span::new_byte_pos, BytePos, Span}; use kclvm_ast::ast::NumberBinarySuffix; -use kclvm_ast::token::{self, CommentKind, Token, TokenKind}; +use kclvm_ast::token::VALID_SPACES_LENGTH; +use kclvm_ast::token::{self, BinOpToken, CommentKind, Token, TokenKind}; use kclvm_ast::token_stream::TokenStream; use kclvm_lexer::Base; use kclvm_span::symbol::Symbol; @@ -41,6 +41,7 @@ pub fn parse_token_streams(sess: &ParseSession, src: &str, start_pos: BytePos) - sess, start_pos, pos: start_pos, + tok_start_pos: start_pos, end_src_index: src.len(), src, token: TokenWithIndents::Token { @@ -112,6 +113,9 @@ struct Lexer<'a> { /// The absolute offset within the source_map of the current character. pos: BytePos, + /// The start position of the current token. + tok_start_pos: BytePos, + /// Stop reading src at this index. end_src_index: usize, @@ -148,18 +152,23 @@ struct IndentContext { impl<'a> Lexer<'a> { fn into_tokens(mut self) -> TokenStream { let mut buf = TokenStreamBuilder::default(); - self.token = self.token(); + // In the process of look-behind lexing, it is necessary to check the type of the previous token in 'buf', + // If the previous token and the current token can form a multi-character token, + // then the previous token will be popped from 'buf'. + // + // Therefore, the method 'self.token()' needs to take the mutable reference of 'buf' as an incoming argument. + self.token = self.token(&mut buf); while !self.token.is_eof() { self.token.append_to(&mut buf); - self.token = self.token(); + self.token = self.token(&mut buf); } self.eof(&mut buf); buf.into_token_stream() } - fn token(&mut self) -> TokenWithIndents { + fn token(&mut self, tok_stream_builder: &mut TokenStreamBuilder) -> TokenWithIndents { loop { let start_src_index = self.src_index(self.pos); let text: &str = &self.src[start_src_index..self.end_src_index]; @@ -176,12 +185,19 @@ impl<'a> Lexer<'a> { // Detect and handle indent cases before lexing on-going token let indent = self.lex_indent_context(token.kind); - let start = self.pos; + // Because of the 'look-behind', the 'start' of the current token becomes a two-way cursor, + // which can not only move forward, but also move backward when 'look-behind'. + // Therefore, the value of 'self.tok_start_pos' can be changed in 'self.lex_token()'. + self.tok_start_pos = self.pos; // update pos after token and indent handling self.pos = self.pos + new_byte_pos(token.len as u32); - if let Some(kind) = self.lex_token(token, start) { - let span = self.span(start, self.pos); + // In the process of look-behind lexing, it is necessary to check the type of the previous token in 'tok_stream_builder', + // If the previous token and the current token can form a multi-character token, + // then the previous token will be popped from 'tok_stream_builder'. + // Therefore, the method 'self.lex_token()' needs to take the mutable reference of 'tok_stream_builder' as an incoming argument. + if let Some(kind) = self.lex_token(token, self.tok_start_pos, tok_stream_builder) { + let span = self.span(self.tok_start_pos, self.pos); match indent { Some(iord) => { @@ -203,7 +219,12 @@ impl<'a> Lexer<'a> { } /// Turns `kclvm_lexer::TokenKind` into a rich `kclvm_ast::TokenKind`. - fn lex_token(&mut self, token: kclvm_lexer::Token, start: BytePos) -> Option { + fn lex_token( + &mut self, + token: kclvm_lexer::Token, + start: BytePos, + tok_stream_builder: &mut TokenStreamBuilder, + ) -> Option { Some(match token.kind { kclvm_lexer::TokenKind::LineComment { doc_style: _ } => { let s = self.str_from(start); @@ -245,22 +266,7 @@ impl<'a> Lexer<'a> { } // Binary op kclvm_lexer::TokenKind::Plus => token::BinOp(token::Plus), - kclvm_lexer::TokenKind::Minus => { - let head = start + new_byte_pos(1); - let tail = start + new_byte_pos(2); - if self.has_next_token(head, tail) { - let next_tkn = self.str_from_to(head, tail); - if next_tkn == ">" { - // waste '>' token - self.pos = self.pos + new_byte_pos(1); - token::RArrow - } else { - token::BinOp(token::Minus) - } - } else { - token::BinOp(token::Minus) - } - } + kclvm_lexer::TokenKind::Minus => token::BinOp(token::Minus), kclvm_lexer::TokenKind::Star => token::BinOp(token::Star), kclvm_lexer::TokenKind::Slash => token::BinOp(token::Slash), kclvm_lexer::TokenKind::Percent => token::BinOp(token::Percent), @@ -289,7 +295,13 @@ impl<'a> Lexer<'a> { kclvm_lexer::TokenKind::BangEq => token::BinCmp(token::NotEq), kclvm_lexer::TokenKind::Lt => token::BinCmp(token::Lt), kclvm_lexer::TokenKind::LtEq => token::BinCmp(token::LtEq), - kclvm_lexer::TokenKind::Gt => token::BinCmp(token::Gt), + // If the current token is '>', + // then lexer need to check whether the previous token is '-', + // if yes, return token '->', if not return token '>'. + kclvm_lexer::TokenKind::Gt => match self.look_behind(&token, tok_stream_builder) { + Some(tok_kind) => tok_kind, + None => token::BinCmp(token::Gt), + }, kclvm_lexer::TokenKind::GtEq => token::BinCmp(token::GtEq), // Structural symbols kclvm_lexer::TokenKind::At => token::At, @@ -424,6 +436,14 @@ impl<'a> Lexer<'a> { ); return None; } + kclvm_lexer::TokenKind::Semi => { + // If we encounter an illegal semi token ';', raise a friendly error. + self.sess.struct_span_error( + "the semicolon ';' here is unnecessary, please remove it", + self.span(start, self.pos), + ); + return None; + } _ => { self.sess .struct_span_error("unknown start of token", self.span(start, self.pos)); @@ -432,6 +452,37 @@ impl<'a> Lexer<'a> { }) } + /// From the lexed tokens stack, check whether the token at the top of the stack and the current character can combine a new token. + /// If yes, lexer will pop the token at the top of the stack and return a new token combined with the token poped and the current character. + /// If not, return None. + fn look_behind( + &mut self, + tok: &kclvm_lexer::Token, + tok_stream_builder: &mut TokenStreamBuilder, + ) -> Option { + match tok.kind { + // Most multi-character tokens are lexed in ['kclvm-lexer'], + // and the multi-character tokens that need to be lexed in ['kclvm-parser/lexer'] are only token '->'. + // If a new multi-character token is added later, the corresponding operation can be added here. + kclvm_lexer::TokenKind::Gt => { + if tok_stream_builder + .pop_if_tok_kind(&TokenKind::BinOp(BinOpToken::Minus)) + .is_some() + { + // After the previous token pops up, 'self.tok_start_pos' needs to be updated. + if self.tok_start_pos >= new_byte_pos(1) { + self.tok_start_pos = self.tok_start_pos - new_byte_pos(1); + return Some(TokenKind::RArrow); + } else { + bug!("Internal Bugs: Please connect us to fix it, invalid token start pos") + } + } + } + _ => return None, + } + None + } + fn lex_literal( &self, start: BytePos, @@ -647,10 +698,6 @@ impl<'a> Lexer<'a> { &self.src[self.src_index(start)..self.src_index(end)] } - fn has_next_token(&self, start: BytePos, end: BytePos) -> bool { - !(self.src_index(start) > self.src_index(end) || self.src_index(end) > self.src.len()) - } - fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol { Symbol::intern(self.str_from_to(start, end)) } @@ -663,7 +710,10 @@ impl<'a> Lexer<'a> { while self.indent_cxt.indents.len() > 1 { self.indent_cxt.indents.pop(); - buf.push(Token::new(token::Dedent, self.span(self.pos, self.pos))); + buf.push(Token::new( + token::Dedent(VALID_SPACES_LENGTH), + self.span(self.pos, self.pos), + )); } buf.push(Token::new(token::Eof, self.span(self.pos, self.pos))); @@ -683,4 +733,27 @@ impl TokenStreamBuilder { fn into_token_stream(self) -> TokenStream { TokenStream::new(self.buf) } + + /// Pop the token at the top of the stack, and return None if the stack is empty. + fn pop(&mut self) -> Option { + self.buf.pop() + } + + /// If the token kind at the top of the stack is 'expected_tok_kind', + /// pop the token and return it, otherwise do nothing and return None. + fn pop_if_tok_kind(&mut self, expected_tok_kind: &TokenKind) -> Option { + if self.peek_tok_kind() == expected_tok_kind { + self.pop() + } else { + None + } + } + + /// Peek the kind of the token on the top of the stack. + fn peek_tok_kind(&self) -> &TokenKind { + match self.buf.last() { + Some(tok) => &tok.kind, + None => &TokenKind::Dummy, + } + } } diff --git a/kclvm/parser/src/lexer/tests.rs b/kclvm/parser/src/lexer/tests.rs index ac2b27a19..8d6ec4b75 100644 --- a/kclvm/parser/src/lexer/tests.rs +++ b/kclvm/parser/src/lexer/tests.rs @@ -21,23 +21,52 @@ impl ParseSession { } } -fn check_lexing(src: &str, expect: Expect) { +/// lexing the 'src'. +fn lex(src: &str) -> (String, String) { let sm = SourceMap::new(FilePathMapping::empty()); - let sf = sm.new_source_file(PathBuf::from("").into(), src.to_string()); + sm.new_source_file(PathBuf::from("").into(), src.to_string()); let sess = &ParseSession::with_source_map(Arc::new(sm)); - match sf.src.as_ref() { - Some(src_from_sf) => { - create_session_globals_then(|| { - let actual: String = parse_token_streams(sess, src_from_sf, new_byte_pos(0)) - .iter() - .map(|token| format!("{token:?}\n")) - .collect(); - expect.assert_eq(&actual) - }); + // preprocess the input str by [`SourceFile`] + let sf = sess + .0 + .sm + .new_source_file(PathBuf::from("").into(), src.to_string()); + + let src_from_sf = match sf.src.as_ref() { + Some(src) => src, + None => { + panic!("Unreachable code") } - None => todo!(), }; + + let res = create_session_globals_then(|| { + parse_token_streams(sess, src_from_sf, new_byte_pos(0)) + .iter() + .map(|token| format!("{:?}\n", token)) + .collect() + }); + + let err_msgs = sess + .0 + .emit_all_diags_into_string() + .unwrap() + .iter() + .map(|err| err.as_ref().unwrap().to_string()) + .collect(); + + (res, err_msgs) +} + +/// check the invalid panic message. +fn check_lexing_with_err_msg(src: &str, expect: Expect, expect_err_msg: Expect) { + let (got, got_err) = lex(src); + expect.assert_eq(&got); + expect_err_msg.assert_eq(&got_err); +} + +fn check_lexing(src: &str, expect: Expect) { + expect.assert_eq(&lex(src).0); } // Get the code snippets from 'src' by token.span, and compare with expect. @@ -373,29 +402,29 @@ println("end") Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 4, len_or_tag: 5 } } Token { kind: Colon, span: Span { base_or_index: 9, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 10, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 15, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 15, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 10 })), span: Span { base_or_index: 15, len_or_tag: 2 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 18, len_or_tag: 5 } } Token { kind: Colon, span: Span { base_or_index: 23, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 24, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 33, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 33, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 44 })), span: Span { base_or_index: 33, len_or_tag: 7 } } Token { kind: OpenDelim(Paren), span: Span { base_or_index: 40, len_or_tag: 1 } } Token { kind: Literal(Lit { kind: Str { is_long_string: false, is_raw: false }, symbol: Symbol(SymbolIndex { idx: 45 }), suffix: None, raw: Some(Symbol(SymbolIndex { idx: 46 })) }), span: Span { base_or_index: 41, len_or_tag: 11 } } Token { kind: CloseDelim(Paren), span: Span { base_or_index: 52, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 53, len_or_tag: 1 } } - Token { kind: Dedent, span: Span { base_or_index: 58, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 58, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 12 })), span: Span { base_or_index: 58, len_or_tag: 4 } } Token { kind: Colon, span: Span { base_or_index: 62, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 63, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 72, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 72, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 44 })), span: Span { base_or_index: 72, len_or_tag: 7 } } Token { kind: OpenDelim(Paren), span: Span { base_or_index: 79, len_or_tag: 1 } } Token { kind: Literal(Lit { kind: Str { is_long_string: false, is_raw: false }, symbol: Symbol(SymbolIndex { idx: 47 }), suffix: None, raw: Some(Symbol(SymbolIndex { idx: 48 })) }), span: Span { base_or_index: 80, len_or_tag: 12 } } Token { kind: CloseDelim(Paren), span: Span { base_or_index: 92, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 93, len_or_tag: 1 } } - Token { kind: Dedent, span: Span { base_or_index: 94, len_or_tag: 0 } } - Token { kind: Dedent, span: Span { base_or_index: 94, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 94, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 94, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 44 })), span: Span { base_or_index: 94, len_or_tag: 7 } } Token { kind: OpenDelim(Paren), span: Span { base_or_index: 101, len_or_tag: 1 } } Token { kind: Literal(Lit { kind: Str { is_long_string: false, is_raw: false }, symbol: Symbol(SymbolIndex { idx: 49 }), suffix: None, raw: Some(Symbol(SymbolIndex { idx: 50 })) }), span: Span { base_or_index: 102, len_or_tag: 5 } } @@ -440,12 +469,12 @@ Schema (1, 2) { Token { kind: CloseDelim(Paren), span: Span { base_or_index: 13, len_or_tag: 1 } } Token { kind: OpenDelim(Brace), span: Span { base_or_index: 15, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 16, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 21, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 21, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 21, len_or_tag: 1 } } Token { kind: Assign, span: Span { base_or_index: 22, len_or_tag: 1 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 44 })), span: Span { base_or_index: 23, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 24, len_or_tag: 1 } } - Token { kind: Dedent, span: Span { base_or_index: 25, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 25, len_or_tag: 0 } } Token { kind: CloseDelim(Brace), span: Span { base_or_index: 25, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 26, len_or_tag: 1 } } Token { kind: Eof, span: Span { base_or_index: 27, len_or_tag: 0 } } @@ -468,12 +497,12 @@ fn schema_expr_1() { Token { kind: CloseDelim(Paren), span: Span { base_or_index: 12, len_or_tag: 1 } } Token { kind: OpenDelim(Brace), span: Span { base_or_index: 14, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 15, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 20, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 20, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 20, len_or_tag: 1 } } Token { kind: Assign, span: Span { base_or_index: 21, len_or_tag: 1 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 44 })), span: Span { base_or_index: 22, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 23, len_or_tag: 1 } } - Token { kind: Dedent, span: Span { base_or_index: 24, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 24, len_or_tag: 0 } } Token { kind: CloseDelim(Brace), span: Span { base_or_index: 24, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 25, len_or_tag: 0 } } Token { kind: Eof, span: Span { base_or_index: 25, len_or_tag: 0 } } @@ -614,7 +643,7 @@ fn test_parse_token_stream_on_win() { Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 8, len_or_tag: 6 } } Token { kind: Colon, span: Span { base_or_index: 14, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 15, len_or_tag: 1 } } - Token { kind: Indent, span: Span { base_or_index: 20, len_or_tag: 0 } } + Token { kind: Indent(0), span: Span { base_or_index: 20, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 20, len_or_tag: 4 } } Token { kind: Colon, span: Span { base_or_index: 24, len_or_tag: 1 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 31 })), span: Span { base_or_index: 26, len_or_tag: 3 } } @@ -622,7 +651,7 @@ fn test_parse_token_stream_on_win() { Token { kind: Literal(Lit { kind: Str { is_long_string: false, is_raw: false }, symbol: Symbol(SymbolIndex { idx: 44 }), suffix: None, raw: Some(Symbol(SymbolIndex { idx: 45 })) }), span: Span { base_or_index: 32, len_or_tag: 5 } } Token { kind: Newline, span: Span { base_or_index: 37, len_or_tag: 1 } } Token { kind: Newline, span: Span { base_or_index: 38, len_or_tag: 1 } } - Token { kind: Dedent, span: Span { base_or_index: 39, len_or_tag: 0 } } + Token { kind: Dedent(0), span: Span { base_or_index: 39, len_or_tag: 0 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 46 })), span: Span { base_or_index: 39, len_or_tag: 2 } } Token { kind: Assign, span: Span { base_or_index: 42, len_or_tag: 1 } } Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 44, len_or_tag: 6 } } @@ -633,3 +662,190 @@ fn test_parse_token_stream_on_win() { "#]], ); } + +#[test] +fn test_rarrow() { + check_lexing( + "lambda x: int, y: int -> int { x + y }\n", + expect![[r#" + Token { kind: Ident(Symbol(SymbolIndex { idx: 18 })), span: Span { base_or_index: 0, len_or_tag: 6 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 7, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 8, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 10, len_or_tag: 3 } } + Token { kind: Comma, span: Span { base_or_index: 13, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 15, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 16, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 18, len_or_tag: 3 } } + Token { kind: RArrow, span: Span { base_or_index: 22, len_or_tag: 2 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 25, len_or_tag: 3 } } + Token { kind: OpenDelim(Brace), span: Span { base_or_index: 29, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 31, len_or_tag: 1 } } + Token { kind: BinOp(Plus), span: Span { base_or_index: 33, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 35, len_or_tag: 1 } } + Token { kind: CloseDelim(Brace), span: Span { base_or_index: 37, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 38, len_or_tag: 1 } } + Token { kind: Eof, span: Span { base_or_index: 39, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_minus_unicode_gt_invalid() { + check_lexing_with_err_msg( + "lambda x: int, y: int -\u{feff}> int { x + y }\n", + expect![[r#" + Token { kind: Ident(Symbol(SymbolIndex { idx: 18 })), span: Span { base_or_index: 0, len_or_tag: 6 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 7, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 8, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 10, len_or_tag: 3 } } + Token { kind: Comma, span: Span { base_or_index: 13, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 15, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 16, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 18, len_or_tag: 3 } } + Token { kind: RArrow, span: Span { base_or_index: 25, len_or_tag: 2 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 28, len_or_tag: 3 } } + Token { kind: OpenDelim(Brace), span: Span { base_or_index: 32, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 34, len_or_tag: 1 } } + Token { kind: BinOp(Plus), span: Span { base_or_index: 36, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 38, len_or_tag: 1 } } + Token { kind: CloseDelim(Brace), span: Span { base_or_index: 40, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 41, len_or_tag: 1 } } + Token { kind: Eof, span: Span { base_or_index: 42, len_or_tag: 0 } } + "#]], + expect![["error[E1001]: InvalidSyntax\nunknown start of token\n\n"]], + ); +} + +#[test] +fn test_unicode_minus_gt_invalid() { + check_lexing_with_err_msg( + "lambda x: int, y: int \u{feff}-> int { x + y }\n", + expect![[r#" + Token { kind: Ident(Symbol(SymbolIndex { idx: 18 })), span: Span { base_or_index: 0, len_or_tag: 6 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 7, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 8, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 10, len_or_tag: 3 } } + Token { kind: Comma, span: Span { base_or_index: 13, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 15, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 16, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 18, len_or_tag: 3 } } + Token { kind: RArrow, span: Span { base_or_index: 25, len_or_tag: 2 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 28, len_or_tag: 3 } } + Token { kind: OpenDelim(Brace), span: Span { base_or_index: 32, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 34, len_or_tag: 1 } } + Token { kind: BinOp(Plus), span: Span { base_or_index: 36, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 38, len_or_tag: 1 } } + Token { kind: CloseDelim(Brace), span: Span { base_or_index: 40, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 41, len_or_tag: 1 } } + Token { kind: Eof, span: Span { base_or_index: 42, len_or_tag: 0 } } + "#]], + expect![["error[E1001]: InvalidSyntax\nunknown start of token\n\n"]], + ); +} + +#[test] +fn test_minus_gt_unicode_invalid() { + check_lexing_with_err_msg( + "lambda x: int, y: int ->\u{feff} int { x + y }\n", + expect![[r#" + Token { kind: Ident(Symbol(SymbolIndex { idx: 18 })), span: Span { base_or_index: 0, len_or_tag: 6 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 7, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 8, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 10, len_or_tag: 3 } } + Token { kind: Comma, span: Span { base_or_index: 13, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 15, len_or_tag: 1 } } + Token { kind: Colon, span: Span { base_or_index: 16, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 18, len_or_tag: 3 } } + Token { kind: RArrow, span: Span { base_or_index: 22, len_or_tag: 2 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 30 })), span: Span { base_or_index: 28, len_or_tag: 3 } } + Token { kind: OpenDelim(Brace), span: Span { base_or_index: 32, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 34, len_or_tag: 1 } } + Token { kind: BinOp(Plus), span: Span { base_or_index: 36, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 43 })), span: Span { base_or_index: 38, len_or_tag: 1 } } + Token { kind: CloseDelim(Brace), span: Span { base_or_index: 40, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 41, len_or_tag: 1 } } + Token { kind: Eof, span: Span { base_or_index: 42, len_or_tag: 0 } } + "#]], + expect![["error[E1001]: InvalidSyntax\nunknown start of token\n\n"]], + ); +} + +#[test] +fn test_only_minus() { + check_lexing( + "-", + expect![[r#" + Token { kind: BinOp(Minus), span: Span { base_or_index: 0, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 1, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 1, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_begin_with_minus() { + check_lexing( + "-123", + expect![[r#" + Token { kind: BinOp(Minus), span: Span { base_or_index: 0, len_or_tag: 1 } } + Token { kind: Literal(Lit { kind: Integer, symbol: Symbol(SymbolIndex { idx: 42 }), suffix: None, raw: None }), span: Span { base_or_index: 1, len_or_tag: 3 } } + Token { kind: Newline, span: Span { base_or_index: 4, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 4, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_only_gt() { + check_lexing( + ">", + expect![[r#" + Token { kind: BinCmp(Gt), span: Span { base_or_index: 0, len_or_tag: 1 } } + Token { kind: Newline, span: Span { base_or_index: 1, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 1, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_begin_with_gt() { + check_lexing( + ">sdjkd + ==", + expect![[r#" + Token { kind: BinCmp(Gt), span: Span { base_or_index: 0, len_or_tag: 1 } } + Token { kind: Ident(Symbol(SymbolIndex { idx: 42 })), span: Span { base_or_index: 1, len_or_tag: 5 } } + Token { kind: BinOp(Plus), span: Span { base_or_index: 7, len_or_tag: 1 } } + Token { kind: BinCmp(Eq), span: Span { base_or_index: 9, len_or_tag: 2 } } + Token { kind: Newline, span: Span { base_or_index: 11, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 11, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_double_rarrow() { + check_lexing( + "->->", + expect![[r#" + Token { kind: RArrow, span: Span { base_or_index: 0, len_or_tag: 2 } } + Token { kind: RArrow, span: Span { base_or_index: 2, len_or_tag: 2 } } + Token { kind: Newline, span: Span { base_or_index: 4, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 4, len_or_tag: 0 } } + "#]], + ); +} + +#[test] +fn test_mess_rarrow() { + check_lexing( + "-->>->", + expect![[r#" + Token { kind: BinOp(Minus), span: Span { base_or_index: 0, len_or_tag: 1 } } + Token { kind: BinOp(Minus), span: Span { base_or_index: 1, len_or_tag: 1 } } + Token { kind: BinOp(Shr), span: Span { base_or_index: 2, len_or_tag: 2 } } + Token { kind: RArrow, span: Span { base_or_index: 4, len_or_tag: 2 } } + Token { kind: Newline, span: Span { base_or_index: 6, len_or_tag: 0 } } + Token { kind: Eof, span: Span { base_or_index: 6, len_or_tag: 0 } } + "#]], + ); +} diff --git a/kclvm/parser/src/lib.rs b/kclvm/parser/src/lib.rs index 47e98f0f7..32fddf76e 100644 --- a/kclvm/parser/src/lib.rs +++ b/kclvm/parser/src/lib.rs @@ -1,5 +1,7 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. +pub mod entry; +pub mod file_graph; mod lexer; mod parser; mod session; @@ -9,26 +11,27 @@ mod tests; extern crate kclvm_error; -pub use crate::session::ParseSession; +use crate::entry::get_compile_entries_from_paths; +pub use crate::session::{ParseSession, ParseSessionRef}; use compiler_base_macros::bug; use compiler_base_session::Session; use compiler_base_span::span::new_byte_pos; +use file_graph::FileGraph; +use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast; -use kclvm_config::modfile::{ - get_pkg_root_from_paths, get_vendor_home, KCL_FILE_EXTENSION, KCL_FILE_SUFFIX, KCL_MOD_FILE, - KCL_MOD_PATH_ENV, -}; +use kclvm_config::modfile::{get_vendor_home, KCL_FILE_EXTENSION, KCL_FILE_SUFFIX, KCL_MOD_FILE}; +use kclvm_error::diagnostic::{Diagnostic, Range}; use kclvm_error::{ErrorKind, Message, Position, Style}; use kclvm_sema::plugin::PLUGIN_MODULE_PREFIX; -use kclvm_utils::path::PathPrefix; use kclvm_utils::pkgpath::parse_external_pkg_name; use kclvm_utils::pkgpath::rm_external_pkg_name; +use anyhow::Result; use lexer::parse_token_streams; use parser::Parser; use std::collections::HashMap; -use std::path::PathBuf; -use std::sync::Arc; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, RwLock}; use kclvm_span::create_session_globals_then; @@ -69,45 +72,82 @@ pub enum ParseMode { ParseComments, } -/// Parse a KCL file to the AST Program. -pub fn parse_program(filename: &str) -> Result { - let abspath = std::fs::canonicalize(std::path::PathBuf::from(filename)).unwrap(); +type Errors = IndexSet; - let mut prog = ast::Program { - root: abspath.parent().unwrap().adjust_canonicalization(), - main: kclvm_ast::MAIN_PKG.to_string(), - pkgs: HashMap::new(), - }; - - let mut module = parse_file(abspath.to_str().unwrap(), None)?; - module.filename = filename.to_string(); - module.pkg = kclvm_ast::MAIN_PKG.to_string(); - module.name = kclvm_ast::MAIN_PKG.to_string(); +/// LoadProgramResult denotes the result of the whole program and a topological +/// ordering of all known files, +#[derive(Debug, Clone)] +pub struct LoadProgramResult { + /// Program AST + pub program: ast::Program, + /// Parse errors + pub errors: Errors, + /// The topological ordering of all known files. + pub paths: Vec, +} - prog.pkgs - .insert(kclvm_ast::MAIN_PKG.to_string(), vec![module]); +/// ParseFileResult denotes the result of a single file including AST, +/// errors and import dependencies. +#[derive(Debug, Clone)] +pub struct ParseFileResult { + /// Module AST + pub module: ast::Module, + /// Parse errors + pub errors: Errors, + /// Dependency paths. + pub deps: Vec, +} - Ok(prog) +/// Parse a KCL file to the AST module with parse errors. +pub fn parse_file(filename: &str, code: Option) -> Result { + let sess = Arc::new(ParseSession::default()); + let mut loader = Loader::new( + sess, + &[filename], + Some(LoadProgramOptions { + load_packages: false, + k_code_list: if let Some(code) = code { + vec![code] + } else { + vec![] + }, + ..Default::default() + }), + None, + ); + let result = loader.load_main()?; + let module = match result.program.get_main_package_first_module() { + Some(module) => module.clone(), + None => ast::Module::default(), + }; + let filename = module.filename.clone(); + let path = Path::new(&filename); + Ok(ParseFileResult { + module, + errors: result.errors.clone(), + deps: if loader.file_graph.contains_file(path) { + loader + .file_graph + .dependencies_of(path) + .into_iter() + .cloned() + .collect() + } else { + vec![] + }, + }) } -/// Parse a KCL file to the AST module. -#[inline] -pub fn parse_file(filename: &str, code: Option) -> Result { +/// Parse a KCL file to the AST module and return errors when meets parse errors as result. +pub fn parse_file_force_errors(filename: &str, code: Option) -> Result { let sess = Arc::new(ParseSession::default()); let result = parse_file_with_global_session(sess.clone(), filename, code); - if sess - .0 - .diag_handler - .has_errors() - .map_err(|e| e.to_string())? - { + if sess.0.diag_handler.has_errors()? { let err = sess .0 - .emit_nth_diag_into_string(0) - .map_err(|e| e.to_string())? - .unwrap_or(Ok(ErrorKind::InvalidSyntax.name())) - .map_err(|e| e.to_string())?; - Err(err) + .emit_nth_diag_into_string(0)? + .unwrap_or(Ok(ErrorKind::InvalidSyntax.name()))?; + Err(anyhow::anyhow!(err)) } else { result } @@ -115,10 +155,10 @@ pub fn parse_file(filename: &str, code: Option) -> Result, + sess: ParseSessionRef, filename: &str, code: Option, -) -> Result { +) -> Result { // Code source. let src = if let Some(s) = code { s @@ -126,7 +166,7 @@ pub fn parse_file_with_session( match std::fs::read_to_string(filename) { Ok(src) => src, Err(err) => { - return Err(format!( + return Err(anyhow::anyhow!( "Failed to load KCL file '{filename}'. Because '{err}'" )); } @@ -142,7 +182,7 @@ pub fn parse_file_with_session( let src_from_sf = match sf.src.as_ref() { Some(src) => src, None => { - return Err(format!( + return Err(anyhow::anyhow!( "Internal Bug: Failed to load KCL file '{filename}'." )); } @@ -163,10 +203,10 @@ pub fn parse_file_with_session( /// Parse a KCL file to the AST module with the parse session and the global session #[inline] pub fn parse_file_with_global_session( - sess: Arc, + sess: ParseSessionRef, filename: &str, code: Option, -) -> Result { +) -> Result { create_session_globals_then(move || parse_file_with_session(sess, filename, code)) } @@ -214,9 +254,6 @@ pub struct LoadProgramOptions { pub k_code_list: Vec, pub vendor_dirs: Vec, pub package_maps: HashMap, - - pub cmd_args: Vec, - pub cmd_overrides: Vec, /// The parser mode. pub mode: ParseMode, /// Whether to load packages. @@ -232,8 +269,6 @@ impl Default for LoadProgramOptions { k_code_list: Default::default(), vendor_dirs: vec![get_vendor_home()], package_maps: Default::default(), - cmd_args: Default::default(), - cmd_overrides: Default::default(), mode: ParseMode::ParseComments, load_packages: true, load_plugins: false, @@ -241,79 +276,144 @@ impl Default for LoadProgramOptions { } } +/// Load the KCL program by paths and options, +/// "module_cache" is used to cache parsed asts to support incremental parse, +/// if it is None, module caching will be disabled +/// +/// # Examples +/// +/// ``` +/// use kclvm_parser::{load_program, ParseSession}; +/// use kclvm_parser::KCLModuleCache; +/// use kclvm_ast::ast::Program; +/// use std::sync::Arc; +/// +/// // Create sessions +/// let sess = Arc::new(ParseSession::default()); +/// // Create module cache +/// let module_cache = KCLModuleCache::default(); +/// +/// // Parse kcl file +/// let kcl_path = "./testdata/import-01.k"; +/// let prog = load_program(sess.clone(), &[kcl_path], None, Some(module_cache.clone())).unwrap(); +/// +/// ``` pub fn load_program( - sess: Arc, + sess: ParseSessionRef, paths: &[&str], opts: Option, -) -> Result { - // todo: support cache - if let Some(opts) = opts { - Loader::new(sess, paths, Some(opts)).load_main() - } else { - Loader::new(sess, paths, None).load_main() - } + module_cache: Option, +) -> Result { + Loader::new(sess, paths, opts, module_cache).load_main() } +pub type KCLModuleCache = Arc>>; struct Loader { - sess: Arc, + sess: ParseSessionRef, paths: Vec, opts: LoadProgramOptions, missing_pkgs: Vec, + module_cache: Option, + file_graph: FileGraph, } impl Loader { - fn new(sess: Arc, paths: &[&str], opts: Option) -> Self { + fn new( + sess: ParseSessionRef, + paths: &[&str], + opts: Option, + module_cache: Option>>>, + ) -> Self { Self { sess, paths: paths.iter().map(|s| s.to_string()).collect(), opts: opts.unwrap_or_default(), + module_cache, missing_pkgs: Default::default(), + file_graph: FileGraph::default(), } } #[inline] - fn load_main(&mut self) -> Result { + fn load_main(&mut self) -> Result { create_session_globals_then(move || self._load_main()) } - fn _load_main(&mut self) -> Result { - let root = get_pkg_root_from_paths(&self.paths)?; - let main_pkg_name = kclvm_ast::MAIN_PKG.to_string(); - - // Get files from options with root. - let k_files = self.get_main_files(&root)?; - - // load module + fn _load_main(&mut self) -> Result { + let compile_entries = get_compile_entries_from_paths(&self.paths, &self.opts)?; + let workdir = compile_entries.get_root_path().to_string(); let mut pkgs = HashMap::new(); let mut pkg_files = Vec::new(); - for (i, filename) in k_files.iter().enumerate() { - if i < self.opts.k_code_list.len() { - let mut m = parse_file_with_session( - self.sess.clone(), - filename, - Some(self.opts.k_code_list[i].clone()), - )?; - self.fix_rel_import_path(&root, &mut m); - pkg_files.push(m) - } else { - let mut m = parse_file_with_session(self.sess.clone(), filename, None)?; - self.fix_rel_import_path(&root, &mut m); + for entry in compile_entries.iter() { + // Get files from options with root. + // let k_files = self.get_main_files_from_pkg(entry.path(), entry.name())?; + let k_files = entry.get_k_files(); + let maybe_k_codes = entry.get_k_codes(); + // Load main package. + for (i, filename) in k_files.iter().enumerate() { + let mut m = if let Some(module_cache) = self.module_cache.as_ref() { + let m = parse_file_with_session( + self.sess.clone(), + filename, + maybe_k_codes[i].clone(), + )?; + let mut module_cache_ref = module_cache.write().unwrap(); + module_cache_ref.insert(filename.clone(), m.clone()); + m + } else { + parse_file_with_session(self.sess.clone(), filename, maybe_k_codes[i].clone())? + }; + fix_rel_import_path(entry.path(), &mut m); pkg_files.push(m); } - } - - // Insert an empty vec to determine whether there is a circular import. - pkgs.insert(kclvm_ast::MAIN_PKG.to_string(), vec![]); - - self.load_import_package(&root, main_pkg_name, &mut pkg_files, &mut pkgs)?; + // Insert an empty vec to determine whether there is a circular import. + pkgs.insert(kclvm_ast::MAIN_PKG.to_string(), vec![]); + self.load_import_package( + entry.path(), + entry.name().to_string(), + &mut pkg_files, + &mut pkgs, + )?; + } // Insert the complete ast to replace the empty list. pkgs.insert(kclvm_ast::MAIN_PKG.to_string(), pkg_files); - - Ok(ast::Program { - root, - main: kclvm_ast::MAIN_PKG.to_string(), + let program = ast::Program { + root: workdir, pkgs, + }; + // Return the files in the order they should be compiled + let paths = match self.file_graph.toposort() { + Ok(files) => files, + Err(cycle) => { + let formatted_cycle = cycle + .iter() + .map(|path| format!("- {}\n", path.to_string_lossy())) + .collect::(); + + self.sess.1.borrow_mut().add_error( + ErrorKind::RecursiveLoad, + &[Message { + range: (Position::dummy_pos(), Position::dummy_pos()), + style: Style::Line, + message: format!( + "Could not compiles due to cyclic import statements\n{}", + formatted_cycle.trim_end() + ), + note: None, + suggested_replacement: None, + }], + ); + + // Return a list of all paths. + self.file_graph.paths() + } + }; + + Ok(LoadProgramResult { + program, + errors: self.sess.1.borrow().diagnostics.clone(), + paths, }) } @@ -332,7 +432,7 @@ impl Loader { pkg_name: &str, pkg_root: &str, pkg_path: &str, - ) -> Result, String> { + ) -> Result> { // 1. Look for in the current package's directory. let is_internal = self.is_internal_pkg(pkg_name, pkg_root, pkg_path)?; @@ -344,13 +444,14 @@ impl Loader { self.sess.1.borrow_mut().add_error( ErrorKind::CannotFindModule, &[Message { - pos: Into::<(Position, Position)>::into(pos).0, + range: Into::::into(pos), style: Style::Line, message: format!( "the `{}` is found multiple times in the current package and vendor package", pkg_path ), note: None, + suggested_replacement: None, }], ); return Ok(None); @@ -358,20 +459,34 @@ impl Loader { // 4. Get package information based on whether the package is internal or external. match is_internal.or(is_external) { - Some(pkg_info) => return Ok(Some(pkg_info)), + Some(pkg_info) => Ok(Some(pkg_info)), None => { self.sess.1.borrow_mut().add_error( ErrorKind::CannotFindModule, &[Message { - pos: Into::<(Position, Position)>::into(pos).0, + range: Into::::into(pos), style: Style::Line, message: format!("pkgpath {} not found in the program", pkg_path), note: None, + suggested_replacement: None, }], ); - return Ok(None); + let mut suggestions = + vec![format!("find more package on 'https://artifacthub.io'")]; + + if let Ok(pkg_name) = parse_external_pkg_name(pkg_path) { + suggestions.insert( + 0, + format!( + "try 'kcl mod add {}' to download the package not found", + pkg_name + ), + ); + } + self.sess.1.borrow_mut().add_suggestions(suggestions); + Ok(None) } - }; + } } /// [`load_import_package`] will traverse all the [`kclvm_ast::ImportStmt`] on the input AST nodes [`pkg`], @@ -387,102 +502,41 @@ impl Loader { pkg_name: String, pkg: &mut [ast::Module], pkgs: &mut HashMap>, - ) -> Result<(), String> { + ) -> Result<()> { for m in pkg { + let mut to_paths: Vec = vec![]; for stmt in &mut m.body { let pos = stmt.pos().clone(); if let ast::Stmt::Import(ref mut import_spec) = &mut stmt.node { - import_spec.path = kclvm_config::vfs::fix_import_path( + import_spec.path.node = kclvm_config::vfs::fix_import_path( pkgroot, &m.filename, - import_spec.path.as_str(), + import_spec.path.node.as_str(), ); import_spec.pkg_name = pkg_name.to_string(); // Load the import package source code and compile. - if let Some(pkg_info) = self.load_package( - &pkgroot, + let pkg_info = self.load_package( + pkgroot, pkg_name.to_string(), - import_spec.path.to_string(), + import_spec.path.node.to_string(), pos.into(), pkgs, - )? { + )?; + if let Some(pkg_info) = &pkg_info { // Add the external package name as prefix of the [`kclvm_ast::ImportStmt`]'s member [`path`]. - import_spec.path = pkg_info.pkg_path.to_string(); - import_spec.pkg_name = pkg_info.pkg_name + import_spec.path.node = pkg_info.pkg_path.to_string(); + import_spec.pkg_name = pkg_info.pkg_name.clone(); + // Add file dependencies. + let mut paths: Vec = + pkg_info.k_files.iter().map(PathBuf::from).collect(); + to_paths.append(&mut paths); } } } + self.file_graph + .update_file(Path::new(&m.filename), &to_paths); } - return Ok(()); - } - - /// Get files in the main package with the package root. - fn get_main_files(&mut self, root: &str) -> Result, String> { - // fix path - let mut path_list = Vec::new(); - for s in &self.paths { - let mut s = s.clone(); - if s.contains(KCL_MOD_PATH_ENV) { - s = s.replace(KCL_MOD_PATH_ENV, root); - } - if !root.is_empty() && !self.is_absolute(s.as_str()) { - let p = std::path::Path::new(s.as_str()); - if let Ok(x) = std::fs::canonicalize(p) { - s = x.adjust_canonicalization(); - } - } - - path_list.push(s); - } - - // get k files - let mut k_files: Vec = Vec::new(); - for (i, path) in path_list.iter().enumerate() { - // read dir/*.k - if self.is_dir(path) { - if self.opts.k_code_list.len() > i { - return Err("Invalid code list".to_string()); - } - //k_code_list - for s in self.get_dir_files(path)? { - k_files.push(s); - } - continue; - } else { - k_files.push(path.to_string()); - } - } - - if k_files.is_empty() { - return Err("No input KCL files".to_string()); - } - - // check all file exists - for (i, filename) in k_files.iter().enumerate() { - if i < self.opts.k_code_list.len() { - continue; - } - - if !self.path_exist(filename.as_str()) { - return Err(format!( - "Cannot find the kcl file, please check whether the file path {}", - filename.as_str(), - )); - } - } - Ok(k_files) - } - - fn fix_rel_import_path(&mut self, pkgroot: &str, m: &mut ast::Module) { - for stmt in &mut m.body { - if let ast::Stmt::Import(ref mut import_spec) = &mut stmt.node { - import_spec.path = kclvm_config::vfs::fix_import_path( - pkgroot, - &m.filename, - import_spec.path.as_str(), - ); - } - } + Ok(()) } /// [`load_package`] will return some basic information about the package @@ -494,11 +548,7 @@ impl Loader { pkgpath: String, pos: ast::Pos, pkgs: &mut HashMap>, - ) -> Result, String> { - if !self.opts.load_packages { - return Ok(None); - } - + ) -> Result> { if pkgpath.is_empty() { return Ok(None); } @@ -516,10 +566,11 @@ impl Loader { self.sess.1.borrow_mut().add_error( ErrorKind::CannotFindModule, &[Message { - pos: Into::<(Position, Position)>::into(pos).0, + range: Into::::into(pos), style: Style::Line, message: format!("the plugin package `{}` is not found, please confirm if plugin mode is enabled", pkgpath), note: None, + suggested_replacement: None, }], ); } @@ -544,17 +595,35 @@ impl Loader { if pkg_info.k_files.is_empty() { self.missing_pkgs.push(pkgpath); - return Ok(None); + return Ok(Some(pkg_info)); } + if !self.opts.load_packages { + return Ok(Some(pkg_info)); + } + + // Load packages let mut pkg_files = Vec::new(); let k_files = pkg_info.k_files.clone(); for filename in k_files { - let mut m = parse_file_with_session(self.sess.clone(), filename.as_str(), None)?; + let mut m = if let Some(module_cache) = self.module_cache.as_ref() { + let module_cache_ref = module_cache.read().unwrap(); + if let Some(module) = module_cache_ref.get(&filename) { + module.clone() + } else { + let m = parse_file_with_session(self.sess.clone(), &filename, None)?; + drop(module_cache_ref); + let mut module_cache_ref = module_cache.write().unwrap(); + module_cache_ref.insert(filename.clone(), m.clone()); + m + } + } else { + parse_file_with_session(self.sess.clone(), &filename, None)? + }; m.pkg = pkg_info.pkg_path.clone(); m.name = "".to_string(); - self.fix_rel_import_path(&pkg_info.pkg_root, &mut m); + fix_rel_import_path(&pkg_info.pkg_root, &mut m); pkg_files.push(m); } @@ -575,7 +644,7 @@ impl Loader { Ok(Some(pkg_info)) } - fn get_pkg_kfile_list(&self, pkgroot: &str, pkgpath: &str) -> Result, String> { + fn get_pkg_kfile_list(&self, pkgroot: &str, pkgpath: &str) -> Result> { // plugin pkgs if self.is_plugin_pkg(pkgpath) { return Ok(Vec::new()); @@ -587,7 +656,7 @@ impl Loader { } if pkgroot.is_empty() { - return Err("pkgroot not found".to_string()); + return Err(anyhow::anyhow!("pkgroot not found")); } let mut pathbuf = std::path::PathBuf::new(); @@ -612,7 +681,7 @@ impl Loader { } /// Get file list in the directory. - fn get_dir_files(&self, dir: &str) -> Result, String> { + fn get_dir_files(&self, dir: &str) -> Result> { if !std::path::Path::new(dir).exists() { return Ok(Vec::new()); } @@ -664,7 +733,7 @@ impl Loader { pkg_name: &str, pkg_root: &str, pkg_path: &str, - ) -> Result, String> { + ) -> Result> { match self.pkg_exists(vec![pkg_root.to_string()], pkg_path) { Some(internal_pkg_root) => { let fullpath = if pkg_name == kclvm_ast::MAIN_PKG { @@ -691,15 +760,13 @@ impl Loader { /// /// - [`is_external_pkg`] will return an error if the package's source files cannot be found. /// - The name of the external package could not be resolved from [`pkg_path`]. - fn is_external_pkg(&self, pkg_path: &str) -> Result, String> { + fn is_external_pkg(&self, pkg_path: &str) -> Result> { let pkg_name = parse_external_pkg_name(pkg_path)?; let external_pkg_root = if let Some(root) = self.opts.package_maps.get(&pkg_name) { PathBuf::from(root).join(KCL_MOD_FILE) } else { match self.pkg_exists(self.opts.vendor_dirs.clone(), pkg_path) { - Some(path) => PathBuf::from(path) - .join(pkg_name.to_string()) - .join(KCL_MOD_FILE), + Some(path) => PathBuf::from(path).join(&pkg_name).join(KCL_MOD_FILE), None => return Ok(None), } }; @@ -721,7 +788,7 @@ impl Loader { None => return Ok(None), })); } else { - return Ok(None); + Ok(None) } } @@ -746,17 +813,14 @@ impl Loader { } } -// utils -impl Loader { - fn is_dir(&self, path: &str) -> bool { - std::path::Path::new(path).is_dir() - } - - fn is_absolute(&self, path: &str) -> bool { - std::path::Path::new(path).is_absolute() - } - - fn path_exist(&self, path: &str) -> bool { - std::path::Path::new(path).exists() +fn fix_rel_import_path(pkgroot: &str, m: &mut ast::Module) { + for stmt in &mut m.body { + if let ast::Stmt::Import(ref mut import_spec) = &mut stmt.node { + import_spec.path.node = kclvm_config::vfs::fix_import_path( + pkgroot, + &m.filename, + import_spec.path.node.as_str(), + ); + } } } diff --git a/kclvm/parser/src/parser/expr.rs b/kclvm/parser/src/parser/expr.rs index 73404da76..b300f2c42 100644 --- a/kclvm/parser/src/parser/expr.rs +++ b/kclvm/parser/src/parser/expr.rs @@ -11,9 +11,10 @@ use either::{self, Either}; use kclvm_ast::node_ref; use crate::parser::precedence::Precedence; +use compiler_base_error_dev::unit_type::{TypeWithUnit, UnitUsize}; use kclvm_ast::ast::*; use kclvm_ast::token; -use kclvm_ast::token::{BinOpToken, DelimToken, TokenKind}; +use kclvm_ast::token::{BinOpToken, DelimToken, TokenKind, VALID_SPACES_LENGTH}; use kclvm_span::symbol::kw; /// Parser implementation of expressions, which consists of sub-expressions, @@ -24,6 +25,42 @@ use kclvm_span::symbol::kw; impl<'a> Parser<'a> { /// ~~~ Entrances + /// [`clean_all_indentations`] will bump all indent and dedent tokens. + pub(crate) fn clean_all_indentations(&mut self) { + self.clean_all_indent(); + self.clean_all_dedent(); + } + + // [`clean_all_indent`] will bump all indent tokens. + fn clean_all_indent(&mut self) { + while matches!(self.token.kind, TokenKind::Indent(_)) { + self.bump(); + } + } + + /// [`clean_all_dedent`] will bump all dedent tokens. + fn clean_all_dedent(&mut self) { + while matches!(self.token.kind, TokenKind::Dedent(_)) { + self.bump(); + } + } + + /// validate_dedent will check the number of spaces in indent and dedent tokens. + pub(crate) fn validate_dedent(&mut self) { + if let TokenKind::Dedent(n) = self.token.kind { + if n != 0 { + self.sess.struct_span_error( + &format!( + "invalid indentation with {}, try to align indents by adding or removing spaces", + UnitUsize(n, "space".to_string()).into_string_with_unit(), + ), + self.token.span, + ); + self.bump(); + } + } + } + /// Syntax: /// expr_list: expr (COMMA expr)* pub(crate) fn parse_exprlist(&mut self) -> Vec> { @@ -49,6 +86,14 @@ impl<'a> Parser<'a> { /// Syntax: /// test: if_expr | simple_expr pub(crate) fn parse_expr(&mut self) -> NodeRef { + if self.token.is_in_recovery_set() { + self.sess.struct_span_error( + &format!("unexpected '{:?}'", self.token.kind), + self.token.span, + ); + self.bump(); + } + let token = self.token; let operand = self.parse_simple_expr(); @@ -165,33 +210,37 @@ impl<'a> Parser<'a> { let y = self.do_parse_simple_expr(oprec); - // compare: a == b == c - if let BinOrCmpOp::Cmp(cmp_op) = op.clone() { - if cmp_expr.ops.is_empty() { - cmp_expr.left = x.clone(); + match op { + // compare: a == b == c + BinOrCmpOp::Cmp(cmp_op) => { + if cmp_expr.ops.is_empty() { + cmp_expr.left = x.clone(); + } + cmp_expr.ops.push(cmp_op); + cmp_expr.comparators.push(y); + continue; } - cmp_expr.ops.push(cmp_op); - cmp_expr.comparators.push(y); - continue; - } + // binary a + b + BinOrCmpOp::Bin(bin_op) => { + if !cmp_expr.ops.is_empty() { + x = Box::new(Node::node( + Expr::Compare(cmp_expr.clone()), + self.sess.struct_token_loc(token, self.prev_token), + )); + cmp_expr.ops = Vec::new(); + cmp_expr.comparators = Vec::new(); + } - if !cmp_expr.ops.is_empty() { - x = Box::new(Node::node( - Expr::Compare(cmp_expr.clone()), - self.sess.struct_token_loc(token, self.prev_token), - )); - cmp_expr.ops = Vec::new(); - cmp_expr.comparators = Vec::new(); + x = Box::new(Node::node( + Expr::Binary(BinaryExpr { + left: x, + op: bin_op, + right: y, + }), + self.sess.struct_token_loc(token, self.prev_token), + )); + } } - - x = Box::new(Node::node( - Expr::Binary(BinaryExpr { - left: x, - op, - right: y, - }), - self.sess.struct_token_loc(token, self.prev_token), - )); } } @@ -328,7 +377,13 @@ impl<'a> Parser<'a> { _ => { let attr = Box::new(Node::node( Identifier { - names: vec!["".to_string()], + names: vec![Node::node( + "".to_string(), + ( + self.sess.lookup_char_pos(self.token.span.lo()), + self.sess.lookup_char_pos(self.token.span.lo()), + ), + )], pkgpath: "".to_string(), ctx: ExprContext::Load, }, @@ -717,11 +772,13 @@ impl<'a> Parser<'a> { let has_newline = if self.token.kind == TokenKind::Newline { self.skip_newlines(); - if self.token.kind == TokenKind::Indent { + if self.token.kind == TokenKind::Indent(VALID_SPACES_LENGTH) { self.bump(); } else { - self.sess - .struct_token_error(&[TokenKind::Indent.into()], self.token) + self.sess.struct_token_error( + &[TokenKind::Indent(VALID_SPACES_LENGTH).into()], + self.token, + ) } true @@ -749,12 +806,14 @@ impl<'a> Parser<'a> { self.sess .struct_token_error(&[TokenKind::Newline.into()], self.token) } - - if self.token.kind == TokenKind::Dedent { + self.validate_dedent(); + if self.token.kind == TokenKind::Dedent(VALID_SPACES_LENGTH) { self.bump(); } else { - self.sess - .struct_token_error(&[TokenKind::Dedent.into()], self.token) + self.sess.struct_token_error( + &[TokenKind::Dedent(VALID_SPACES_LENGTH).into()], + self.token, + ) } } @@ -890,9 +949,8 @@ impl<'a> Parser<'a> { let has_newline = if self.token.kind == TokenKind::Newline { self.skip_newlines(); - if self.token.kind == TokenKind::Indent { - self.bump(); - } else if self.token.kind == TokenKind::CloseDelim(DelimToken::Bracket) { + self.clean_all_indentations(); + if self.token.kind == TokenKind::CloseDelim(DelimToken::Bracket) { // bump bracket close delim token `]` self.bump(); return Box::new(Node::node( @@ -902,17 +960,6 @@ impl<'a> Parser<'a> { }), self.sess.struct_token_loc(token, self.prev_token), )); - } else { - // If we don't find the indentation, skip and parse the next statement. - self.sess - .struct_token_error(&[TokenKind::Indent.into()], self.token); - return Box::new(Node::node( - Expr::List(ListExpr { - elts: vec![], - ctx: ExprContext::Load, - }), - self.sess.struct_token_loc(token, self.token), - )); } true } else { @@ -924,15 +971,8 @@ impl<'a> Parser<'a> { let generators = self.parse_comp_clauses(); // _DEDENT - if has_newline { - self.skip_newlines(); - if self.token.kind == TokenKind::Dedent { - self.bump(); - } else { - self.sess - .struct_token_error(&[TokenKind::Dedent.into()], self.token) - } - } + self.skip_newlines(); + self.clean_all_indentations(); // RIGHT_BRACKETS match self.token.kind { @@ -997,7 +1037,7 @@ impl<'a> Parser<'a> { /// list_items: expr ((COMMA [NEWLINE] | NEWLINE) expr)* [COMMA] [NEWLINE] pub(crate) fn parse_list_items(&mut self, has_newline: bool) -> Vec> { let is_terminator = |token: &kclvm_ast::token::Token| match &token.kind { - TokenKind::CloseDelim(DelimToken::Bracket) | TokenKind::Dedent | TokenKind::Eof => true, + TokenKind::CloseDelim(DelimToken::Bracket) | TokenKind::Eof => true, TokenKind::Newline if !has_newline => true, _ => token.is_keyword(kw::For), }; @@ -1016,6 +1056,7 @@ impl<'a> Parser<'a> { } loop { let marker = self.mark(); + self.clean_all_indentations(); if is_terminator(&self.token) { break; } @@ -1166,6 +1207,7 @@ impl<'a> Parser<'a> { x.node.orelse = if_item.orelse; let t = Node { + id: AstIndex::default(), node: Expr::ListIfItem(x.node), filename: x.filename, line: x.line, @@ -1196,12 +1238,13 @@ impl<'a> Parser<'a> { } self.skip_newlines(); - self.bump_token(TokenKind::Indent); + self.bump_token(TokenKind::Indent(VALID_SPACES_LENGTH)); let mut body = Vec::new(); loop { - if matches!(self.token.kind, TokenKind::Dedent) { + self.validate_dedent(); + if matches!(self.token.kind, TokenKind::Dedent(VALID_SPACES_LENGTH)) { break; } @@ -1212,8 +1255,8 @@ impl<'a> Parser<'a> { } self.skip_newlines(); } - - self.bump_token(TokenKind::Dedent); + self.validate_dedent(); + self.bump_token(TokenKind::Dedent(VALID_SPACES_LENGTH)); body } @@ -1238,22 +1281,13 @@ impl<'a> Parser<'a> { let has_newline = if self.token.kind == TokenKind::Newline { self.skip_newlines(); - if self.token.kind == TokenKind::Indent { - self.bump(); - } else if self.token.kind == TokenKind::CloseDelim(DelimToken::Brace) { + self.clean_all_indentations(); + if self.token.kind == TokenKind::CloseDelim(DelimToken::Brace) { self.bump(); return Box::new(Node::node( Expr::Config(ConfigExpr { items: vec![] }), self.sess.struct_token_loc(token, self.prev_token), )); - } else { - // If we don't find the indentation, skip and parse the next statement. - self.sess - .struct_token_error(&[TokenKind::Indent.into()], self.token); - return Box::new(Node::node( - Expr::Config(ConfigExpr { items: vec![] }), - self.sess.struct_token_loc(token, self.token), - )); } true } else { @@ -1265,15 +1299,8 @@ impl<'a> Parser<'a> { let generators = self.parse_comp_clauses(); // _DEDENT - if has_newline { - self.skip_newlines(); - if self.token.kind == TokenKind::Dedent { - self.bump(); - } else { - self.sess - .struct_token_error(&[TokenKind::Dedent.into()], self.token) - } - } + self.skip_newlines(); + self.clean_all_indentations(); // RIGHT_BRACE match self.token.kind { @@ -1332,7 +1359,7 @@ impl<'a> Parser<'a> { /// config_entries: config_entry ((COMMA [NEWLINE] | NEWLINE) config_entry)* [COMMA] [NEWLINE] fn parse_config_entries(&mut self, has_newline: bool) -> Vec> { let is_terminator = |token: &kclvm_ast::token::Token| match &token.kind { - TokenKind::CloseDelim(DelimToken::Brace) | TokenKind::Dedent | TokenKind::Eof => true, + TokenKind::CloseDelim(DelimToken::Brace) | TokenKind::Eof => true, TokenKind::Newline if !has_newline => true, _ => token.is_keyword(kw::For), }; @@ -1352,6 +1379,7 @@ impl<'a> Parser<'a> { loop { let marker = self.mark(); + self.clean_all_indentations(); if is_terminator(&self.token) { break; @@ -1511,6 +1539,7 @@ impl<'a> Parser<'a> { /// (ELSE COLON if_entry_exec_block)? fn parse_if_entry_expr(&mut self) -> NodeRef { let mut need_skip_newlines = false; + let token = self.token; let mut if_entry = { self.bump_keyword(kw::If); @@ -1534,6 +1563,7 @@ impl<'a> Parser<'a> { // elif ... let mut need_skip_newlines = false; let mut elif_list = Vec::new(); + let mut last_token = self.token; loop { if !self.token.is_keyword(kw::Elif) { break; @@ -1560,6 +1590,7 @@ impl<'a> Parser<'a> { x, self.sess.struct_token_loc(token, self.prev_token), ))); + last_token = self.prev_token; } if let TokenKind::Newline = self.token.kind { @@ -1589,6 +1620,7 @@ impl<'a> Parser<'a> { Expr::Config(orelse), self.sess.struct_token_loc(token, self.prev_token), )); + last_token = self.prev_token; if_entry.node.orelse = Some(t); } @@ -1605,6 +1637,7 @@ impl<'a> Parser<'a> { x.node.orelse = if_entry.node.orelse; let t = Node { + id: AstIndex::default(), node: Expr::ConfigIfEntry(x.node), filename: x.filename, line: x.line, @@ -1615,13 +1648,10 @@ impl<'a> Parser<'a> { if_entry.node.orelse = Some(Box::new(t)); } - Box::new(Node::new( + + Box::new(Node::node( Expr::ConfigIfEntry(if_entry.node), - if_entry.filename, - if_entry.line, - if_entry.column, - if_entry.end_line, - if_entry.end_column, + self.sess.struct_token_loc(token, last_token), )) } @@ -1640,13 +1670,13 @@ impl<'a> Parser<'a> { ) -> NodeRef { if need_skip_newlines { self.skip_newlines(); - self.bump_token(TokenKind::Indent); + self.bump_token(TokenKind::Indent(VALID_SPACES_LENGTH)); } let token = self.token; - let mut body = { let node = Node { + id: AstIndex::default(), node: Expr::NameConstantLit(NameConstantLit { value: NameConstant::None, // ignore }), @@ -1670,7 +1700,8 @@ impl<'a> Parser<'a> { ) -> bool { let marker = this.mark(); if need_skip_newlines { - if let TokenKind::Dedent = this.token.kind { + if let TokenKind::Dedent(VALID_SPACES_LENGTH) = this.token.kind { + this.bump(); return false; } } else if let TokenKind::Newline = this.token.kind { @@ -1699,8 +1730,8 @@ impl<'a> Parser<'a> { return true; } - - if let TokenKind::Dedent = this.token.kind { + this.validate_dedent(); + if let TokenKind::Dedent(VALID_SPACES_LENGTH) = this.token.kind { return false; } if let TokenKind::Newline = this.token.kind { @@ -1729,8 +1760,8 @@ impl<'a> Parser<'a> { return true; } - - if let TokenKind::Dedent = this.token.kind { + this.validate_dedent(); + if let TokenKind::Dedent(VALID_SPACES_LENGTH) = this.token.kind { return false; } if let TokenKind::Newline = this.token.kind { @@ -1767,8 +1798,16 @@ impl<'a> Parser<'a> { }; let expr1 = this.parse_expr(); - - let pos = expr1.pos(); + let expr0_pos = expr0.clone().unwrap().pos(); + let expr1_pos = expr1.pos(); + + let pos = ( + expr0_pos.0, + expr0_pos.1, + expr0_pos.2, + expr1_pos.3, + expr1_pos.4, + ); body.items.push(node_ref!( ConfigEntry { @@ -1799,8 +1838,6 @@ impl<'a> Parser<'a> { if need_skip_newlines { self.skip_newlines(); - self.bump_token(TokenKind::Dedent); - Box::new(Node::node( body, self.sess.struct_token_loc(token, self.prev_token), @@ -1882,7 +1919,6 @@ impl<'a> Parser<'a> { self.bump_keyword(kw::Lambda); let mut args = None; - let mut return_type_str = None; let mut return_ty = None; // schema_arguments @@ -1898,7 +1934,6 @@ impl<'a> Parser<'a> { if let TokenKind::RArrow = self.token.kind { self.bump_token(TokenKind::RArrow); let typ = self.parse_type_annotation(); - return_type_str = Some(typ.node.to_string()); return_ty = Some(typ); } @@ -1909,22 +1944,18 @@ impl<'a> Parser<'a> { // NEWLINE _INDENT let has_newline = if self.token.kind == TokenKind::Newline { self.skip_newlines(); - - if self.token.kind == TokenKind::Indent { - self.bump(); - } else { - self.sess - .struct_token_error(&[TokenKind::Indent.into()], self.token) - } + self.clean_all_indentations(); true } else { false }; loop { + let marker = self.mark(); + self.clean_all_indentations(); if matches!( self.token.kind, - TokenKind::CloseDelim(DelimToken::Brace) | TokenKind::Dedent | TokenKind::Eof + TokenKind::CloseDelim(DelimToken::Brace) | TokenKind::Eof ) { break; } @@ -1934,16 +1965,13 @@ impl<'a> Parser<'a> { } else { self.bump(); } + + self.drop(marker); } // _DEDENT if has_newline { - if self.token.kind == TokenKind::Dedent { - self.bump(); - } else { - self.sess - .struct_token_error(&[TokenKind::Dedent.into()], self.token) - } + self.clean_all_dedent(); } self.bump_token(TokenKind::CloseDelim(DelimToken::Brace)); @@ -1951,7 +1979,6 @@ impl<'a> Parser<'a> { Box::new(Node::node( Expr::Lambda(LambdaExpr { args, - return_type_str, return_ty, body: stmt_list, }), @@ -2117,18 +2144,27 @@ impl<'a> Parser<'a> { pub(crate) fn parse_identifier(&mut self) -> NodeRef { let token = self.token; - let mut names = Vec::new(); + let mut names: Vec> = Vec::new(); let ident = self.token.ident(); match ident { Some(id) => { - names.push(id.as_str()); + names.push(Node::node( + id.as_str(), + self.sess.struct_token_loc(self.token, self.token), + )); self.bump(); } None => { { self.sess .struct_token_error(&[TokenKind::ident_value()], self.token); - names.push("".to_string()); + names.push(Node::node( + "".to_string(), + ( + self.sess.lookup_char_pos(self.token.span.lo()), + self.sess.lookup_char_pos(self.token.span.lo()), + ), + )); return Box::new(Node::node( Identifier { names, @@ -2152,13 +2188,22 @@ impl<'a> Parser<'a> { let ident = self.token.ident(); match ident { Some(id) => { - names.push(id.as_str().to_string()); + names.push(Node::node( + id.as_str(), + self.sess.struct_token_loc(self.token, self.token), + )); self.bump(); } None => { self.sess .struct_token_error(&[TokenKind::ident_value()], self.token); - names.push("".to_string()) + names.push(Node::node( + "".to_string(), + ( + self.sess.lookup_char_pos(self.token.span.lo()), + self.sess.lookup_char_pos(self.token.span.lo()), + ), + )) } } } diff --git a/kclvm/parser/src/parser/mod.rs b/kclvm/parser/src/parser/mod.rs index 4e24d8f6f..58ae1532c 100644 --- a/kclvm/parser/src/parser/mod.rs +++ b/kclvm/parser/src/parser/mod.rs @@ -107,6 +107,12 @@ impl<'a> Parser<'a> { self.cursor.next().is_some() } + #[inline] + /// Whether the parser has the next token in the token stream. + pub(crate) fn peek_has_next(&mut self) -> bool { + self.cursor.peek().is_some() + } + pub(crate) fn bump_keyword(&mut self, kw: Symbol) { if !self.token.is_keyword(kw) { self.sess.struct_token_error(&[kw.into()], self.token); @@ -189,6 +195,7 @@ impl<'a> Parser<'a> { let filename: String = format!("{}", lo.file.name.prefer_remapped()); let node = kclvm_ast::ast::Node { + id: kclvm_ast::ast::AstIndex::default(), node: Comment { text: x.as_str().to_string(), }, diff --git a/kclvm/parser/src/parser/module.rs b/kclvm/parser/src/parser/module.rs index c8c978aae..ae4295051 100644 --- a/kclvm/parser/src/parser/module.rs +++ b/kclvm/parser/src/parser/module.rs @@ -1,4 +1,5 @@ use kclvm_ast::ast::*; +use kclvm_ast::node_ref; use kclvm_ast::{token::LitKind, token::TokenKind}; use super::Parser; @@ -19,7 +20,7 @@ impl<'a> Parser<'a> { } } - pub(crate) fn parse_doc(&mut self) -> String { + pub(crate) fn parse_doc(&mut self) -> Option> { // doc string match self.token.kind { TokenKind::Literal(lit) => { @@ -27,15 +28,19 @@ impl<'a> Parser<'a> { let doc_expr = self.parse_str_expr(lit); self.skip_newlines(); match &doc_expr.node { - Expr::StringLit(str) => str.raw_value.clone(), - Expr::JoinedString(str) => str.raw_value.clone(), - _ => "".to_string(), + Expr::StringLit(str) => { + Some(node_ref!(str.raw_value.clone(), doc_expr.pos())) + } + Expr::JoinedString(str) => { + Some(node_ref!(str.raw_value.clone(), doc_expr.pos())) + } + _ => None, } } else { - "".to_string() + None } } - _ => "".to_string(), + _ => None, } } diff --git a/kclvm/parser/src/parser/stmt.rs b/kclvm/parser/src/parser/stmt.rs index 2c2b56fd3..2f6558ae9 100644 --- a/kclvm/parser/src/parser/stmt.rs +++ b/kclvm/parser/src/parser/stmt.rs @@ -2,7 +2,8 @@ #![allow(unused_macros)] use compiler_base_span::{span::new_byte_pos, BytePos, Span}; -use kclvm_ast::token::{DelimToken, LitKind, Token, TokenKind}; +use kclvm_ast::token::VALID_SPACES_LENGTH; +use kclvm_ast::token::{CommentKind, DelimToken, LitKind, Token, TokenKind}; use kclvm_ast::{ast::*, expr_as, node_ref}; use kclvm_span::symbol::kw; @@ -38,8 +39,10 @@ impl<'a> Parser<'a> { return Some(stmt); } - self.sess - .struct_span_error("expected statement", self.token.span); + self.sess.struct_span_error( + &format!("unexpected '{:?}'", self.token.kind), + self.token.span, + ); None } @@ -134,9 +137,15 @@ impl<'a> Parser<'a> { close_tok: TokenKind, ) -> Vec> { let mut stmt_list = Vec::new(); - + self.validate_dedent(); self.bump_token(open_tok); loop { + if self.token.kind == TokenKind::Eof { + self.bump(); + break; + } + + self.validate_dedent(); if self.token.kind == close_tok { self.bump_token(close_tok); break; @@ -257,10 +266,9 @@ impl<'a> Parser<'a> { return Some(node_ref!( Stmt::SchemaAttr(SchemaAttr { doc: "".to_string(), - name: node_ref!(target.names.join("."), targets[0].pos()), - type_str: type_annotation.unwrap(), + name: node_ref!(target.get_name(), targets[0].pos()), ty: ty.unwrap(), - op: Some(BinOrAugOp::Aug(aug_op)), + op: Some(aug_op), value: Some(value), is_optional: false, decorators: Vec::new(), @@ -297,12 +305,7 @@ impl<'a> Parser<'a> { self.skip_newlines(); Some(node_ref!( - Stmt::Assign(AssignStmt { - targets, - value, - type_annotation, - ty, - }), + Stmt::Assign(AssignStmt { targets, value, ty }), self.token_span_pos(token, stmt_end_token) )) } else { @@ -312,8 +315,7 @@ impl<'a> Parser<'a> { return Some(node_ref!( Stmt::SchemaAttr(SchemaAttr { doc: "".to_string(), - name: node_ref!(target.names.join("."), targets[0].pos()), - type_str: type_annotation.unwrap(), + name: node_ref!(target.get_names().join("."), targets[0].pos()), ty: ty.unwrap(), op: None, value: None, @@ -340,9 +342,41 @@ impl<'a> Parser<'a> { Some(t) } else { + let miss_expr = self.missing_expr(); + self.skip_newlines(); self.sess .struct_token_error(&[TokenKind::Assign.into()], self.token); - None + if type_annotation.is_some() && !targets.is_empty() && !is_in_schema_stmt { + let mut pos = targets[0].pos(); + pos.3 = targets.last().unwrap().end_line; + pos.4 = targets.last().unwrap().end_column; + + let targets: Vec<_> = targets + .iter() + .map(|expr| match &expr.node { + Expr::Identifier(x) => { + let mut x = x.clone(); + x.ctx = ExprContext::Store; + Box::new(Node::node_with_pos(x, expr.pos())) + } + _ => { + self.sess + .struct_token_error(&[TokenKind::ident_value()], self.token); + Box::new(expr.into_missing_identifier()) + } + }) + .collect(); + Some(Box::new(Node::node_with_pos( + Stmt::Assign(AssignStmt { + targets: targets.clone(), + value: miss_expr, + ty, + }), + pos, + ))) + } else { + None + } } } } @@ -387,6 +421,7 @@ impl<'a> Parser<'a> { fn parse_import_stmt(&mut self) -> NodeRef { let token = self.token; self.bump_keyword(kw::Import); + let dot_name_token = self.token; let mut leading_dot = Vec::new(); while let TokenKind::DotDotDot = self.token.kind { @@ -398,28 +433,41 @@ impl<'a> Parser<'a> { self.bump_token(TokenKind::Dot); } let dot_name = self.parse_identifier().node; + let dot_name_end_token = self.prev_token; + let asname = if self.token.is_keyword(kw::As) { self.bump_keyword(kw::As); let ident = self.parse_identifier().node; - Some(ident.names.join(".")) + match ident.names.len() { + 1 => Some(ident.names[0].clone()), + _ => { + self.sess + .struct_span_error("Invalid import asname", self.token.span); + None + } + } } else { None }; let mut path = leading_dot.join(""); - path.push_str(dot_name.names.join(".").as_str()); + path.push_str(dot_name.get_names().join(".").as_str()); let rawpath = path.clone(); + let path_node = Node::node_with_pos( + path, + self.token_span_pos(dot_name_token, dot_name_end_token), + ); let name = if let Some(as_name_value) = asname.clone() { - as_name_value + as_name_value.node } else { - dot_name.names.last().unwrap().clone() + dot_name.get_names().last().unwrap().clone() }; let t = node_ref!( Stmt::Import(ImportStmt { - path, + path: path_node, rawpath, name, asname, @@ -487,7 +535,10 @@ impl<'a> Parser<'a> { } } else { self.skip_newlines(); - self.parse_block_stmt_list(TokenKind::Indent, TokenKind::Dedent) + self.parse_block_stmt_list( + TokenKind::Indent(VALID_SPACES_LENGTH), + TokenKind::Dedent(VALID_SPACES_LENGTH), + ) }; IfStmt { @@ -521,7 +572,10 @@ impl<'a> Parser<'a> { } } else { self.skip_newlines(); - self.parse_block_stmt_list(TokenKind::Indent, TokenKind::Dedent) + self.parse_block_stmt_list( + TokenKind::Indent(VALID_SPACES_LENGTH), + TokenKind::Dedent(VALID_SPACES_LENGTH), + ) }; let t = node_ref!( @@ -543,7 +597,19 @@ impl<'a> Parser<'a> { // else if self.token.is_keyword(kw::Else) { self.bump_keyword(kw::Else); - self.bump_token(TokenKind::Colon); + + // `else if -> elif` error recovery. + if self.token.is_keyword(kw::If) { + self.sess.struct_span_error( + "'else if' here is invalid in KCL, consider using the 'elif' keyword", + self.token.span, + ); + } else if self.token.kind != TokenKind::Colon { + self.sess + .struct_token_error(&[TokenKind::Colon.into()], self.token); + } + // Bump colon token. + self.bump(); let else_body = if self.token.kind != TokenKind::Newline { if let Some(stmt) = self.parse_expr_or_assign_stmt(false) { @@ -555,7 +621,10 @@ impl<'a> Parser<'a> { } } else { self.skip_newlines(); - self.parse_block_stmt_list(TokenKind::Indent, TokenKind::Dedent) + self.parse_block_stmt_list( + TokenKind::Indent(VALID_SPACES_LENGTH), + TokenKind::Dedent(VALID_SPACES_LENGTH), + ) }; if_stmt.orelse = else_body; @@ -563,8 +632,20 @@ impl<'a> Parser<'a> { // fix elif-list and else while let Some(mut x) = elif_list.pop() { - x.node.orelse = if_stmt.orelse; - let pos = x.clone().pos(); + x.node.orelse = if_stmt.orelse.clone(); + let pos = if if_stmt.orelse.is_empty() { + x.clone().pos() + } else { + let start_pos = x.clone().pos(); + let end_pos = if_stmt.orelse.last().unwrap().pos(); + ( + start_pos.0.clone(), + start_pos.1, + start_pos.2, + end_pos.3, + end_pos.4, + ) + }; let t = Box::new(Node::node_with_pos(Stmt::If(x.node), pos)); if_stmt.orelse = vec![t]; } @@ -612,7 +693,7 @@ impl<'a> Parser<'a> { let name_expr = self.parse_identifier(); let name_pos = name_expr.pos(); let name = name_expr.node; - let name = node_ref!(name.names.join("."), name_pos); + let name = node_ref!(name.get_names().join("."), name_pos); if name .node @@ -665,10 +746,17 @@ impl<'a> Parser<'a> { self.skip_newlines(); - if let TokenKind::Indent = self.token.kind { + if let TokenKind::Indent(VALID_SPACES_LENGTH) = self.token.kind { let body = self.parse_schema_body(); - let pos = self.token_span_pos(token, self.prev_token); + let mut pos = self.token_span_pos(token, self.prev_token); + // Insert a fake newline character to expand the scope of the schema, + // used to complete the schema attributes at the end of the file + // FIXME: fix in lsp + if let TokenKind::Eof = self.prev_token.kind { + pos.3 += 1; + pos.4 = 0; + } node_ref!( Stmt::Schema(SchemaStmt { @@ -691,7 +779,7 @@ impl<'a> Parser<'a> { let pos = self.token_span_pos(token, self.prev_token); node_ref!( Stmt::Schema(SchemaStmt { - doc: "".to_string(), + doc: None, name, parent_name, for_host_name, @@ -770,11 +858,12 @@ impl<'a> Parser<'a> { let mut args = Arguments { args: Vec::new(), defaults: Vec::new(), - type_annotation_list: Vec::new(), ty_list: Vec::new(), }; loop { + let marker = self.mark(); + let mut has_close_token = false; for token in close_tokens { if *token == self.token.kind { @@ -804,14 +893,12 @@ impl<'a> Parser<'a> { let name = node_ref!(name, self.token_span_pos(name_pos, name_end)); - let (type_annotation, type_annotation_node) = if let TokenKind::Colon = self.token.kind - { + let type_annotation_node = if let TokenKind::Colon = self.token.kind { self.bump_token(TokenKind::Colon); let typ = self.parse_type_annotation(); - - (Some(node_ref!(typ.node.to_string(), typ.pos())), Some(typ)) + Some(typ) } else { - (None, None) + None }; let default_value = if let TokenKind::Assign = self.token.kind { @@ -822,13 +909,14 @@ impl<'a> Parser<'a> { }; args.args.push(name); - args.type_annotation_list.push(type_annotation); args.ty_list.push(type_annotation_node); args.defaults.push(default_value); // Parameter interval comma if let TokenKind::Comma = self.token.kind { self.bump(); } + + self.drop(marker); } self.skip_newlines(); @@ -853,10 +941,19 @@ impl<'a> Parser<'a> { /// LEFT_BRACKETS [NAME COLON] [ELLIPSIS] basic_type RIGHT_BRACKETS /// COLON type [ASSIGN test] NEWLINE fn parse_schema_body(&mut self) -> SchemaStmt { - self.bump_token(TokenKind::Indent); + self.validate_dedent(); + self.bump_token(TokenKind::Indent(VALID_SPACES_LENGTH)); - // doc string - let body_doc = self.parse_doc(); + // doc string when it is not a string-like attribute statement. + let body_doc = if let Some(peek) = self.cursor.peek() { + if matches!(peek.kind, TokenKind::Colon) { + None + } else { + self.parse_doc() + } + } else { + self.parse_doc() + }; // mixin let body_mixins = if self.token.is_keyword(kw::Mixin) { @@ -873,8 +970,11 @@ impl<'a> Parser<'a> { loop { let marker = self.mark(); - if matches!(self.token.kind, TokenKind::Dedent | TokenKind::Eof) - || self.token.is_keyword(kw::Check) + self.validate_dedent(); + if matches!( + self.token.kind, + TokenKind::Dedent(VALID_SPACES_LENGTH) | TokenKind::Eof + ) || self.token.is_keyword(kw::Check) { break; } @@ -888,6 +988,20 @@ impl<'a> Parser<'a> { body_body.push(self.parse_if_stmt()); continue; } + // schema_attribute_stmt: string COLON type_annotation + else if self.token.is_string_lit() { + if let Some(peek) = self.cursor.peek() { + if let TokenKind::Colon = peek.kind { + let token = self.token; + let attr = self.parse_schema_attribute(); + body_body.push(node_ref!( + Stmt::SchemaAttr(attr), + self.token_span_pos(token, self.prev_token) + )); + continue; + } + } + } // schema_attribute_stmt else if let TokenKind::At = self.token.kind { let token = self.token; @@ -954,26 +1068,23 @@ impl<'a> Parser<'a> { if let Stmt::Assign(assign) = x.node.clone() { if assign.targets.len() == 1 { let ident = assign.targets[0].clone().node; - if let Some(type_str) = assign.type_annotation { - if !type_str.node.is_empty() { - body_body.push(node_ref!( - Stmt::SchemaAttr(SchemaAttr { - doc: "".to_string(), - name: node_ref!( - ident.names.join("."), - assign.targets[0].pos() - ), - type_str, - ty: assign.ty.unwrap(), - op: Some(BinOrAugOp::Aug(AugOp::Assign)), - value: Some(assign.value), - is_optional: false, - decorators: Vec::new(), - }), - x.pos() - )); - continue; - } + if assign.ty.is_some() { + body_body.push(node_ref!( + Stmt::SchemaAttr(SchemaAttr { + doc: "".to_string(), + name: node_ref!( + ident.get_names().join("."), + assign.targets[0].pos() + ), + ty: assign.ty.unwrap(), + op: Some(AugOp::Assign), + value: Some(assign.value), + is_optional: false, + decorators: Vec::new(), + }), + x.pos() + )); + continue; }; } } @@ -988,8 +1099,8 @@ impl<'a> Parser<'a> { // check_block let body_checks = self.parse_schema_check_block(); - - self.bump_token(TokenKind::Dedent); + self.validate_dedent(); + self.bump_token(TokenKind::Dedent(VALID_SPACES_LENGTH)); self.skip_newlines(); SchemaStmt { @@ -1000,6 +1111,7 @@ impl<'a> Parser<'a> { index_signature: body_index_signature, name: Box::new(Node { + id: AstIndex::default(), node: "".to_string(), filename: "".to_string(), line: 0, @@ -1030,12 +1142,13 @@ impl<'a> Parser<'a> { // NEWLINE _INDENT let has_newline = if self.token.kind == TokenKind::Newline { self.skip_newlines(); - - if self.token.kind == TokenKind::Indent { + if self.token.kind == TokenKind::Indent(VALID_SPACES_LENGTH) { self.bump(); } else { - self.sess - .struct_token_error(&[TokenKind::Indent.into()], self.token) + self.sess.struct_token_error( + &[TokenKind::Indent(VALID_SPACES_LENGTH).into()], + self.token, + ) } true } else { @@ -1043,9 +1156,10 @@ impl<'a> Parser<'a> { }; loop { + self.validate_dedent(); if matches!( self.token.kind, - TokenKind::CloseDelim(DelimToken::Bracket) | TokenKind::Dedent + TokenKind::CloseDelim(DelimToken::Bracket) | TokenKind::Dedent(VALID_SPACES_LENGTH) ) { break; } @@ -1063,11 +1177,14 @@ impl<'a> Parser<'a> { // _DEDENT if has_newline { - if self.token.kind == TokenKind::Dedent { + self.validate_dedent(); + if self.token.kind == TokenKind::Dedent(VALID_SPACES_LENGTH) { self.bump(); } else { - self.sess - .struct_token_error(&[TokenKind::Dedent.into()], self.token) + self.sess.struct_token_error( + &[TokenKind::Dedent(VALID_SPACES_LENGTH).into()], + self.token, + ) } } @@ -1078,7 +1195,7 @@ impl<'a> Parser<'a> { /// Syntax: /// schema_attribute_stmt: attribute_stmt NEWLINE - /// attribute_stmt: [decorators] identifier [QUESTION] COLON type [(ASSIGN|COMP_OR) test] + /// attribute_stmt: [decorators] (identifier | string) [QUESTION] COLON type [(ASSIGN|COMP_OR) test] fn parse_schema_attribute(&mut self) -> SchemaAttr { let doc = "".to_string(); @@ -1091,12 +1208,17 @@ impl<'a> Parser<'a> { Vec::new() }; - let name_expr = self.parse_identifier(); - - let name_pos = name_expr.pos(); - let name = name_expr.node; - let name = node_ref!(name.names.join("."), name_pos); + // Parse schema identifier-like or string-like attributes + let name = if let Some(name) = self.parse_string_attribute() { + name + } else { + let name_expr = self.parse_identifier(); + let name_pos = name_expr.pos(); + let name = name_expr.node; + node_ref!(name.get_names().join("."), name_pos) + }; + // Parse attribute optional annotation `?` let is_optional = if let TokenKind::Question = self.token.kind { self.bump_token(TokenKind::Question); true @@ -1104,17 +1226,18 @@ impl<'a> Parser<'a> { false }; + // Bump the schema attribute annotation token `:` self.bump_token(TokenKind::Colon); - let typ = self.parse_type_annotation(); - let type_str = node_ref!(typ.node.to_string(), typ.pos()); + // Parse the schema attribute type annotation. + let ty = self.parse_type_annotation(); let op = if self.token.kind == TokenKind::Assign { self.bump_token(TokenKind::Assign); - Some(BinOrAugOp::Aug(AugOp::Assign)) + Some(AugOp::Assign) } else if let TokenKind::BinOpEq(x) = self.token.kind { self.bump_token(self.token.kind); - Some(BinOrAugOp::Aug(x.into())) + Some(x.into()) } else { None }; @@ -1128,8 +1251,7 @@ impl<'a> Parser<'a> { SchemaAttr { doc, name, - type_str, - ty: typ, + ty, op, value, is_optional, @@ -1178,27 +1300,19 @@ impl<'a> Parser<'a> { /// LEFT_BRACKETS [NAME COLON] [ELLIPSIS] basic_type RIGHT_BRACKETS /// COLON type [ASSIGN test] NEWLINE fn parse_schema_index_signature(&mut self) -> SchemaIndexSignature { - let (key_name, key_type, any_other) = if matches!(self.token.kind, TokenKind::DotDotDot) { + let (key_name, key_ty, any_other) = if matches!(self.token.kind, TokenKind::DotDotDot) { // bump token `...` self.bump(); - let key_type = { - let typ = self.parse_type_annotation(); - node_ref!(typ.node.to_string(), typ.pos()) - }; - (None, key_type, true) + (None, self.parse_type_annotation(), true) } else { let token = self.token; let expr = self.parse_identifier_expr(); let ident = self.expr_as_identifier(expr.clone(), token); let pos = expr.pos(); - let key_name = ident.names.join("."); + let key_name = ident.get_names().join("."); if let TokenKind::CloseDelim(DelimToken::Bracket) = self.token.kind { - let key_type = { - let typ = node_ref!(Type::Named(ident), pos); - node_ref!(typ.node.to_string(), typ.pos()) - }; - (None, key_type, false) + (None, node_ref!(Type::Named(ident), pos), false) } else { self.bump_token(TokenKind::Colon); let any_other = if let TokenKind::DotDotDot = self.token.kind { @@ -1207,19 +1321,14 @@ impl<'a> Parser<'a> { } else { false }; - let key_type = { - let typ = self.parse_type_annotation(); - node_ref!(typ.node.to_string(), typ.pos()) - }; - (Some(key_name), key_type, any_other) + (Some(key_name), self.parse_type_annotation(), any_other) } }; self.bump_token(TokenKind::CloseDelim(DelimToken::Bracket)); self.bump_token(TokenKind::Colon); - let typ = self.parse_type_annotation(); - let value_type = node_ref!(typ.node.to_string(), typ.pos()); + let value_ty = self.parse_type_annotation(); let value = if let TokenKind::Assign = self.token.kind { self.bump(); @@ -1232,9 +1341,8 @@ impl<'a> Parser<'a> { SchemaIndexSignature { key_name, - key_type, - value_type, - value_ty: typ, + key_ty, + value_ty, value, any_other, } @@ -1250,9 +1358,8 @@ impl<'a> Parser<'a> { self.bump_keyword(kw::Check); self.bump_token(TokenKind::Colon); self.skip_newlines(); - - self.bump_token(TokenKind::Indent); - while self.token.kind != TokenKind::Dedent { + self.bump_token(TokenKind::Indent(VALID_SPACES_LENGTH)); + while self.token.kind != TokenKind::Dedent(VALID_SPACES_LENGTH) { let marker = self.mark(); if matches!(self.token.kind, TokenKind::Eof) { self.sess @@ -1268,7 +1375,8 @@ impl<'a> Parser<'a> { self.skip_newlines(); self.drop(marker); } - self.bump_token(TokenKind::Dedent); + self.validate_dedent(); + self.bump_token(TokenKind::Dedent(VALID_SPACES_LENGTH)); } check_expr_list @@ -1290,7 +1398,7 @@ impl<'a> Parser<'a> { let name_expr = self.parse_identifier_expr(); let name_pos = name_expr.pos(); let name = expr_as!(name_expr, Expr::Identifier).unwrap(); - let name = node_ref!(name.names.join("."), name_pos); + let name = node_ref!(name.get_names().join("."), name_pos); let args = if let TokenKind::OpenDelim(DelimToken::Bracket) = self.token.kind { self.parse_parameters( @@ -1364,8 +1472,7 @@ impl<'a> Parser<'a> { self.bump_token(TokenKind::Colon); self.skip_newlines(); - - self.bump_token(TokenKind::Indent); + self.bump_token(TokenKind::Indent(VALID_SPACES_LENGTH)); // doc string let body_doc = match self.token.kind { @@ -1374,19 +1481,24 @@ impl<'a> Parser<'a> { let doc_expr = self.parse_str_expr(lit); self.skip_newlines(); match &doc_expr.node { - Expr::StringLit(str) => str.raw_value.clone(), - Expr::JoinedString(str) => str.raw_value.clone(), - _ => "".to_string(), + Expr::StringLit(str) => { + Some(node_ref!(str.raw_value.clone(), doc_expr.pos())) + } + Expr::JoinedString(str) => { + Some(node_ref!(str.raw_value.clone(), doc_expr.pos())) + } + _ => None, } } else { - "".to_string() + None } } - _ => "".to_string(), + _ => None, }; let mut check_expr_list = vec![]; - while self.token.kind != TokenKind::Dedent { + self.validate_dedent(); + while self.token.kind != TokenKind::Dedent(VALID_SPACES_LENGTH) { let marker = self.mark(); if matches!(self.token.kind, TokenKind::Eof) { self.sess @@ -1402,7 +1514,8 @@ impl<'a> Parser<'a> { self.skip_newlines(); self.drop(marker); } - self.bump_token(TokenKind::Dedent); + self.validate_dedent(); + self.bump_token(TokenKind::Dedent(VALID_SPACES_LENGTH)); let pos = self.token_span_pos(token, self.prev_token); @@ -1420,6 +1533,23 @@ impl<'a> Parser<'a> { ) } + pub(crate) fn parse_string_attribute(&mut self) -> Option> { + match self.token.kind { + TokenKind::Literal(lit) => { + if let LitKind::Str { .. } = lit.kind { + let str_expr = self.parse_str_expr(lit); + match &str_expr.node { + Expr::StringLit(str) => Some(node_ref!(str.value.clone(), str_expr.pos())), + _ => None, + } + } else { + None + } + } + _ => None, + } + } + pub(crate) fn parse_joined_string( &mut self, s: &StringLit, @@ -1485,9 +1615,8 @@ impl<'a> Parser<'a> { if let TokenKind::Colon = parser.token.kind { // bump the format spec interval token `:`. parser.bump(); - if let TokenKind::DocComment(_) = parser.token.kind { - let format_spec = parser.sess.span_to_snippet(parser.token.span); - formatted_value.format_spec = Some(format_spec); + if let TokenKind::DocComment(CommentKind::Line(symbol)) = parser.token.kind { + formatted_value.format_spec = Some(symbol.as_str()); } else { this.sess.struct_span_error( "invalid joined string spec without #", diff --git a/kclvm/parser/src/parser/tests.rs b/kclvm/parser/src/parser/tests.rs index 23d71d9aa..6315e36b7 100644 --- a/kclvm/parser/src/parser/tests.rs +++ b/kclvm/parser/src/parser/tests.rs @@ -1,1468 +1,9 @@ -use crate::lexer::parse_token_streams; -use crate::parse_file; -use crate::parser::Parser; -use crate::session::ParseSession; -use compiler_base_span::span::new_byte_pos; -use compiler_base_span::{FilePathMapping, SourceMap}; -use expect_test::{expect, Expect}; -use kclvm_span::create_session_globals_then; +use crate::parse_file_force_errors; use regex::Regex; -use std::path::PathBuf; -use std::sync::Arc; - -fn check_parsing_expr(src: &str, expect: Expect) { - let sm = SourceMap::new(FilePathMapping::empty()); - let sf = sm.new_source_file(PathBuf::from("").into(), src.to_string()); - let sess = &ParseSession::with_source_map(Arc::new(sm)); - - match sf.src.as_ref() { - Some(src_from_sf) => { - create_session_globals_then(|| { - let stream = parse_token_streams(sess, src_from_sf.as_str(), new_byte_pos(0)); - let mut parser = Parser::new(sess, stream); - let expr = parser.parse_expr(); - let actual = format!("{expr:?}\n"); - expect.assert_eq(&actual) - }); - } - None => todo!(), - }; -} - -fn check_parsing_file_ast_json(filename: &str, src: &str, expect: Expect) { - let m = crate::parse_file_with_global_session( - Arc::new(ParseSession::default()), - filename, - Some(src.into()), - ) - .unwrap(); - let actual = serde_json::ser::to_string(&m).unwrap(); - let actual = format!("{actual}\n"); - expect.assert_eq(&actual) -} - -fn check_parsing_type(src: &str, expect: Expect) { - let sm = SourceMap::new(FilePathMapping::empty()); - sm.new_source_file(PathBuf::from("").into(), src.to_string()); - let sess = &ParseSession::with_source_map(Arc::new(sm)); - - create_session_globals_then(|| { - let stream = parse_token_streams(sess, src, new_byte_pos(0)); - let mut parser = Parser::new(sess, stream); - let typ = parser.parse_type_annotation(); - let actual = format!("{typ:?}\n"); - expect.assert_eq(&actual) - }); -} - -fn check_type_str(src: &str, expect: Expect) { - let sm = SourceMap::new(FilePathMapping::empty()); - sm.new_source_file(PathBuf::from("").into(), src.to_string()); - let sess = &ParseSession::with_source_map(Arc::new(sm)); - - create_session_globals_then(|| { - let stream = parse_token_streams(sess, src, new_byte_pos(0)); - let mut parser = Parser::new(sess, stream); - let typ = parser.parse_type_annotation(); - let actual = typ.node.to_string(); - expect.assert_eq(&actual) - }); -} - -fn check_parsing_module(filename: &str, src: &str, expect: &str) { - let m = crate::parse_file(filename, Some(src.to_string())).expect(filename); - let actual = format!("{}\n", serde_json::ser::to_string(&m).unwrap()); - assert_eq!(actual.trim(), expect.trim()); -} - -#[test] -fn smoke_test_parsing_expr() { - check_parsing_expr( - "1\n", - expect![[r#" - Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 } - "#]], - ); - check_parsing_expr( - "\"1\"\n", - expect![[r#" - Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"1\"", value: "1" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); -} - -#[test] -fn named_literal_expr() { - check_parsing_expr( - r####"Undefined"####, - expect![[r#" - Node { node: NameConstantLit(NameConstantLit { value: Undefined }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 } - "#]], - ); - check_parsing_expr( - r####"None"####, - expect![[r#" - Node { node: NameConstantLit(NameConstantLit { value: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); - ( - r####"True"####, - expect![[r#" - Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 1, column: 1, end_line: 1, end_column: 1 } - "#]], - ); - check_parsing_expr( - r####"False"####, - expect![[r#" - Node { node: NameConstantLit(NameConstantLit { value: False }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn nonstring_literal_expr() { - check_parsing_expr( - r####"1234"####, - expect![[r#" - Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1234) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ) -} - -#[test] -fn string_literal_expr_0() { - check_parsing_expr( - r####"'1234'"####, - expect![[r#" - Node { node: StringLit(StringLit { is_long_string: false, raw_value: "'1234'", value: "1234" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ) -} - -#[test] -fn string_literal_expr_1() { - check_parsing_expr( - r####""1234""####, - expect![[r#" - Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"1234\"", value: "1234" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ) -} - -#[test] -fn string_literal_expr_2() { - check_parsing_expr( - r####""1234\n""####, - expect![[r#" - Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"1234\\n\"", value: "1234\n" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 8 } - "#]], - ) -} - -#[test] -fn number_bin_suffix_expr() { - check_parsing_expr( - r####"1234Ki"####, - expect![[r#" - Node { node: NumberLit(NumberLit { binary_suffix: Some(Ki), value: Int(1234) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ) -} - -#[test] -fn unary_expr() { - check_parsing_expr( - r####"+1"####, - expect![[r#" - Node { node: Unary(UnaryExpr { op: UAdd, operand: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 2 } - "#]], - ); -} - -#[test] -fn binary_expr_0() { - check_parsing_expr( - r####"1+2+3"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn binary_expr_1() { - check_parsing_expr( - r####"1+2*3-4"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Add), right: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }, op: Bin(Mul), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 2, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, op: Bin(Sub), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(4) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn binary_expr_2() { - check_parsing_expr( - r####"1+2*3/4"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Add), right: Node { node: Binary(BinaryExpr { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }, op: Bin(Mul), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 2, end_line: 1, end_column: 5 }, op: Bin(Div), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(4) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 2, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn binary_expr_3() { - check_parsing_expr( - r####"a or b"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Or), right: Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn binary_expr_4() { - check_parsing_expr( - r####"x == a or b"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [Eq], comparators: [Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 }, op: Bin(Or), right: Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 } - "#]], - ); - check_parsing_expr( - r####"22 > 11 and 111 < 222"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(22) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 2 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(11) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 7 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 21 }, op: Bin(And), right: Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(111) }), filename: "", line: 1, column: 12, end_line: 1, end_column: 15 }, ops: [Lt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(222) }), filename: "", line: 1, column: 18, end_line: 1, end_column: 21 }] }), filename: "", line: 1, column: 12, end_line: 1, end_column: 21 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 21 } - "#]], - ); - check_parsing_expr( - r####"int(e.value) > 1 and i == 0"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Compare(Compare { left: Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["int"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, args: [Node { node: Identifier(Identifier { names: ["e", "value"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 11 }], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 12 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 15, end_line: 1, end_column: 16 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 }, op: Bin(And), right: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["i"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 21, end_line: 1, end_column: 22 }, ops: [Eq], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 26, end_line: 1, end_column: 27 }] }), filename: "", line: 1, column: 21, end_line: 1, end_column: 27 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 } - "#]], - ); - check_parsing_expr( - r####"key in ['key']"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["key"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, ops: [In], comparators: [Node { node: List(ListExpr { elts: [Node { node: StringLit(StringLit { is_long_string: false, raw_value: "'key'", value: "key" }), filename: "", line: 1, column: 8, end_line: 1, end_column: 13 }], ctx: Load }), filename: "", line: 1, column: 7, end_line: 1, end_column: 14 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 } - "#]], - ); - check_parsing_expr( - r####"key not in ['key']"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["key"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, ops: [NotIn], comparators: [Node { node: List(ListExpr { elts: [Node { node: StringLit(StringLit { is_long_string: false, raw_value: "'key'", value: "key" }), filename: "", line: 1, column: 12, end_line: 1, end_column: 17 }], ctx: Load }), filename: "", line: 1, column: 11, end_line: 1, end_column: 18 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 18 } - "#]], - ); - - check_parsing_expr( - r####"1 is 1 and 11 is not 22"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [Is], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 23 }, op: Bin(And), right: Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(11) }), filename: "", line: 1, column: 11, end_line: 1, end_column: 13 }, ops: [IsNot], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(22) }), filename: "", line: 1, column: 21, end_line: 1, end_column: 23 }] }), filename: "", line: 1, column: 11, end_line: 1, end_column: 23 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 23 } - "#]], - ); -} - -#[test] -fn binary_expr_5() { - check_parsing_expr( - r####"1 + a and b"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Add), right: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, op: Bin(And), right: Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 } - "#]], - ); -} - -#[test] -fn binary_expr_with_paren() { - check_parsing_expr( - r####"1*(2+3)-4"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Mul), right: Node { node: Paren(ParenExpr { expr: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 3, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 2, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 }, op: Bin(Sub), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(4) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 } - "#]], - ); -} - -#[test] -fn logic_expr_0() { - check_parsing_expr( - r####"0 < a < 100"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [Lt, Lt], comparators: [Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(100) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 11 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 } - "#]], - ); - check_parsing_expr( - r####"0 < a < 100 + a"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [Lt, Lt], comparators: [Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(100) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 11 }, op: Bin(Add), right: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 14, end_line: 1, end_column: 15 } }), filename: "", line: 1, column: 8, end_line: 1, end_column: 15 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 15 } - "#]], - ); - check_parsing_expr( - r####"100 > a > 0"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(100) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, ops: [Gt, Gt], comparators: [Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 } - "#]], - ); - check_parsing_expr( - r####"100 + a > a > 0"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(100) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, op: Bin(Add), right: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 }, ops: [Gt, Gt], comparators: [Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 14, end_line: 1, end_column: 15 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 15 } - "#]], - ); -} - -#[test] -fn logic_expr_1() { - check_parsing_expr( - r####"a is b"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [Is], comparators: [Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); - check_parsing_expr( - r####"a is not True"####, - expect![[r#" - Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, ops: [IsNot], comparators: [Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 1, column: 9, end_line: 1, end_column: 13 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 13 } - "#]], - ); - check_parsing_expr( - r####"not False or a > 0 and b is True"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: Unary(UnaryExpr { op: Not, operand: Node { node: NameConstantLit(NameConstantLit { value: False }), filename: "", line: 1, column: 4, end_line: 1, end_column: 9 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 }, op: Bin(Or), right: Node { node: Binary(BinaryExpr { left: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 13, end_line: 1, end_column: 14 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 17, end_line: 1, end_column: 18 }] }), filename: "", line: 1, column: 13, end_line: 1, end_column: 32 }, op: Bin(And), right: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 23, end_line: 1, end_column: 24 }, ops: [Is], comparators: [Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 1, column: 28, end_line: 1, end_column: 32 }] }), filename: "", line: 1, column: 23, end_line: 1, end_column: 32 } }), filename: "", line: 1, column: 13, end_line: 1, end_column: 32 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 32 } - "#]], - ); -} - -#[test] -fn if_expr() { - check_parsing_expr( - r####"1 if true else 2"####, - expect![[r#" - Node { node: If(IfExpr { body: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, cond: Node { node: Identifier(Identifier { names: ["true"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 5, end_line: 1, end_column: 9 }, orelse: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 15, end_line: 1, end_column: 16 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 16 } - "#]], - ); -} - -#[test] -fn primary_expr_0() { - check_parsing_expr( - r####"a.b.c"####, - expect![[r#" - Node { node: Identifier(Identifier { names: ["a", "b", "c"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn primary_expr_1() { - check_parsing_expr( - r####"'{}'.format(1)"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Selector(SelectorExpr { value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "'{}'", value: "{}" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 }, attr: Node { node: Identifier { names: ["format"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 5, end_line: 1, end_column: 11 }, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 12, end_line: 1, end_column: 13 }], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 } - "#]], - ); -} - -#[test] -fn primary_expr_2() { - check_parsing_expr( - r####"str(1).isdigit()"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Selector(SelectorExpr { value: Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["str"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, attr: Node { node: Identifier { names: ["isdigit"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 14 }, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 }, args: [], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 16 } - "#]], - ); -} - -#[test] -fn list_expr() { - check_parsing_expr( - r####"[1, 2, 3]"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 } - "#]], - ); - - check_parsing_expr( - r####"[1, if True: 2, 3]"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, Node { node: ListIfItem(ListIfItemExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 1, column: 7, end_line: 1, end_column: 11 }, exprs: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 13, end_line: 1, end_column: 14 }], orelse: None }), filename: "", line: 1, column: 4, end_line: 1, end_column: 14 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 16, end_line: 1, end_column: 17 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 18 } - "#]], - ); -} - -#[test] -fn list_comp_expr_0() { - check_parsing_expr( - r####"[x ** 2 for x in [1, 2, 3]]"####, - expect![[r#" - Node { node: ListComp(ListComp { elt: Node { node: Binary(BinaryExpr { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, op: Bin(Pow), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 1, end_line: 1, end_column: 7 }, generators: [Node { node: CompClause { targets: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 12, end_line: 1, end_column: 13 }], iter: Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 18, end_line: 1, end_column: 19 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 21, end_line: 1, end_column: 22 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 24, end_line: 1, end_column: 25 }], ctx: Load }), filename: "", line: 1, column: 17, end_line: 1, end_column: 26 }, ifs: [] }, filename: "", line: 1, column: 8, end_line: 1, end_column: 26 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 } - "#]], - ); -} - -#[test] -fn list_comp_expr_1() { - check_parsing_expr( - r####"[i for i in [1, 2, 3] if i > 2]"####, - expect![[r#" - Node { node: ListComp(ListComp { elt: Node { node: Identifier(Identifier { names: ["i"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, generators: [Node { node: CompClause { targets: [Node { node: Identifier { names: ["i"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], iter: Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 13, end_line: 1, end_column: 14 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 16, end_line: 1, end_column: 17 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 19, end_line: 1, end_column: 20 }], ctx: Load }), filename: "", line: 1, column: 12, end_line: 1, end_column: 21 }, ifs: [Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["i"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 25, end_line: 1, end_column: 26 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 29, end_line: 1, end_column: 30 }] }), filename: "", line: 1, column: 25, end_line: 1, end_column: 30 }] }, filename: "", line: 1, column: 3, end_line: 1, end_column: 30 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 31 } - "#]], - ); -} - -#[test] -fn dict_expr() { - check_parsing_expr( - r####"{k0=v0, k1=v1}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k0"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 3 }), value: Node { node: Identifier(Identifier { names: ["v0"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 6 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 1, end_line: 1, end_column: 6 }, Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 8, end_line: 1, end_column: 10 }), value: Node { node: Identifier(Identifier { names: ["v1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 11, end_line: 1, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 8, end_line: 1, end_column: 13 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 } - "#]], - ); -} - -#[test] -fn dict_comp_expr() { - check_parsing_expr( - r####"{k: v + 1 for k, v in {k1 = 1, k2 = 2}}"####, - expect![[r#" - Node { node: DictComp(DictComp { entry: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }), value: Node { node: Binary(BinaryExpr { left: Node { node: Identifier(Identifier { names: ["v"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 } }), filename: "", line: 1, column: 4, end_line: 1, end_column: 9 }, operation: Union, insert_index: -1 }, generators: [Node { node: CompClause { targets: [Node { node: Identifier { names: ["k"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 14, end_line: 1, end_column: 15 }, Node { node: Identifier { names: ["v"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 17, end_line: 1, end_column: 18 }], iter: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 23, end_line: 1, end_column: 25 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 28, end_line: 1, end_column: 29 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 23, end_line: 1, end_column: 29 }, Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k2"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 31, end_line: 1, end_column: 33 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 36, end_line: 1, end_column: 37 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 31, end_line: 1, end_column: 37 }] }), filename: "", line: 1, column: 22, end_line: 1, end_column: 38 }, ifs: [] }, filename: "", line: 1, column: 10, end_line: 1, end_column: 38 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 39 } - "#]], - ); -} - -#[test] -fn subscript_expr_0() { - check_parsing_expr( - r####"a[0]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), lower: None, upper: None, step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); -} - -#[test] -fn subscript_expr_1() { - check_parsing_expr( - r####"b["k"]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["b"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"k\"", value: "k" }), filename: "", line: 1, column: 2, end_line: 1, end_column: 5 }), lower: None, upper: None, step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn subscript_expr_2() { - check_parsing_expr( - r####"c?[1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["c"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }), lower: None, upper: None, step: None, ctx: Load, has_question: true }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn subscript_expr_3() { - check_parsing_expr( - r####"a[1:]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: None, step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn subscript_expr_4() { - check_parsing_expr( - r####"a[:-1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: None, upper: Some(Node { node: Unary(UnaryExpr { op: USub, operand: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 3, end_line: 1, end_column: 5 }), step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn subscript_expr_5() { - check_parsing_expr( - r####"a[1:len]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: Some(Node { node: Identifier(Identifier { names: ["len"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 7 }), step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 8 } - "#]], - ); -} - -#[test] -fn subscript_expr_6() { - check_parsing_expr( - r####"a[0:-1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: Some(Node { node: Unary(UnaryExpr { op: USub, operand: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 4, end_line: 1, end_column: 6 }), step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn subscript_expr_7() { - check_parsing_expr( - r####"a[::]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: None, upper: None, step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn subscript_expr_8() { - check_parsing_expr( - r####"a[1::]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: None, step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn subscript_expr_9() { - check_parsing_expr( - r####"a[:0:]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: None, upper: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }), step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn subscript_expr_10() { - check_parsing_expr( - r####"a[::-1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: None, upper: None, step: Some(Node { node: Unary(UnaryExpr { op: USub, operand: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 4, end_line: 1, end_column: 6 }), ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn subscript_expr_11() { - check_parsing_expr( - r####"a[1::2]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: None, step: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }), ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn subscript_expr_12() { - check_parsing_expr( - r####"a[:2:1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: None, upper: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }), step: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }), ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn subscript_expr_13() { - check_parsing_expr( - r####"a[1:2:]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }), step: None, ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn subscript_expr_14() { - check_parsing_expr( - r####"a[1:3:1]"####, - expect![[r#" - Node { node: Subscript(Subscript { value: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, index: None, lower: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), upper: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }), step: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }), ctx: Load, has_question: false }), filename: "", line: 1, column: 0, end_line: 1, end_column: 8 } - "#]], - ); -} - -#[test] -fn call_expr_0() { - check_parsing_expr( - r####"func0()"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["func0"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, args: [], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn call_expr_1() { - check_parsing_expr( - r####"func1(1)"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["func1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }], keywords: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 8 } - "#]], - ); -} - -#[test] -fn call_expr_2() { - check_parsing_expr( - r####"func2(x=2)"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["func2"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, args: [], keywords: [Node { node: Keyword { arg: Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }, value: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 }) }, filename: "", line: 1, column: 6, end_line: 1, end_column: 9 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 10 } - "#]], - ); -} - -#[test] -fn call_expr_3() { - check_parsing_expr( - r####"func3(1,x=2)"####, - expect![[r#" - Node { node: Call(CallExpr { func: Node { node: Identifier(Identifier { names: ["func3"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }], keywords: [Node { node: Keyword { arg: Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 8, end_line: 1, end_column: 9 }, value: Some(Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 }) }, filename: "", line: 1, column: 8, end_line: 1, end_column: 11 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 12 } - "#]], - ); -} - -#[test] -fn quant_expr_0() { - check_parsing_expr( - r####"all x in collection {x > 0}"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: Identifier(Identifier { names: ["collection"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 9, end_line: 1, end_column: 19 }, variables: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], op: All, test: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 21, end_line: 1, end_column: 22 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 25, end_line: 1, end_column: 26 }] }), filename: "", line: 1, column: 21, end_line: 1, end_column: 26 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 } - "#]], - ); -} - -#[test] -fn quant_expr_1() { - check_parsing_expr( - r####"any y in collection {y < 0}"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: Identifier(Identifier { names: ["collection"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 9, end_line: 1, end_column: 19 }, variables: [Node { node: Identifier { names: ["y"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], op: Any, test: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["y"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 21, end_line: 1, end_column: 22 }, ops: [Lt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 25, end_line: 1, end_column: 26 }] }), filename: "", line: 1, column: 21, end_line: 1, end_column: 26 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 } - "#]], - ); -} - -#[test] -fn quant_expr_2() { - check_parsing_expr( - r####"map x in collection {x + 1}"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: Identifier(Identifier { names: ["collection"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 9, end_line: 1, end_column: 19 }, variables: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], op: Map, test: Node { node: Binary(BinaryExpr { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 21, end_line: 1, end_column: 22 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 25, end_line: 1, end_column: 26 } }), filename: "", line: 1, column: 21, end_line: 1, end_column: 26 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 27 } - "#]], - ); -} - -#[test] -fn quant_expr_3() { - check_parsing_expr( - r####"filter x in collection {x > 1}"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: Identifier(Identifier { names: ["collection"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 12, end_line: 1, end_column: 22 }, variables: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], op: Filter, test: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 24, end_line: 1, end_column: 25 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 28, end_line: 1, end_column: 29 }] }), filename: "", line: 1, column: 24, end_line: 1, end_column: 29 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 30 } - "#]], - ); -} - -#[test] -fn quant_expr_4() { - check_parsing_expr( - r####"filter x in collection {x > 1}"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: Identifier(Identifier { names: ["collection"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 12, end_line: 1, end_column: 22 }, variables: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], op: Filter, test: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 24, end_line: 1, end_column: 25 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 28, end_line: 1, end_column: 29 }] }), filename: "", line: 1, column: 24, end_line: 1, end_column: 29 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 30 } - "#]], - ); -} - -#[test] -fn quant_expr_5() { - check_parsing_expr( - r####"map i, e in [{k1 = "v1", k2 = "v2"}] { e }"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: List(ListExpr { elts: [Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 14, end_line: 1, end_column: 16 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"v1\"", value: "v1" }), filename: "", line: 1, column: 19, end_line: 1, end_column: 23 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 14, end_line: 1, end_column: 23 }, Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k2"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 25, end_line: 1, end_column: 27 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"v2\"", value: "v2" }), filename: "", line: 1, column: 30, end_line: 1, end_column: 34 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 25, end_line: 1, end_column: 34 }] }), filename: "", line: 1, column: 13, end_line: 1, end_column: 35 }], ctx: Load }), filename: "", line: 1, column: 12, end_line: 1, end_column: 36 }, variables: [Node { node: Identifier { names: ["i"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, Node { node: Identifier { names: ["e"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], op: Map, test: Node { node: Identifier(Identifier { names: ["e"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 39, end_line: 1, end_column: 40 }, if_cond: None, ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 42 } - "#]], - ); -} - -#[test] -fn quant_expr_6() { - check_parsing_expr( - r####"map i, e in [{k1 = "v1", k2 = "v2"}] { e if i > 0 }"####, - expect![[r#" - Node { node: Quant(QuantExpr { target: Node { node: List(ListExpr { elts: [Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k1"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 14, end_line: 1, end_column: 16 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"v1\"", value: "v1" }), filename: "", line: 1, column: 19, end_line: 1, end_column: 23 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 14, end_line: 1, end_column: 23 }, Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k2"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 25, end_line: 1, end_column: 27 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"v2\"", value: "v2" }), filename: "", line: 1, column: 30, end_line: 1, end_column: 34 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 25, end_line: 1, end_column: 34 }] }), filename: "", line: 1, column: 13, end_line: 1, end_column: 35 }], ctx: Load }), filename: "", line: 1, column: 12, end_line: 1, end_column: 36 }, variables: [Node { node: Identifier { names: ["i"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, Node { node: Identifier { names: ["e"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], op: Map, test: Node { node: Identifier(Identifier { names: ["e"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 39, end_line: 1, end_column: 40 }, if_cond: Some(Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["i"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 44, end_line: 1, end_column: 45 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(0) }), filename: "", line: 1, column: 48, end_line: 1, end_column: 49 }] }), filename: "", line: 1, column: 44, end_line: 1, end_column: 49 }), ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 51 } - "#]], - ); -} - -#[test] -fn lambda_expr_0() { - check_parsing_expr( - r####"lambda {}"####, - expect![[r#" - Node { node: Lambda(LambdaExpr { args: None, return_type_str: None, body: [], return_ty: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 } - "#]], - ); -} - -#[test] -fn lambda_expr_1() { - check_parsing_expr( - r####"lambda x {}"####, - expect![[r#" - Node { node: Lambda(LambdaExpr { args: Some(Node { node: Arguments { args: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], defaults: [None], type_annotation_list: [None], ty_list: [None] }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }), return_type_str: None, body: [], return_ty: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 11 } - "#]], - ); -} - -#[test] -fn lambda_expr_2() { - check_parsing_expr( - r####"lambda x: int -> int {x}"####, - expect![[r#" - Node { node: Lambda(LambdaExpr { args: Some(Node { node: Arguments { args: [Node { node: Identifier { names: ["x"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 7, end_line: 1, end_column: 8 }], defaults: [None], type_annotation_list: [Some(Node { node: "int", filename: "", line: 1, column: 10, end_line: 1, end_column: 13 })], ty_list: [Some(Node { node: Basic(Int), filename: "", line: 1, column: 10, end_line: 1, end_column: 13 })] }, filename: "", line: 1, column: 7, end_line: 1, end_column: 13 }), return_type_str: Some("int"), body: [Node { node: Expr(ExprStmt { exprs: [Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 22, end_line: 1, end_column: 23 }] }), filename: "", line: 1, column: 22, end_line: 1, end_column: 23 }], return_ty: Some(Node { node: Basic(Int), filename: "", line: 1, column: 17, end_line: 1, end_column: 20 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 24 } - "#]], - ); -} - -#[test] -fn lambda_expr_3() { - check_parsing_expr( - r####"lambda { - if True: - _a = 1 - else: - _a = 2 - _a -}"####, - expect![[r#" - Node { node: Lambda(LambdaExpr { args: None, return_type_str: None, body: [Node { node: If(IfStmt { body: [Node { node: Assign(AssignStmt { targets: [Node { node: Identifier { names: ["_a"], pkgpath: "", ctx: Store }, filename: "", line: 3, column: 8, end_line: 3, end_column: 10 }], value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 3, column: 13, end_line: 3, end_column: 14 }, type_annotation: None, ty: None }), filename: "", line: 3, column: 8, end_line: 3, end_column: 14 }], cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 2, column: 7, end_line: 2, end_column: 11 }, orelse: [Node { node: Assign(AssignStmt { targets: [Node { node: Identifier { names: ["_a"], pkgpath: "", ctx: Store }, filename: "", line: 5, column: 8, end_line: 5, end_column: 10 }], value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 5, column: 13, end_line: 5, end_column: 14 }, type_annotation: None, ty: None }), filename: "", line: 5, column: 8, end_line: 5, end_column: 14 }] }), filename: "", line: 2, column: 4, end_line: 6, end_column: 4 }, Node { node: Expr(ExprStmt { exprs: [Node { node: Identifier(Identifier { names: ["_a"], pkgpath: "", ctx: Load }), filename: "", line: 6, column: 4, end_line: 6, end_column: 6 }] }), filename: "", line: 6, column: 4, end_line: 6, end_column: 6 }], return_ty: None }), filename: "", line: 1, column: 0, end_line: 7, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_expr_0() { - check_parsing_expr( - r####"{ - "name" = { - "name": "alice" - }, - "gender" = "female" -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 2, column: 4, end_line: 2, end_column: 10 }), value: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 3, column: 8, end_line: 3, end_column: 14 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"alice\"", value: "alice" }), filename: "", line: 3, column: 16, end_line: 3, end_column: 23 }, operation: Union, insert_index: -1 }, filename: "", line: 3, column: 8, end_line: 3, end_column: 23 }] }), filename: "", line: 2, column: 13, end_line: 4, end_column: 5 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 4, end_column: 5 }, Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"gender\"", value: "gender" }), filename: "", line: 5, column: 4, end_line: 5, end_column: 12 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"female\"", value: "female" }), filename: "", line: 5, column: 15, end_line: 5, end_column: 23 }, operation: Override, insert_index: -1 }, filename: "", line: 5, column: 4, end_line: 5, end_column: 23 }] }), filename: "", line: 1, column: 0, end_line: 6, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_expr_1() { - check_parsing_expr( - r####"{ - "name" = { - "name": "alice" - } - "gender" = "female", -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 2, column: 4, end_line: 2, end_column: 10 }), value: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 3, column: 8, end_line: 3, end_column: 14 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"alice\"", value: "alice" }), filename: "", line: 3, column: 16, end_line: 3, end_column: 23 }, operation: Union, insert_index: -1 }, filename: "", line: 3, column: 8, end_line: 3, end_column: 23 }] }), filename: "", line: 2, column: 13, end_line: 4, end_column: 5 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 4, end_column: 5 }, Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"gender\"", value: "gender" }), filename: "", line: 5, column: 4, end_line: 5, end_column: 12 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"female\"", value: "female" }), filename: "", line: 5, column: 15, end_line: 5, end_column: 23 }, operation: Override, insert_index: -1 }, filename: "", line: 5, column: 4, end_line: 5, end_column: 23 }] }), filename: "", line: 1, column: 0, end_line: 6, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_expr_2() { - check_parsing_expr( - r####"{ - "name" = { - "name": "alice", - } - "gender" = "female" -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 2, column: 4, end_line: 2, end_column: 10 }), value: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"name\"", value: "name" }), filename: "", line: 3, column: 8, end_line: 3, end_column: 14 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"alice\"", value: "alice" }), filename: "", line: 3, column: 16, end_line: 3, end_column: 23 }, operation: Union, insert_index: -1 }, filename: "", line: 3, column: 8, end_line: 3, end_column: 23 }] }), filename: "", line: 2, column: 13, end_line: 4, end_column: 5 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 4, end_column: 5 }, Node { node: ConfigEntry { key: Some(Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"gender\"", value: "gender" }), filename: "", line: 5, column: 4, end_line: 5, end_column: 12 }), value: Node { node: StringLit(StringLit { is_long_string: false, raw_value: "\"female\"", value: "female" }), filename: "", line: 5, column: 15, end_line: 5, end_column: 23 }, operation: Override, insert_index: -1 }, filename: "", line: 5, column: 4, end_line: 5, end_column: 23 }] }), filename: "", line: 1, column: 0, end_line: 6, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_if_expr_0() { - check_parsing_expr( - r####"{ - if True: - a = 1 -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: None, value: Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 2, column: 7, end_line: 2, end_column: 11 }, items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 3, column: 8, end_line: 3, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }], orelse: None }), filename: "", line: 3, column: 8, end_line: 4, end_column: 0 }, operation: Union, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 4, end_column: 0 }] }), filename: "", line: 1, column: 0, end_line: 4, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_if_expr_1() { - check_parsing_expr( - r####"{ - if True: - a = 1 - else: - a = 2 -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: None, value: Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 2, column: 7, end_line: 2, end_column: 11 }, items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 3, column: 8, end_line: 3, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }], orelse: Some(Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 5, column: 8, end_line: 5, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 5, column: 12, end_line: 5, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 5, column: 12, end_line: 5, end_column: 13 }] }), filename: "", line: 4, column: 4, end_line: 6, end_column: 0 }) }), filename: "", line: 3, column: 8, end_line: 4, end_column: 4 }, operation: Union, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 6, end_column: 0 }] }), filename: "", line: 1, column: 0, end_line: 6, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_if_expr_2() { - check_parsing_expr( - r####"{ - if True: - a = 1 - elif x > 1: - a = 2 - else: - a = 3 -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: None, value: Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 2, column: 7, end_line: 2, end_column: 11 }, items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 3, column: 8, end_line: 3, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 3, column: 12, end_line: 3, end_column: 13 }], orelse: Some(Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: Compare(Compare { left: Node { node: Identifier(Identifier { names: ["x"], pkgpath: "", ctx: Load }), filename: "", line: 4, column: 9, end_line: 4, end_column: 10 }, ops: [Gt], comparators: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 4, column: 13, end_line: 4, end_column: 14 }] }), filename: "", line: 4, column: 9, end_line: 4, end_column: 14 }, items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 5, column: 8, end_line: 5, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 5, column: 12, end_line: 5, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 5, column: 12, end_line: 5, end_column: 13 }], orelse: Some(Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 7, column: 8, end_line: 7, end_column: 9 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 7, column: 12, end_line: 7, end_column: 13 }, operation: Override, insert_index: -1 }, filename: "", line: 7, column: 12, end_line: 7, end_column: 13 }] }), filename: "", line: 6, column: 4, end_line: 8, end_column: 0 }) }), filename: "", line: 4, column: 4, end_line: 6, end_column: 4 }) }), filename: "", line: 3, column: 8, end_line: 4, end_column: 4 }, operation: Union, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 8, end_column: 0 }] }), filename: "", line: 1, column: 0, end_line: 8, end_column: 1 } - "#]], - ); -} - -#[test] -fn config_if_expr_3() { - check_parsing_expr( - r####"{ - if True: - if False: - a = 1 -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: None, value: Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: True }), filename: "", line: 2, column: 7, end_line: 2, end_column: 11 }, items: [Node { node: ConfigEntry { key: None, value: Node { node: ConfigIfEntry(ConfigIfEntryExpr { if_cond: Node { node: NameConstantLit(NameConstantLit { value: False }), filename: "", line: 3, column: 11, end_line: 3, end_column: 16 }, items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 4, column: 12, end_line: 4, end_column: 13 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 4, column: 16, end_line: 4, end_column: 17 }, operation: Override, insert_index: -1 }, filename: "", line: 4, column: 16, end_line: 4, end_column: 17 }], orelse: None }), filename: "", line: 4, column: 12, end_line: 5, end_column: 0 }, operation: Override, insert_index: -1 }, filename: "", line: 4, column: 12, end_line: 5, end_column: 0 }], orelse: None }), filename: "", line: 3, column: 8, end_line: 5, end_column: 0 }, operation: Union, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 5, end_column: 0 }] }), filename: "", line: 1, column: 0, end_line: 5, end_column: 1 } - "#]], - ); -} - -#[test] -fn schema_expr_0() { - check_parsing_expr( - r####"Schema {}"####, - expect![[r#" - Node { node: Schema(SchemaExpr { name: Node { node: Identifier { names: ["Schema"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, args: [], kwargs: [], config: Node { node: Config(ConfigExpr { items: [] }), filename: "", line: 1, column: 7, end_line: 1, end_column: 9 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 9 } - "#]], - ); -} - -#[test] -fn schema_expr_1() { - check_parsing_expr( - r####"Schema {k=v}"####, - expect![[r#" - Node { node: Schema(SchemaExpr { name: Node { node: Identifier { names: ["Schema"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, args: [], kwargs: [], config: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 }), value: Node { node: Identifier(Identifier { names: ["v"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 10, end_line: 1, end_column: 11 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 8, end_line: 1, end_column: 11 }] }), filename: "", line: 1, column: 7, end_line: 1, end_column: 12 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 12 } - "#]], - ); -} - -#[test] -fn schema_expr_2() { - check_parsing_expr( - r####"Schema () {k=v}"####, - expect![[r#" - Node { node: Schema(SchemaExpr { name: Node { node: Identifier { names: ["Schema"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, args: [], kwargs: [], config: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 11, end_line: 1, end_column: 12 }), value: Node { node: Identifier(Identifier { names: ["v"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 13, end_line: 1, end_column: 14 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 11, end_line: 1, end_column: 14 }] }), filename: "", line: 1, column: 10, end_line: 1, end_column: 15 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 15 } - "#]], - ); -} - -#[test] -fn schema_expr_3() { - check_parsing_expr( - r####"Schema (1, 2) {k=v}"####, - expect![[r#" - Node { node: Schema(SchemaExpr { name: Node { node: Identifier { names: ["Schema"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 11, end_line: 1, end_column: 12 }], kwargs: [], config: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 15, end_line: 1, end_column: 16 }), value: Node { node: Identifier(Identifier { names: ["v"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 17, end_line: 1, end_column: 18 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 15, end_line: 1, end_column: 18 }] }), filename: "", line: 1, column: 14, end_line: 1, end_column: 19 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 19 } - "#]], - ); -} - -#[test] -fn schema_expr_4() { - check_parsing_expr( - r####"Schema (1, 2) { - k=v -}"####, - expect![[r#" - Node { node: Schema(SchemaExpr { name: Node { node: Identifier { names: ["Schema"], pkgpath: "", ctx: Load }, filename: "", line: 1, column: 0, end_line: 1, end_column: 6 }, args: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 11, end_line: 1, end_column: 12 }], kwargs: [], config: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["k"], pkgpath: "", ctx: Load }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }), value: Node { node: Identifier(Identifier { names: ["v"], pkgpath: "", ctx: Load }), filename: "", line: 2, column: 6, end_line: 2, end_column: 7 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 2, end_column: 7 }] }), filename: "", line: 1, column: 14, end_line: 3, end_column: 1 } }), filename: "", line: 1, column: 0, end_line: 3, end_column: 1 } - "#]], - ); -} - -#[test] -fn line_continue() { - check_parsing_expr( - r####"1 + \ -2 -"####, - expect![[r#" - Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 2, column: 0, end_line: 2, end_column: 1 } }), filename: "", line: 1, column: 0, end_line: 2, end_column: 1 } - "#]], - ); -} - -#[test] -fn test_basic_type() { - check_parsing_type( - r####"bool"####, - expect![[r#" - Node { node: Basic(Bool), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); - check_parsing_type( - r####"int"####, - expect![[r#" - Node { node: Basic(Int), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); - check_parsing_type( - r####"float"####, - expect![[r#" - Node { node: Basic(Float), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - check_parsing_type( - r####"str"####, - expect![[r#" - Node { node: Basic(Str), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); -} - -#[test] -fn test_any_type() { - check_parsing_type( - r####"any"####, - expect![[r#" - Node { node: Any, filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); -} - -#[test] -fn test_list_type() { - check_parsing_type( - r####"[]"####, - expect![[r#" - Node { node: List(ListType { inner_type: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 2 } - "#]], - ); - check_parsing_type( - r####"[int]"####, - expect![[r#" - Node { node: List(ListType { inner_type: Some(Node { node: Basic(Int), filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - check_parsing_type( - r####"[any]"####, - expect![[r#" - Node { node: List(ListType { inner_type: Some(Node { node: Any, filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - - check_parsing_type( - r####"[[]]"####, - expect![[r#" - Node { node: List(ListType { inner_type: Some(Node { node: List(ListType { inner_type: None }), filename: "", line: 1, column: 1, end_line: 1, end_column: 3 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); - check_parsing_type( - r####"[[str]]"####, - expect![[r#" - Node { node: List(ListType { inner_type: Some(Node { node: List(ListType { inner_type: Some(Node { node: Basic(Str), filename: "", line: 1, column: 2, end_line: 1, end_column: 5 }) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn test_dict_type() { - check_parsing_type( - r####"{:}"####, - expect![[r#" - Node { node: Dict(DictType { key_type: None, value_type: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); - check_parsing_type( - r####"{str:}"####, - expect![[r#" - Node { node: Dict(DictType { key_type: Some(Node { node: Basic(Str), filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }), value_type: None }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); - check_parsing_type( - r####"{:[]}"####, - expect![[r#" - Node { node: Dict(DictType { key_type: None, value_type: Some(Node { node: List(ListType { inner_type: None }), filename: "", line: 1, column: 2, end_line: 1, end_column: 4 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - check_parsing_type( - r####"{str:{:float}}"####, - expect![[r#" - Node { node: Dict(DictType { key_type: Some(Node { node: Basic(Str), filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }), value_type: Some(Node { node: Dict(DictType { key_type: None, value_type: Some(Node { node: Basic(Float), filename: "", line: 1, column: 7, end_line: 1, end_column: 12 }) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 13 }) }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 } - "#]], - ); -} - -#[test] -fn test_union_type() { - check_parsing_type( - r####"int|str"####, - expect![[r#" - Node { node: Union(UnionType { type_elements: [Node { node: Basic(Int), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, Node { node: Basic(Str), filename: "", line: 1, column: 4, end_line: 1, end_column: 7 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); - check_parsing_type( - r####"int | str | [] | {:}"####, - expect![[r#" - Node { node: Union(UnionType { type_elements: [Node { node: Basic(Int), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 }, Node { node: Basic(Str), filename: "", line: 1, column: 6, end_line: 1, end_column: 9 }, Node { node: List(ListType { inner_type: None }), filename: "", line: 1, column: 12, end_line: 1, end_column: 14 }, Node { node: Dict(DictType { key_type: None, value_type: None }), filename: "", line: 1, column: 17, end_line: 1, end_column: 20 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 20 } - "#]], - ); -} - -#[test] -fn test_named_type() { - check_parsing_type( - r####"Person"####, - expect![[r#" - Node { node: Named(Identifier { names: ["Person"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); - check_parsing_type( - r####"some.pkg.Person"####, - expect![[r#" - Node { node: Named(Identifier { names: ["some", "pkg", "Person"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 15 } - "#]], - ) -} - -#[test] -fn test_literal_type() { - check_parsing_type( - r####"True"####, - expect![[r#" - Node { node: Literal(Bool(true)), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); - check_parsing_type( - r####" False "####, - expect![[r#" - Node { node: Literal(Bool(false)), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 } - "#]], - ); - - check_parsing_type( - r####"123"####, - expect![[r#" - Node { node: Literal(Int(123, None)), filename: "", line: 1, column: 0, end_line: 1, end_column: 3 } - "#]], - ); - - check_parsing_type( - r####"123.0"####, - expect![[r#" - Node { node: Literal(Float(123.0)), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - - check_parsing_type( - r####""abc""####, - expect![[r#" - Node { node: Literal(Str("abc")), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); - check_parsing_type( - r####"''"####, - expect![[r#" - Node { node: Literal(Str("")), filename: "", line: 1, column: 0, end_line: 1, end_column: 2 } - "#]], - ); -} - -#[test] -fn test_type_str() { - check_type_str(r####"int"####, expect![[r#"int"#]]); - check_type_str(r####" int "####, expect![[r#"int"#]]); - - check_type_str( - r####"bool | True | int | str|str"####, - expect![[r#"bool|True|int|str|str"#]], - ); - check_type_str( - r####"[ [{str: float}] | int]"####, - expect![[r#"[[{str:float}]|int]"#]], - ); -} - -#[test] -fn test_parse_schema_stmt() { - check_parsing_file_ast_json( - "hello.k", - r####" -schema TestBool: - [] - [str ]: int - [a: str]: int - [a: ...str]: int - [...str]: int - a: int - b?: str - c: int = 0 - d?: str = "" - - [a] - [a, b, c] - [ - 1 - ] - [ - a - ] - [a for a in [1, 2, 3]] - [ - a for a in [1, 2, 3] - ] - - check: - a > 1, "msg" - name not None, "we fail here" - "####, - expect![[r#" - {"filename":"hello.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Schema":{"doc":"","name":{"node":"TestBool","filename":"hello.k","line":2,"column":7,"end_line":2,"end_column":15},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"Expr":{"exprs":[{"node":{"List":{"elts":[],"ctx":"Load"}},"filename":"hello.k","line":3,"column":4,"end_line":3,"end_column":6}]}},"filename":"hello.k","line":3,"column":4,"end_line":3,"end_column":6},{"node":{"SchemaAttr":{"doc":"","name":{"node":"a","filename":"hello.k","line":8,"column":4,"end_line":8,"end_column":5},"type_str":{"node":"int","filename":"hello.k","line":8,"column":7,"end_line":8,"end_column":10},"op":null,"value":null,"is_optional":false,"decorators":[],"ty":{"node":{"Basic":"Int"},"filename":"hello.k","line":8,"column":7,"end_line":8,"end_column":10}}},"filename":"hello.k","line":8,"column":4,"end_line":8,"end_column":10},{"node":{"SchemaAttr":{"doc":"","name":{"node":"b","filename":"hello.k","line":9,"column":4,"end_line":9,"end_column":5},"type_str":{"node":"str","filename":"hello.k","line":9,"column":8,"end_line":9,"end_column":11},"op":null,"value":null,"is_optional":true,"decorators":[],"ty":{"node":{"Basic":"Str"},"filename":"hello.k","line":9,"column":8,"end_line":9,"end_column":11}}},"filename":"hello.k","line":9,"column":4,"end_line":10,"end_column":0},{"node":{"SchemaAttr":{"doc":"","name":{"node":"c","filename":"hello.k","line":10,"column":4,"end_line":10,"end_column":5},"type_str":{"node":"int","filename":"hello.k","line":10,"column":7,"end_line":10,"end_column":10},"op":{"Aug":"Assign"},"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":0}}},"filename":"hello.k","line":10,"column":13,"end_line":10,"end_column":14},"is_optional":false,"decorators":[],"ty":{"node":{"Basic":"Int"},"filename":"hello.k","line":10,"column":7,"end_line":10,"end_column":10}}},"filename":"hello.k","line":10,"column":4,"end_line":10,"end_column":14},{"node":{"SchemaAttr":{"doc":"","name":{"node":"d","filename":"hello.k","line":11,"column":4,"end_line":11,"end_column":5},"type_str":{"node":"str","filename":"hello.k","line":11,"column":8,"end_line":11,"end_column":11},"op":{"Aug":"Assign"},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"\"","value":""}},"filename":"hello.k","line":11,"column":14,"end_line":11,"end_column":16},"is_optional":true,"decorators":[],"ty":{"node":{"Basic":"Str"},"filename":"hello.k","line":11,"column":8,"end_line":11,"end_column":11}}},"filename":"hello.k","line":11,"column":4,"end_line":13,"end_column":0},{"node":{"Expr":{"exprs":[{"node":{"List":{"elts":[{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":13,"column":5,"end_line":13,"end_column":6}],"ctx":"Load"}},"filename":"hello.k","line":13,"column":4,"end_line":13,"end_column":7}]}},"filename":"hello.k","line":13,"column":4,"end_line":13,"end_column":7},{"node":{"Expr":{"exprs":[{"node":{"List":{"elts":[{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":14,"column":5,"end_line":14,"end_column":6},{"node":{"Identifier":{"names":["b"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":14,"column":8,"end_line":14,"end_column":9},{"node":{"Identifier":{"names":["c"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":14,"column":11,"end_line":14,"end_column":12}],"ctx":"Load"}},"filename":"hello.k","line":14,"column":4,"end_line":14,"end_column":13}]}},"filename":"hello.k","line":14,"column":4,"end_line":14,"end_column":13},{"node":{"Expr":{"exprs":[{"node":{"List":{"elts":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":16,"column":8,"end_line":16,"end_column":9}],"ctx":"Load"}},"filename":"hello.k","line":15,"column":4,"end_line":17,"end_column":5}]}},"filename":"hello.k","line":15,"column":4,"end_line":17,"end_column":5},{"node":{"Expr":{"exprs":[{"node":{"List":{"elts":[{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":19,"column":8,"end_line":19,"end_column":9}],"ctx":"Load"}},"filename":"hello.k","line":18,"column":4,"end_line":20,"end_column":5}]}},"filename":"hello.k","line":18,"column":4,"end_line":20,"end_column":5},{"node":{"Expr":{"exprs":[{"node":{"ListComp":{"elt":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":21,"column":5,"end_line":21,"end_column":6},"generators":[{"node":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Load"},"filename":"hello.k","line":21,"column":11,"end_line":21,"end_column":12}],"iter":{"node":{"List":{"elts":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":21,"column":17,"end_line":21,"end_column":18},{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"hello.k","line":21,"column":20,"end_line":21,"end_column":21},{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":3}}},"filename":"hello.k","line":21,"column":23,"end_line":21,"end_column":24}],"ctx":"Load"}},"filename":"hello.k","line":21,"column":16,"end_line":21,"end_column":25},"ifs":[]},"filename":"hello.k","line":21,"column":7,"end_line":21,"end_column":25}]}},"filename":"hello.k","line":21,"column":4,"end_line":21,"end_column":26}]}},"filename":"hello.k","line":21,"column":4,"end_line":21,"end_column":26},{"node":{"Expr":{"exprs":[{"node":{"ListComp":{"elt":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":23,"column":8,"end_line":23,"end_column":9},"generators":[{"node":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Load"},"filename":"hello.k","line":23,"column":14,"end_line":23,"end_column":15}],"iter":{"node":{"List":{"elts":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":23,"column":20,"end_line":23,"end_column":21},{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"hello.k","line":23,"column":23,"end_line":23,"end_column":24},{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":3}}},"filename":"hello.k","line":23,"column":26,"end_line":23,"end_column":27}],"ctx":"Load"}},"filename":"hello.k","line":23,"column":19,"end_line":23,"end_column":28},"ifs":[]},"filename":"hello.k","line":23,"column":10,"end_line":24,"end_column":0}]}},"filename":"hello.k","line":22,"column":4,"end_line":24,"end_column":5}]}},"filename":"hello.k","line":22,"column":4,"end_line":24,"end_column":5}],"decorators":[],"checks":[{"node":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":27,"column":8,"end_line":27,"end_column":9},"ops":["Gt"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":27,"column":12,"end_line":27,"end_column":13}]}},"filename":"hello.k","line":27,"column":8,"end_line":27,"end_column":13},"if_cond":null,"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"msg\"","value":"msg"}},"filename":"hello.k","line":27,"column":15,"end_line":27,"end_column":20}},"filename":"hello.k","line":27,"column":8,"end_line":27,"end_column":20},{"node":{"test":{"node":{"Identifier":{"names":["name"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":28,"column":8,"end_line":28,"end_column":12},"if_cond":null,"msg":null},"filename":"hello.k","line":28,"column":8,"end_line":28,"end_column":12},{"node":{"test":{"node":{"Unary":{"op":"Not","operand":{"node":{"NameConstantLit":{"value":"None"}},"filename":"hello.k","line":28,"column":17,"end_line":28,"end_column":21}}},"filename":"hello.k","line":28,"column":13,"end_line":28,"end_column":21},"if_cond":null,"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"we fail here\"","value":"we fail here"}},"filename":"hello.k","line":28,"column":23,"end_line":28,"end_column":37}},"filename":"hello.k","line":28,"column":13,"end_line":28,"end_column":37}],"index_signature":{"node":{"key_name":null,"key_type":{"node":"str","filename":"hello.k","line":7,"column":8,"end_line":7,"end_column":11},"value_type":{"node":"int","filename":"hello.k","line":7,"column":14,"end_line":7,"end_column":17},"value":null,"any_other":true,"value_ty":{"node":{"Basic":"Int"},"filename":"hello.k","line":7,"column":14,"end_line":7,"end_column":17}},"filename":"hello.k","line":7,"column":4,"end_line":8,"end_column":0}}},"filename":"hello.k","line":2,"column":0,"end_line":29,"end_column":8}],"comments":[]} - "#]], - ); -} - -#[test] -fn test_parse_joined_string() { - check_parsing_expr( - r####"'${123+200}'"####, - expect![[r#" - Node { node: JoinedString(JoinedString { is_long_string: false, values: [Node { node: FormattedValue(FormattedValue { is_long_string: false, value: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(123) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 6 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(200) }), filename: "", line: 1, column: 7, end_line: 1, end_column: 10 } }), filename: "", line: 1, column: 3, end_line: 1, end_column: 10 }, format_spec: None }), filename: "", line: 1, column: 3, end_line: 1, end_column: 10 }], raw_value: "'${123+200}'" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 12 } - "#]], - ); - check_parsing_expr( - r####"'abc${a+1}cde'"####, - expect![[r#" - Node { node: JoinedString(JoinedString { is_long_string: false, values: [Node { node: StringLit(StringLit { is_long_string: false, raw_value: "abc", value: "abc" }), filename: "", line: 1, column: 1, end_line: 1, end_column: 1 }, Node { node: FormattedValue(FormattedValue { is_long_string: false, value: Node { node: Binary(BinaryExpr { left: Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 6, end_line: 1, end_column: 7 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 1, column: 8, end_line: 1, end_column: 9 } }), filename: "", line: 1, column: 6, end_line: 1, end_column: 9 }, format_spec: None }), filename: "", line: 1, column: 6, end_line: 1, end_column: 9 }, Node { node: StringLit(StringLit { is_long_string: false, raw_value: "cde", value: "cde" }), filename: "", line: 1, column: 1, end_line: 1, end_column: 1 }], raw_value: "'abc${a+1}cde'" }), filename: "", line: 1, column: 0, end_line: 1, end_column: 14 } - "#]], - ); -} - -#[test] -fn test_parse_assign_stmt() { - check_parsing_file_ast_json( - "hello.k", - r####"a=123"####, - expect![[r#" - {"filename":"hello.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":1,"column":0,"end_line":1,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":123}}},"filename":"hello.k","line":1,"column":2,"end_line":1,"end_column":5},"type_annotation":null,"ty":null}},"filename":"hello.k","line":1,"column":0,"end_line":1,"end_column":5}],"comments":[]} - "#]], - ); -} - -#[test] -fn test_parse_if_stmt() { - check_parsing_file_ast_json( - "hello.k", - r####" -a = 10 -b = 12 -_condition = 0 -if a == 11 or b == 13: _condition = 1 -elif a == 10 and b == 12: _condition = 2 -condition = _condition - "####, - expect![[r#" - {"filename":"hello.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":2,"column":0,"end_line":2,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":10}}},"filename":"hello.k","line":2,"column":4,"end_line":2,"end_column":6},"type_annotation":null,"ty":null}},"filename":"hello.k","line":2,"column":0,"end_line":2,"end_column":6},{"node":{"Assign":{"targets":[{"node":{"names":["b"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":3,"column":0,"end_line":3,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":12}}},"filename":"hello.k","line":3,"column":4,"end_line":3,"end_column":6},"type_annotation":null,"ty":null}},"filename":"hello.k","line":3,"column":0,"end_line":3,"end_column":6},{"node":{"Assign":{"targets":[{"node":{"names":["_condition"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":4,"column":0,"end_line":4,"end_column":10}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":0}}},"filename":"hello.k","line":4,"column":13,"end_line":4,"end_column":14},"type_annotation":null,"ty":null}},"filename":"hello.k","line":4,"column":0,"end_line":4,"end_column":14},{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["_condition"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":5,"column":23,"end_line":5,"end_column":33}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":5,"column":36,"end_line":5,"end_column":37},"type_annotation":null,"ty":null}},"filename":"hello.k","line":5,"column":23,"end_line":5,"end_column":37}],"cond":{"node":{"Binary":{"left":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":5,"column":3,"end_line":5,"end_column":4},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":11}}},"filename":"hello.k","line":5,"column":8,"end_line":5,"end_column":10}]}},"filename":"hello.k","line":5,"column":3,"end_line":5,"end_column":21},"op":{"Bin":"Or"},"right":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["b"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":5,"column":14,"end_line":5,"end_column":15},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":13}}},"filename":"hello.k","line":5,"column":19,"end_line":5,"end_column":21}]}},"filename":"hello.k","line":5,"column":14,"end_line":5,"end_column":21}}},"filename":"hello.k","line":5,"column":3,"end_line":5,"end_column":21},"orelse":[{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["_condition"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":6,"column":26,"end_line":6,"end_column":36}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"hello.k","line":6,"column":39,"end_line":6,"end_column":40},"type_annotation":null,"ty":null}},"filename":"hello.k","line":6,"column":26,"end_line":6,"end_column":40}],"cond":{"node":{"Binary":{"left":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":6,"column":5,"end_line":6,"end_column":6},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":10}}},"filename":"hello.k","line":6,"column":10,"end_line":6,"end_column":12}]}},"filename":"hello.k","line":6,"column":5,"end_line":6,"end_column":24},"op":{"Bin":"And"},"right":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["b"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":6,"column":17,"end_line":6,"end_column":18},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":12}}},"filename":"hello.k","line":6,"column":22,"end_line":6,"end_column":24}]}},"filename":"hello.k","line":6,"column":17,"end_line":6,"end_column":24}}},"filename":"hello.k","line":6,"column":5,"end_line":6,"end_column":24},"orelse":[]}},"filename":"hello.k","line":6,"column":0,"end_line":7,"end_column":0}]}},"filename":"hello.k","line":5,"column":0,"end_line":7,"end_column":0},{"node":{"Assign":{"targets":[{"node":{"names":["condition"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":7,"column":0,"end_line":7,"end_column":9}],"value":{"node":{"Identifier":{"names":["_condition"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":7,"column":12,"end_line":7,"end_column":22},"type_annotation":null,"ty":null}},"filename":"hello.k","line":7,"column":0,"end_line":7,"end_column":22}],"comments":[]} - "#]], - ); - - check_parsing_file_ast_json( - "hello.k", - r####" -data2 = { - **{key = "value1"} - if a == 123: if b == 456: key = "value2" -} - "####, - expect![[r#" - {"filename":"hello.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["data2"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":2,"column":0,"end_line":2,"end_column":5}],"value":{"node":{"Config":{"items":[{"node":{"key":null,"value":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["key"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":3,"column":7,"end_line":3,"end_column":10},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"value1\"","value":"value1"}},"filename":"hello.k","line":3,"column":13,"end_line":3,"end_column":21},"operation":"Override","insert_index":-1},"filename":"hello.k","line":3,"column":7,"end_line":3,"end_column":21}]}},"filename":"hello.k","line":3,"column":6,"end_line":3,"end_column":22},"operation":"Union","insert_index":-1},"filename":"hello.k","line":3,"column":4,"end_line":3,"end_column":22},{"node":{"key":null,"value":{"node":{"ConfigIfEntry":{"if_cond":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":4,"column":7,"end_line":4,"end_column":8},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":123}}},"filename":"hello.k","line":4,"column":12,"end_line":4,"end_column":15}]}},"filename":"hello.k","line":4,"column":7,"end_line":4,"end_column":15},"items":[{"node":{"key":null,"value":{"node":{"ConfigIfEntry":{"if_cond":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["b"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":4,"column":20,"end_line":4,"end_column":21},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":456}}},"filename":"hello.k","line":4,"column":25,"end_line":4,"end_column":28}]}},"filename":"hello.k","line":4,"column":20,"end_line":4,"end_column":28},"items":[{"node":{"key":{"node":{"Identifier":{"names":["key"],"pkgpath":"","ctx":"Load"}},"filename":"hello.k","line":4,"column":30,"end_line":4,"end_column":33},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"value2\"","value":"value2"}},"filename":"hello.k","line":4,"column":36,"end_line":4,"end_column":44},"operation":"Override","insert_index":-1},"filename":"hello.k","line":4,"column":36,"end_line":4,"end_column":44}],"orelse":null}},"filename":"hello.k","line":4,"column":30,"end_line":4,"end_column":44},"operation":"Override","insert_index":-1},"filename":"hello.k","line":4,"column":30,"end_line":4,"end_column":44}],"orelse":null}},"filename":"hello.k","line":4,"column":17,"end_line":5,"end_column":0},"operation":"Union","insert_index":-1},"filename":"hello.k","line":4,"column":4,"end_line":5,"end_column":0}]}},"filename":"hello.k","line":2,"column":8,"end_line":5,"end_column":1},"type_annotation":null,"ty":null}},"filename":"hello.k","line":2,"column":0,"end_line":5,"end_column":1}],"comments":[]} - "#]], - ); - - check_parsing_file_ast_json( - "hello.k", - r####" -# comment1 -a = 1 -# comment22 -b = 2 -# comment333 -c = 3 # comment4444 - "####, - expect![[r###" - {"filename":"hello.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":3,"column":0,"end_line":3,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"hello.k","line":3,"column":4,"end_line":3,"end_column":5},"type_annotation":null,"ty":null}},"filename":"hello.k","line":3,"column":0,"end_line":3,"end_column":5},{"node":{"Assign":{"targets":[{"node":{"names":["b"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":5,"column":0,"end_line":5,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"hello.k","line":5,"column":4,"end_line":5,"end_column":5},"type_annotation":null,"ty":null}},"filename":"hello.k","line":5,"column":0,"end_line":5,"end_column":5},{"node":{"Assign":{"targets":[{"node":{"names":["c"],"pkgpath":"","ctx":"Store"},"filename":"hello.k","line":7,"column":0,"end_line":7,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":3}}},"filename":"hello.k","line":7,"column":4,"end_line":7,"end_column":5},"type_annotation":null,"ty":null}},"filename":"hello.k","line":7,"column":0,"end_line":7,"end_column":5}],"comments":[{"node":{"text":"# comment1"},"filename":"hello.k","line":2,"column":0,"end_line":2,"end_column":10},{"node":{"text":"# comment22"},"filename":"hello.k","line":4,"column":0,"end_line":4,"end_column":11},{"node":{"text":"# comment333"},"filename":"hello.k","line":6,"column":0,"end_line":6,"end_column":12},{"node":{"text":"# comment4444"},"filename":"hello.k","line":7,"column":6,"end_line":7,"end_column":19}]} - "###]], - ); -} - -#[test] -fn test_parse_file() { - let filenames = vec![ - "testdata/assert-01.k", - "testdata/assert-02.k", - "testdata/assert-03.k", - "testdata/assert-if-0.k", - "testdata/assert-if-1.k", - "testdata/assert-if-2.k", - "testdata/assign-01.k", - "testdata/config_expr-01.k", - "testdata/config_expr-02.k", - "testdata/config_expr-03.k", - "testdata/config_expr-04.k", - "testdata/import-01.k", - "testdata/if-01.k", - "testdata/if-02.k", - "testdata/if-03.k", - "testdata/type-01.k", - "testdata/hello_win.k", - ]; - for filename in filenames { - let code = std::fs::read_to_string(filename).unwrap(); - let expect = std::fs::read_to_string(filename.to_string() + ".json").unwrap(); - check_parsing_module( - filename.trim_start_matches("testdata/"), - code.as_str(), - expect.as_str(), - ); - } -} - -#[test] -fn expr_with_paren1() { - check_parsing_expr( - r####"(2+3)"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 } }), filename: "", line: 1, column: 1, end_line: 1, end_column: 4 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_paren2() { - check_parsing_expr( - r####"((2+3)"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Paren(ParenExpr { expr: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 2, end_line: 1, end_column: 5 } }), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn expr_with_paren3() { - check_parsing_expr( - r####"(2+3))"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Binary(BinaryExpr { left: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, op: Bin(Add), right: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 } }), filename: "", line: 1, column: 1, end_line: 1, end_column: 4 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_bracket1() { - check_parsing_expr( - r####"[2,3]"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_bracket2() { - check_parsing_expr( - r####"[[2,3]"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn expr_with_bracket3() { - check_parsing_expr( - r####"[2,3]]"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_bracket4() { - check_parsing_expr( - r####"[2,3"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(3) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 4 } - "#]], - ); -} - -#[test] -fn expr_with_bracket5() { - check_parsing_expr( - r####"["####, - expect![[r#" - Node { node: List(ListExpr { elts: [], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 } - "#]], - ); -} - -#[test] -fn expr_with_bracket6() { - check_parsing_expr( - r####"[ - 1 - 2, -] - "####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 3, column: 4, end_line: 3, end_column: 5 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 4, end_column: 1 } - "#]], - ); -} - -#[test] -fn expr_with_bracket7() { - check_parsing_expr( - r####"[ - 1,2, -] - "####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 2, column: 6, end_line: 2, end_column: 7 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 3, end_column: 1 } - "#]], - ); -} - -#[test] -fn expr_with_bracket8() { - check_parsing_expr( - r####"[ - 1,2, - - "####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }, Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 2, column: 6, end_line: 2, end_column: 7 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 4, end_column: 8 } - "#]], - ); -} - -#[test] -fn expr_with_brace1() { - check_parsing_expr( - r####"{a=2}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_brace2() { - check_parsing_expr( - r####"{a=2}}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 3, end_line: 1, end_column: 4 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 1, end_line: 1, end_column: 4 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 5 } - "#]], - ); -} - -#[test] -fn expr_with_delim1() { - check_parsing_expr( - r####"({a=2}"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 2, end_line: 1, end_column: 5 }] }), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn expr_with_delim2() { - check_parsing_expr( - r####"({a=(2}"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), value: Node { node: Paren(ParenExpr { expr: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 } }), filename: "", line: 1, column: 4, end_line: 1, end_column: 7 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 2, end_line: 1, end_column: 7 }] }), filename: "", line: 1, column: 1, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn expr_with_delim3() { - check_parsing_expr( - r####"{a=[2]"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 1, end_line: 1, end_column: 2 }), value: Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }], ctx: Load }), filename: "", line: 1, column: 3, end_line: 1, end_column: 6 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 1, end_line: 1, end_column: 6 }] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn expr_with_delim4() { - check_parsing_expr( - r####"[{a=2}"####, - expect![[r#" - Node { node: List(ListExpr { elts: [Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 4, end_line: 1, end_column: 5 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 2, end_line: 1, end_column: 5 }] }), filename: "", line: 1, column: 1, end_line: 1, end_column: 6 }], ctx: Load }), filename: "", line: 1, column: 0, end_line: 1, end_column: 6 } - "#]], - ); -} - -#[test] -fn expr_with_delim5() { - check_parsing_expr( - r####"({a=[2}"####, - expect![[r#" - Node { node: Paren(ParenExpr { expr: Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 1, column: 2, end_line: 1, end_column: 3 }), value: Node { node: List(ListExpr { elts: [Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(2) }), filename: "", line: 1, column: 5, end_line: 1, end_column: 6 }], ctx: Load }), filename: "", line: 1, column: 4, end_line: 1, end_column: 7 }, operation: Override, insert_index: -1 }, filename: "", line: 1, column: 2, end_line: 1, end_column: 7 }] }), filename: "", line: 1, column: 1, end_line: 1, end_column: 7 } }), filename: "", line: 1, column: 0, end_line: 1, end_column: 7 } - "#]], - ); -} - -#[test] -fn expr_with_delim6() { - check_parsing_expr( - r####"{"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [] }), filename: "", line: 1, column: 0, end_line: 1, end_column: 1 } - "#]], - ); -} - -#[test] -fn expr_with_delim7() { - check_parsing_expr( - r####"{ - a = 1 -}"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 2, column: 8, end_line: 2, end_column: 9 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 2, end_column: 9 }] }), filename: "", line: 1, column: 0, end_line: 3, end_column: 1 } - "#]], - ); -} - -#[test] -fn expr_with_delim8() { - check_parsing_expr( - r####"{ - a = 1 -"####, - expect![[r#" - Node { node: Config(ConfigExpr { items: [Node { node: ConfigEntry { key: Some(Node { node: Identifier(Identifier { names: ["a"], pkgpath: "", ctx: Load }), filename: "", line: 2, column: 4, end_line: 2, end_column: 5 }), value: Node { node: NumberLit(NumberLit { binary_suffix: None, value: Int(1) }), filename: "", line: 2, column: 8, end_line: 2, end_column: 9 }, operation: Override, insert_index: -1 }, filename: "", line: 2, column: 4, end_line: 2, end_column: 9 }] }), filename: "", line: 1, column: 0, end_line: 2, end_column: 10 } - "#]], - ); -} #[test] fn test_parse_file_not_found() { - match parse_file("The file path is invalid", None) { + match parse_file_force_errors("The file path is invalid", None) { Ok(_) => { panic!("unreachable") } @@ -1470,7 +11,7 @@ fn test_parse_file_not_found() { assert!( Regex::new(r"^Failed to load KCL file 'The file path is invalid'. Because.*") .unwrap() - .is_match(&err_msg) + .is_match(&err_msg.to_string()) ); } } diff --git a/kclvm/parser/src/parser/ty.rs b/kclvm/parser/src/parser/ty.rs index 63c4ba8c2..b3bd9882d 100644 --- a/kclvm/parser/src/parser/ty.rs +++ b/kclvm/parser/src/parser/ty.rs @@ -131,9 +131,15 @@ impl<'a> Parser<'a> { let v = lit.symbol.as_str().parse::().unwrap(); if let Some(suffix) = lit.suffix { let x = ast::NumberBinarySuffix::try_from(suffix.as_str().as_str()); - ast::LiteralType::Int(v, Some(x.unwrap())) + ast::LiteralType::Int(ast::IntLiteralType { + value: v, + suffix: Some(x.unwrap()), + }) } else { - ast::LiteralType::Int(v, None) + ast::LiteralType::Int(ast::IntLiteralType { + value: v, + suffix: None, + }) } } token::LitKind::Float => { @@ -219,7 +225,44 @@ impl<'a> Parser<'a> { self.sess.struct_token_loc(token, self.prev_token), )); } + // (type) -> type + else if let TokenKind::OpenDelim(DelimToken::Paren) = self.token.kind { + self.bump_token(TokenKind::OpenDelim(DelimToken::Paren)); + let mut params_type = vec![]; + // Parse all the params type until the params list end ')' + while self.token.kind != TokenKind::CloseDelim(DelimToken::Paren) + && self.peek_has_next() + { + params_type.push(self.parse_type_annotation()); + // All the params type should be separated by ',' + if let TokenKind::Comma = self.token.kind { + self.bump_token(TokenKind::Comma); + } + } + // If there is no params type, set it to None + let params_ty = if params_type.is_empty() { + None + } else { + Some(params_type) + }; + + self.bump_token(TokenKind::CloseDelim(DelimToken::Paren)); + // If there is a return type, parse it + // Return type start with '->' + let ret_ty = if let TokenKind::RArrow = self.token.kind { + self.bump_token(TokenKind::RArrow); + Some(self.parse_type_annotation()) + } else { + None + }; + let t = Type::Function(ast::FunctionType { params_ty, ret_ty }); + + return Box::new(Node::node( + t, + self.sess.struct_token_loc(token, self.prev_token), + )); + } // Expect type tokens self.sess.struct_token_error( &[ @@ -234,9 +277,11 @@ impl<'a> Parser<'a> { TokenKind::literal_value(), TokenKind::OpenDelim(DelimToken::Bracket).into(), TokenKind::OpenDelim(DelimToken::Brace).into(), + TokenKind::CloseDelim(DelimToken::Paren).into(), ], self.token, ); + self.bump(); Box::new(Node::node( Type::Any, self.sess.struct_token_loc(token, self.prev_token), diff --git a/kclvm/parser/src/session/mod.rs b/kclvm/parser/src/session/mod.rs index 859604601..e15ea170d 100644 --- a/kclvm/parser/src/session/mod.rs +++ b/kclvm/parser/src/session/mod.rs @@ -6,6 +6,9 @@ use kclvm_ast::token::Token; use kclvm_error::{Diagnostic, Handler, ParseError}; use kclvm_span::{BytePos, Loc, Span}; use std::{cell::RefCell, sync::Arc}; + +pub type ParseSessionRef = Arc; + /// ParseSession represents the data associated with a parse session such as the /// source map and the error handler. #[derive(Default, Clone)] diff --git a/kclvm/parser/src/testdata/multimods/kcl1/kcl.mod b/kclvm/parser/src/testdata/multimods/kcl1/kcl.mod new file mode 100644 index 000000000..ab572545d --- /dev/null +++ b/kclvm/parser/src/testdata/multimods/kcl1/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl1" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/parser/src/testdata/multimods/kcl1/main.k b/kclvm/parser/src/testdata/multimods/kcl1/main.k new file mode 100644 index 000000000..f44f8ed9f --- /dev/null +++ b/kclvm/parser/src/testdata/multimods/kcl1/main.k @@ -0,0 +1 @@ +The_first_kcl_program_1 = 'Hello World 1!' \ No newline at end of file diff --git a/kclvm/parser/src/testdata/multimods/kcl2/kcl.mod b/kclvm/parser/src/testdata/multimods/kcl2/kcl.mod new file mode 100644 index 000000000..5fb058acd --- /dev/null +++ b/kclvm/parser/src/testdata/multimods/kcl2/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl2" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/parser/src/testdata/multimods/kcl2/main.k b/kclvm/parser/src/testdata/multimods/kcl2/main.k new file mode 100644 index 000000000..ae85392dc --- /dev/null +++ b/kclvm/parser/src/testdata/multimods/kcl2/main.k @@ -0,0 +1 @@ +The_first_kcl_program_2 = 'Hello World 2!' \ No newline at end of file diff --git a/kclvm/parser/src/testdata/pkg_not_found/suggestions.k b/kclvm/parser/src/testdata/pkg_not_found/suggestions.k new file mode 100644 index 000000000..0655110e0 --- /dev/null +++ b/kclvm/parser/src/testdata/pkg_not_found/suggestions.k @@ -0,0 +1,3 @@ +import k9s + +a = k9s.a \ No newline at end of file diff --git a/kclvm/parser/src/testdata/test_k_code_list/main.k b/kclvm/parser/src/testdata/test_k_code_list/main.k new file mode 100644 index 000000000..deeb74230 --- /dev/null +++ b/kclvm/parser/src/testdata/test_k_code_list/main.k @@ -0,0 +1 @@ +test = "test" \ No newline at end of file diff --git a/kclvm/parser/src/testdata/test_k_code_list/main1.k b/kclvm/parser/src/testdata/test_k_code_list/main1.k new file mode 100644 index 000000000..d93edb624 --- /dev/null +++ b/kclvm/parser/src/testdata/test_k_code_list/main1.k @@ -0,0 +1 @@ +test1 = "test1" \ No newline at end of file diff --git a/kclvm/parser/src/tests.rs b/kclvm/parser/src/tests.rs index c31a351a2..5dfb903e0 100644 --- a/kclvm/parser/src/tests.rs +++ b/kclvm/parser/src/tests.rs @@ -10,7 +10,11 @@ use crate::*; use core::any::Any; +mod ast; mod error_recovery; +mod expr; +mod file; +mod types; #[macro_export] macro_rules! parse_expr_snapshot { @@ -32,6 +36,46 @@ macro_rules! parse_module_snapshot { }; } +#[macro_export] +macro_rules! parse_type_snapshot { + ($name:ident, $src:expr) => { + #[test] + fn $name() { + insta::assert_snapshot!($crate::tests::parsing_type_string($src)); + } + }; +} + +#[macro_export] +macro_rules! parse_type_node_snapshot { + ($name:ident, $src:expr) => { + #[test] + fn $name() { + insta::assert_snapshot!($crate::tests::parsing_type_node_string($src)); + } + }; +} + +#[macro_export] +macro_rules! parse_file_ast_json_snapshot { + ($name:ident, $filename:expr, $src:expr) => { + #[test] + fn $name() { + insta::assert_snapshot!($crate::tests::parsing_file_ast_json($filename, $src)); + } + }; +} + +#[macro_export] +macro_rules! parse_file_snapshot { + ($name:ident, $filename:expr) => { + #[test] + fn $name() { + insta::assert_snapshot!($crate::tests::parsing_file_string($filename)); + } + }; +} + pub(crate) fn parsing_expr_string(src: &str) -> String { let sm = SourceMap::new(FilePathMapping::empty()); let sf = sm.new_source_file(PathBuf::from("").into(), src.to_string()); @@ -64,6 +108,50 @@ pub(crate) fn parsing_module_string(src: &str) -> String { } } +pub(crate) fn parsing_type_string(src: &str) -> String { + let sm = SourceMap::new(FilePathMapping::empty()); + sm.new_source_file(PathBuf::from("").into(), src.to_string()); + let sess = &ParseSession::with_source_map(Arc::new(sm)); + + create_session_globals_then(|| { + let stream = parse_token_streams(sess, src, new_byte_pos(0)); + let mut parser = Parser::new(sess, stream); + let typ = parser.parse_type_annotation(); + format!("{typ:#?}\n") + }) +} + +pub(crate) fn parsing_type_node_string(src: &str) -> String { + let sm = SourceMap::new(FilePathMapping::empty()); + sm.new_source_file(PathBuf::from("").into(), src.to_string()); + let sess = &ParseSession::with_source_map(Arc::new(sm)); + + create_session_globals_then(|| { + let stream = parse_token_streams(sess, src, new_byte_pos(0)); + let mut parser = Parser::new(sess, stream); + let typ = parser.parse_type_annotation(); + typ.node.to_string() + }) +} + +pub(crate) fn parsing_file_ast_json(filename: &str, src: &str) -> String { + let m = crate::parse_file_with_global_session( + Arc::new(ParseSession::default()), + filename, + Some(src.into()), + ) + .unwrap(); + serde_json::ser::to_string_pretty(&m).unwrap() +} + +pub(crate) fn parsing_file_string(filename: &str) -> String { + let code = std::fs::read_to_string(filename).unwrap(); + let m = crate::parse_file(filename.trim_start_matches("testdata/"), Some(code)) + .expect(filename) + .module; + serde_json::ser::to_string_pretty(&m).unwrap() +} + pub fn check_result_panic_info(result: Result<(), Box>) { if let Err(e) = result { assert!(e.downcast::().is_ok()); @@ -88,7 +176,6 @@ const PARSE_FILE_INVALID_TEST_CASES: &[&str] = &[ "a: int", // No initial value error "a -", // Invalid binary expression error "a?: int", // Invalid optional annotation error - "a: () = 1", // Type annotation error "if a not is not b: a = 1", // Logic operator error "if True:\n a=1\n b=2", // Indent error with recovery "a[1::::]", // List slice error @@ -102,7 +189,7 @@ const PARSE_FILE_INVALID_TEST_CASES: &[&str] = &[ #[test] pub fn test_parse_file_invalid() { for case in PARSE_FILE_INVALID_TEST_CASES { - let result = parse_file("test.k", Some((&case).to_string())); + let result = parse_file_force_errors("test.k", Some((&case).to_string())); assert!(result.is_err(), "case: {case}, result {result:?}"); } } @@ -154,9 +241,12 @@ fn test_in_order() { ); test_vendor_home(); println!("{:?} PASS", "test_vendor_home"); + test_pkg_not_found_suggestion(); + println!("{:?} PASS", "test_pkg_not_found_suggestion"); } pub fn test_import_vendor() { + let module_cache = KCLModuleCache::default(); let vendor = set_vendor_home(); let sm = SourceMap::new(FilePathMapping::empty()); let sess = Arc::new(ParseSession::with_source_map(Arc::new(sm))); @@ -199,27 +289,38 @@ pub fn test_import_vendor() { .canonicalize() .unwrap(); - test_cases.into_iter().for_each(|(test_case_name, pkgs)| { - let test_case_path = dir.join(test_case_name).display().to_string(); - let m = load_program(sess.clone(), &[&test_case_path], None).unwrap(); - assert_eq!(m.pkgs.len(), pkgs.len()); - m.pkgs.into_iter().for_each(|(name, modules)| { - println!("{:?} - {:?}", test_case_name, name); - assert!(pkgs.contains(&name.as_str())); - for pkg in pkgs.clone() { - if name == pkg { - if name == "__main__" { - assert_eq!(modules.len(), 1); - assert_eq!(modules.get(0).unwrap().filename, test_case_path); - } else { - modules.into_iter().for_each(|module| { - assert!(module.filename.contains(&vendor)); - }); + let test_fn = + |test_case_name: &&str, pkgs: &Vec<&str>, module_cache: Option| { + let test_case_path = dir.join(test_case_name).display().to_string(); + let m = load_program(sess.clone(), &[&test_case_path], None, module_cache) + .unwrap() + .program; + assert_eq!(m.pkgs.len(), pkgs.len()); + m.pkgs.into_iter().for_each(|(name, modules)| { + println!("{:?} - {:?}", test_case_name, name); + assert!(pkgs.contains(&name.as_str())); + for pkg in pkgs.clone() { + if name == pkg { + if name == "__main__" { + assert_eq!(modules.len(), 1); + assert_eq!(modules.get(0).unwrap().filename, test_case_path); + } else { + modules.into_iter().for_each(|module| { + assert!(module.filename.contains(&vendor)); + }); + } + break; } - break; } - } - }); + }); + }; + + test_cases + .iter() + .for_each(|(test_case_name, pkgs)| test_fn(test_case_name, pkgs, None)); + + test_cases.iter().for_each(|(test_case_name, pkgs)| { + test_fn(test_case_name, pkgs, Some(module_cache.clone())) }); } @@ -237,7 +338,9 @@ pub fn test_import_vendor_without_kclmod() { test_cases.into_iter().for_each(|(test_case_name, pkgs)| { let test_case_path = dir.join(test_case_name).display().to_string(); - let m = load_program(sess.clone(), &[&test_case_path], None).unwrap(); + let m = load_program(sess.clone(), &[&test_case_path], None, None) + .unwrap() + .program; assert_eq!(m.pkgs.len(), pkgs.len()); m.pkgs.into_iter().for_each(|(name, modules)| { assert!(pkgs.contains(&name.as_str())); @@ -268,11 +371,37 @@ pub fn test_import_vendor_without_vendor_home() { .canonicalize() .unwrap(); let test_case_path = dir.join("assign.k").display().to_string(); - match load_program(sess.clone(), &[&test_case_path], None) { + match load_program(sess.clone(), &[&test_case_path], None, None) { Ok(_) => { let errors = sess.classification().0; let msgs = [ "pkgpath assign not found in the program", + "try 'kcl mod add assign' to download the package not found", + "find more package on 'https://artifacthub.io'", + "pkgpath assign.assign not found in the program", + ]; + assert_eq!(errors.len(), msgs.len()); + for (diag, m) in errors.iter().zip(msgs.iter()) { + assert_eq!(diag.messages[0].message, m.to_string()); + } + } + Err(_) => { + panic!("Unreachable code.") + } + } + + match load_program( + sess.clone(), + &[&test_case_path], + None, + Some(KCLModuleCache::default()), + ) { + Ok(_) => { + let errors = sess.classification().0; + let msgs = [ + "pkgpath assign not found in the program", + "try 'kcl mod add assign' to download the package not found", + "find more package on 'https://artifacthub.io'", "pkgpath assign.assign not found in the program", ]; assert_eq!(errors.len(), msgs.len()); @@ -296,7 +425,27 @@ fn test_import_vendor_with_same_internal_pkg() { .canonicalize() .unwrap(); let test_case_path = dir.join("same_name.k").display().to_string(); - match load_program(sess.clone(), &[&test_case_path], None) { + match load_program(sess.clone(), &[&test_case_path], None, None) { + Ok(_) => { + let errors = sess.classification().0; + let msgs = [ + "the `same_vendor` is found multiple times in the current package and vendor package" + ]; + assert_eq!(errors.len(), msgs.len()); + for (diag, m) in errors.iter().zip(msgs.iter()) { + assert_eq!(diag.messages[0].message, m.to_string()); + } + } + Err(_) => { + panic!("Unreachable code.") + } + } + match load_program( + sess.clone(), + &[&test_case_path], + None, + Some(KCLModuleCache::default()), + ) { Ok(_) => { let errors = sess.classification().0; let msgs = [ @@ -323,7 +472,28 @@ fn test_import_vendor_without_kclmod_and_same_name() { .canonicalize() .unwrap(); let test_case_path = dir.join("assign.k").display().to_string(); - match load_program(sess.clone(), &[&test_case_path], None) { + match load_program(sess.clone(), &[&test_case_path], None, None) { + Ok(_) => { + let errors = sess.classification().0; + let msgs = [ + "the `assign` is found multiple times in the current package and vendor package", + ]; + assert_eq!(errors.len(), msgs.len()); + for (diag, m) in errors.iter().zip(msgs.iter()) { + assert_eq!(diag.messages[0].message, m.to_string()); + } + } + Err(_) => { + panic!("Unreachable code.") + } + } + + match load_program( + sess.clone(), + &[&test_case_path], + None, + Some(KCLModuleCache::default()), + ) { Ok(_) => { let errors = sess.classification().0; let msgs = [ @@ -344,7 +514,7 @@ fn test_import_vendor_by_external_arguments() { let vendor = set_vendor_home(); let sm = SourceMap::new(FilePathMapping::empty()); let sess = Arc::new(ParseSession::with_source_map(Arc::new(sm))); - + let module_cache = KCLModuleCache::default(); let external_dir = &PathBuf::from(".") .join("testdata") .join("test_vendor") @@ -394,33 +564,176 @@ fn test_import_vendor_by_external_arguments() { .canonicalize() .unwrap(); - test_cases - .into_iter() - .for_each(|(test_case_name, dep_name, pkgs)| { - let mut opts = LoadProgramOptions::default(); - opts.package_maps.insert( - dep_name.to_string(), - external_dir.join(dep_name).display().to_string(), - ); - let test_case_path = dir.join(test_case_name).display().to_string(); - let m = load_program(sess.clone(), &[&test_case_path], None).unwrap(); - - assert_eq!(m.pkgs.len(), pkgs.len()); - m.pkgs.into_iter().for_each(|(name, modules)| { - assert!(pkgs.contains(&name.as_str())); - for pkg in pkgs.clone() { - if name == pkg { - if name == "__main__" { - assert_eq!(modules.len(), 1); - assert_eq!(modules.get(0).unwrap().filename, test_case_path); - } else { - modules.into_iter().for_each(|module| { - assert!(module.filename.contains(&vendor)); - }); - } - break; + let test_fn = |test_case_name: &&str, + dep_name: &&str, + pkgs: &Vec<&str>, + module_cache: Option| { + let mut opts = LoadProgramOptions::default(); + opts.package_maps.insert( + dep_name.to_string(), + external_dir.join(dep_name).display().to_string(), + ); + let test_case_path = dir.join(test_case_name).display().to_string(); + let m = load_program(sess.clone(), &[&test_case_path], None, module_cache) + .unwrap() + .program; + assert_eq!(m.pkgs.len(), pkgs.len()); + m.pkgs.into_iter().for_each(|(name, modules)| { + assert!(pkgs.contains(&name.as_str())); + for pkg in pkgs.clone() { + if name == pkg { + if name == "__main__" { + assert_eq!(modules.len(), 1); + assert_eq!(modules.get(0).unwrap().filename, test_case_path); + } else { + modules.into_iter().for_each(|module| { + assert!(module.filename.contains(&vendor)); + }); } + break; } - }); + } }); + }; + + test_cases + .iter() + .for_each(|(test_case_name, dep_name, pkgs)| test_fn(test_case_name, dep_name, pkgs, None)); + + test_cases + .iter() + .for_each(|(test_case_name, dep_name, pkgs)| { + test_fn(test_case_name, dep_name, pkgs, Some(module_cache.clone())) + }); +} + +#[test] +fn test_get_compile_entries_from_paths() { + let testpath = PathBuf::from("./src/testdata/multimods") + .canonicalize() + .unwrap(); + + // [`kcl1_path`] is a normal path of the package [`kcl1`] root directory. + // It looks like `/xxx/xxx/xxx`. + let kcl1_path = testpath.join("kcl1"); + + // [`kcl2_path`] is a mod relative path of the packege [`kcl2`] root directory. + // It looks like `${kcl2:KCL_MOD}/xxx/xxx` + let kcl2_path = PathBuf::from("${kcl2:KCL_MOD}/main.k"); + + // [`kcl3_path`] is a mod relative path of the [`__main__`] packege. + let kcl3_path = PathBuf::from("${KCL_MOD}/main.k"); + + // [`package_maps`] is a map to show the real path of the mod relative path [`kcl2`]. + let mut opts = LoadProgramOptions::default(); + opts.package_maps.insert( + "kcl2".to_string(), + testpath.join("kcl2").to_str().unwrap().to_string(), + ); + + // [`get_compile_entries_from_paths`] will return the map of package name to package root real path. + let entries = get_compile_entries_from_paths( + &[ + kcl1_path.to_str().unwrap().to_string(), + kcl2_path.display().to_string(), + kcl3_path.display().to_string(), + ], + &opts, + ) + .unwrap(); + + assert_eq!(entries.len(), 3); + + assert_eq!(entries.get_nth_entry(0).unwrap().name(), "__main__"); + assert_eq!( + PathBuf::from(entries.get_nth_entry(0).unwrap().path()) + .canonicalize() + .unwrap() + .display() + .to_string(), + kcl1_path.canonicalize().unwrap().to_str().unwrap() + ); + + assert_eq!(entries.get_nth_entry(1).unwrap().name(), "kcl2"); + assert_eq!( + PathBuf::from(entries.get_nth_entry(1).unwrap().path()) + .canonicalize() + .unwrap() + .display() + .to_string(), + testpath + .join("kcl2") + .canonicalize() + .unwrap() + .to_str() + .unwrap() + ); + + assert_eq!(entries.get_nth_entry(2).unwrap().name(), "__main__"); + assert_eq!( + PathBuf::from(entries.get_nth_entry(2).unwrap().path()) + .canonicalize() + .unwrap() + .to_str() + .unwrap(), + kcl1_path.canonicalize().unwrap().to_str().unwrap() + ); +} + +#[test] +fn test_dir_with_k_code_list() { + let sm = SourceMap::new(FilePathMapping::empty()); + let sess = Arc::new(ParseSession::with_source_map(Arc::new(sm))); + let testpath = PathBuf::from("./src/testdata/test_k_code_list") + .canonicalize() + .unwrap(); + + let mut opts = LoadProgramOptions::default(); + opts.k_code_list = vec!["test_code = 1".to_string()]; + + match load_program( + sess.clone(), + &[&testpath.display().to_string()], + Some(opts.clone()), + None, + ) { + Ok(_) => panic!("unreachable code"), + Err(err) => assert!(err.to_string().contains("Invalid code list")), + } + + match load_program( + sess.clone(), + &[&testpath.display().to_string()], + Some(opts), + Some(KCLModuleCache::default()), + ) { + Ok(_) => panic!("unreachable code"), + Err(err) => assert!(err.to_string().contains("Invalid code list")), + } +} + +pub fn test_pkg_not_found_suggestion() { + let sm = SourceMap::new(FilePathMapping::empty()); + let sess = Arc::new(ParseSession::with_source_map(Arc::new(sm))); + let dir = &PathBuf::from("./src/testdata/pkg_not_found") + .canonicalize() + .unwrap(); + let test_case_path = dir.join("suggestions.k").display().to_string(); + match load_program(sess.clone(), &[&test_case_path], None, None) { + Ok(_) => { + let errors = sess.classification().0; + let msgs = [ + "pkgpath k9s not found in the program", + "try 'kcl mod add k9s' to download the package not found", + "find more package on 'https://artifacthub.io'", + ]; + assert_eq!(errors.len(), msgs.len()); + for (diag, m) in errors.iter().zip(msgs.iter()) { + assert_eq!(diag.messages[0].message, m.to_string()); + } + } + Err(_) => { + panic!("Unreachable code.") + } + } } diff --git a/kclvm/parser/src/tests/ast.rs b/kclvm/parser/src/tests/ast.rs new file mode 100644 index 000000000..337c6b4bd --- /dev/null +++ b/kclvm/parser/src/tests/ast.rs @@ -0,0 +1,70 @@ +use crate::tests::parse_file_ast_json_snapshot; + +parse_file_ast_json_snapshot!( + schema_stmt, + "hello.k", + r####" +schema TestBool: + [] + [str ]: int + [a: str]: int + [a: ...str]: int + [...str]: int + a: int + b?: str + c: int = 0 + d?: str = "" + + [a] + [a, b, c] + [ + 1 + ] + [ + a + ] + [a for a in [1, 2, 3]] + [ + a for a in [1, 2, 3] + ] + + check: + a > 1, "msg" + name not None, "we fail here" + "#### +); +parse_file_ast_json_snapshot!(assign_stmt, "hello.k", r####"a=123"####); +parse_file_ast_json_snapshot!( + if_stmt_0, + "hello.k", + r####" +a = 10 +b = 12 +_condition = 0 +if a == 11 or b == 13: _condition = 1 +elif a == 10 and b == 12: _condition = 2 +condition = _condition + "#### +); +parse_file_ast_json_snapshot!( + if_stmt_1, + "hello.k", + r####" +data2 = { + **{key = "value1"} + if a == 123: if b == 456: key = "value2" +} + "#### +); +parse_file_ast_json_snapshot!( + basic_stmt, + "hello.k", + r####" +# comment1 +a = 1 +# comment22 +b = 2 +# comment333 +c = 3 # comment4444 + "#### +); diff --git a/kclvm/parser/src/tests/error_recovery.rs b/kclvm/parser/src/tests/error_recovery.rs index 5c5632717..b27706e1e 100644 --- a/kclvm/parser/src/tests/error_recovery.rs +++ b/kclvm/parser/src/tests/error_recovery.rs @@ -70,6 +70,7 @@ parse_expr_snapshot! { config_recovery_11, "{if True: a = , b = 2}" } parse_expr_snapshot! { config_recovery_12, "{if True: *a, b = 2}" } parse_expr_snapshot! { config_recovery_13, "{if True: key: {}}" } parse_expr_snapshot! { config_recovery_14, "{if True: key: []}" } +parse_expr_snapshot! { config_recovery_15, "{你好" } parse_expr_snapshot! { comp_clause_recovery_0, "[i for i in [1,2,3]]" } parse_expr_snapshot! { comp_clause_recovery_1, "[i, j for i in [1,2,3]]" } parse_expr_snapshot! { comp_clause_recovery_2, "[for i in [1,2,3]]" } @@ -155,6 +156,14 @@ parse_expr_snapshot! { joined_string_recovery_2, r#"'${(a +}'"# } parse_expr_snapshot! { joined_string_recovery_3, r#"'${a'"# } parse_expr_snapshot! { joined_string_recovery_5, r#"'${a + 1 = }'"# } parse_expr_snapshot! { joined_string_recovery_6, r#"'${a: json}'"# } +parse_expr_snapshot! { joined_string_recovery_7, r#"'\n${a: #json}'"# } +parse_expr_snapshot! { joined_string_recovery_8, r#"'a\nb${a: #json}\n'"# } +parse_expr_snapshot! { lambda_recovery_0, r#"lambda"# } +parse_expr_snapshot! { lambda_recovery_1, r#"lambda {"# } +parse_expr_snapshot! { lambda_recovery_2, r#"lambda {}"# } +parse_expr_snapshot! { lambda_recovery_3, r#"{lambda}"# } +parse_expr_snapshot! { lambda_recovery_4, r#"{lambda{}"# } +parse_expr_snapshot! { lambda_recovery_5, r#"{lambda a{}"# } /* Stmt error recovery */ @@ -194,6 +203,11 @@ parse_module_snapshot! { if_stmt_recovery_3, r#"if True: a = 1 else b = 2"#} parse_module_snapshot! { if_stmt_recovery_4, r#"if True: else: b = 2"#} parse_module_snapshot! { if_stmt_recovery_5, r#"if"#} parse_module_snapshot! { if_stmt_recovery_6, r#"if else"#} +parse_module_snapshot! { if_stmt_recovery_7, r#"if True:"#} +parse_module_snapshot! { if_stmt_recovery_8, r#"if True: a = 1 +else if False: b = 1"#} +parse_module_snapshot! { if_stmt_recovery_9, r#"if True: a = 1 +else False: b = 1"#} parse_module_snapshot! { schema_stmt_recovery_0, r#"schema"#} parse_module_snapshot! { schema_stmt_recovery_1, r#"schema A"#} parse_module_snapshot! { schema_stmt_recovery_2, r#"schema A["#} @@ -264,6 +278,19 @@ parse_module_snapshot! { schema_stmt_recovery_31, r#" schema A: [str]: str [str]: int"#} +parse_module_snapshot! { schema_stmt_recovery_32, r#" +schema A: + "attr": str"#} +parse_module_snapshot! { schema_stmt_recovery_33, r#" +schema A: + """Schema Doc""" + "attr": str"#} +parse_module_snapshot! { schema_stmt_recovery_34, r#" +schema A: + "attr: str"#} +parse_module_snapshot! { schema_stmt_recovery_35, r#" +schema A: + "attr":"#} parse_module_snapshot! { rule_stmt_recovery_0, r#"rule"#} parse_module_snapshot! { rule_stmt_recovery_1, r#"rule A"#} parse_module_snapshot! { rule_stmt_recovery_2, r#"rule A["#} @@ -277,3 +304,28 @@ parse_module_snapshot! { rule_stmt_recovery_7, r#" rule A: @ "#} +parse_module_snapshot! { fn_ty_annotation_recovery_0, r#"a:("#} +parse_module_snapshot! { fn_ty_annotation_recovery_1, r#"a:(i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_2, r#"a:(int"#} +parse_module_snapshot! { fn_ty_annotation_recovery_3, r#"a:i)"#} +parse_module_snapshot! { fn_ty_annotation_recovery_4, r#"a:([i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_5, r#"a:([i:"#} +parse_module_snapshot! { fn_ty_annotation_recovery_6, r#"a:([i]"#} +parse_module_snapshot! { fn_ty_annotation_recovery_7, r#"a:([int]"#} +parse_module_snapshot! { fn_ty_annotation_recovery_8, r#"a:([int"#} +parse_module_snapshot! { fn_ty_annotation_recovery_9, r#"a:({}"#} +parse_module_snapshot! { fn_ty_annotation_recovery_10, r#"a:({"#} +parse_module_snapshot! { fn_ty_annotation_recovery_11, r#"a:({i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_12, r#"a:({i:"#} +parse_module_snapshot! { fn_ty_annotation_recovery_13, r#"a:({i:i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_14, r#"a:({i:int"#} +parse_module_snapshot! { fn_ty_annotation_recovery_15, r#"a:({i:int]"#} +parse_module_snapshot! { fn_ty_annotation_recovery_16, r#"a:({str:int]"#} +parse_module_snapshot! { fn_ty_annotation_recovery_17, r#"a:({str:int}"#} +parse_module_snapshot! { fn_ty_annotation_recovery_18, r#"a:({str:int} ->"#} +parse_module_snapshot! { fn_ty_annotation_recovery_19, r#"a:({str:int}) -> i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_20, r#"a:(str|int) -> i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_21, r#"a:(str|int, int) -> i"#} +parse_module_snapshot! { fn_ty_annotation_recovery_22, r#"a:(str|int, int|"#} +parse_module_snapshot! { fn_ty_annotation_recovery_23, r#"a:(str|int, int|) ->"#} +parse_module_snapshot! { import_recovery_0, r#"import json as j.a"#} diff --git a/kclvm/parser/src/tests/expr.rs b/kclvm/parser/src/tests/expr.rs new file mode 100644 index 000000000..d7b491e5c --- /dev/null +++ b/kclvm/parser/src/tests/expr.rs @@ -0,0 +1,221 @@ +use crate::tests::parse_expr_snapshot; + +parse_expr_snapshot!(smoke_test_parsing_expr_0, "1\n"); +parse_expr_snapshot!(smoke_test_parsing_expr_1, "\"1\"\n"); +parse_expr_snapshot!(named_literal_expr_0, "Undefined"); +parse_expr_snapshot!(named_literal_expr_1, "None"); +parse_expr_snapshot!(named_literal_expr_2, "True"); +parse_expr_snapshot!(named_literal_expr_3, "False"); +parse_expr_snapshot!(nonstring_literal_expr, r####"1234"####); +parse_expr_snapshot!(string_literal_expr_0, r####"'1234'"####); +parse_expr_snapshot!(string_literal_expr_1, r####""1234""####); +parse_expr_snapshot!(string_literal_expr_2, r####""1234\n""####); +parse_expr_snapshot!(number_bin_suffix_expr, r####"1234Ki"####); +parse_expr_snapshot!(unary_expr, r####"+1"####); +parse_expr_snapshot!(binary_expr_0, r####"1+2+3"####); +parse_expr_snapshot!(binary_expr_1, r####"1+2*3-4"####); +parse_expr_snapshot!(binary_expr_2, r####"1+2*3/4"####); +parse_expr_snapshot!(binary_expr_3, r####"a or b"####); +parse_expr_snapshot!(binary_expr_4, r####"x == a or b"####); +parse_expr_snapshot!(binary_expr_5, r####"22 > 11 and 111 < 222"####); +parse_expr_snapshot!(binary_expr_6, r####"int(e.value) > 1 and i == 0"####); +parse_expr_snapshot!(binary_expr_7, r####"key in ['key']"####); +parse_expr_snapshot!(binary_expr_8, r####"key not in ['key']"####); +parse_expr_snapshot!(binary_expr_9, r####"1 is 1 and 11 is not 22"####); +parse_expr_snapshot!(binary_expr_10, r####"1 + a and b"####); +parse_expr_snapshot!(binary_expr_with_paren, r####"1*(2+3)-4"####); +parse_expr_snapshot!(logic_expr_0, r####"0 < a < 100"####); +parse_expr_snapshot!(logic_expr_1, r####"0 < a < 100 + a"####); +parse_expr_snapshot!(logic_expr_2, r####"100 > a > 0"####); +parse_expr_snapshot!(logic_expr_3, r####"100 + a > a > 0"####); +parse_expr_snapshot!(logic_expr_4, r####"a is b"####); +parse_expr_snapshot!(logic_expr_5, r####"a is not True"####); +parse_expr_snapshot!(logic_expr_6, r####"not False or a > 0 and b is True"####); +parse_expr_snapshot!(if_expr, r####"1 if true else 2"####); +parse_expr_snapshot!(primary_expr_0, r####"a.b.c"####); +parse_expr_snapshot!(primary_expr_1, r####"'{}'.format(1)"####); +parse_expr_snapshot!(primary_expr_2, r####"str(1).isdigit()"####); +parse_expr_snapshot!(list_expr_0, r####"[1, 2, 3]"####); +parse_expr_snapshot!(list_expr_1, r####"[1, if True: 2, 3]"####); +parse_expr_snapshot!(list_comp_expr_0, r####"[x ** 2 for x in [1, 2, 3]]"####); +parse_expr_snapshot!(list_comp_expr_1, r####"[i for i in [1, 2, 3] if i > 2]"####); +parse_expr_snapshot!(dict_expr, r####"{k0=v0, k1=v1}"####); +parse_expr_snapshot!( + dict_comp_expr, + r####"{k: v + 1 for k, v in {k1 = 1, k2 = 2}}"#### +); +parse_expr_snapshot!(subscript_expr_0, r####"a[0]"####); +parse_expr_snapshot!(subscript_expr_1, r####"b["k"]"####); +parse_expr_snapshot!(subscript_expr_2, r####"c?[1]"####); +parse_expr_snapshot!(subscript_expr_3, r####"a[1:]"####); +parse_expr_snapshot!(subscript_expr_4, r####"a[:-1]"####); +parse_expr_snapshot!(subscript_expr_5, r####"a[1:len]"####); +parse_expr_snapshot!(subscript_expr_6, r####"a[0:-1]"####); +parse_expr_snapshot!(subscript_expr_7, r####"a[::]"####); +parse_expr_snapshot!(subscript_expr_8, r####"a[1::]"####); +parse_expr_snapshot!(subscript_expr_9, r####"a[:0:]"####); +parse_expr_snapshot!(subscript_expr_10, r####"a[::-1]"####); +parse_expr_snapshot!(subscript_expr_11, r####"a[1::2]"####); +parse_expr_snapshot!(subscript_expr_12, r####"a[:2:1]"####); +parse_expr_snapshot!(subscript_expr_13, r####"a[1:2:]"####); +parse_expr_snapshot!(subscript_expr_14, r####"a[1:3:1]"####); +parse_expr_snapshot!(call_expr_0, r####"func0()"####); +parse_expr_snapshot!(call_expr_1, r####"func1(1)"####); +parse_expr_snapshot!(call_expr_2, r####"func2(x=2)"####); +parse_expr_snapshot!(call_expr_3, r####"func3(1,x=2)"####); +parse_expr_snapshot!(quant_expr_0, r####"all x in collection {x > 0}"####); +parse_expr_snapshot!(quant_expr_1, r####"any y in collection {y < 0}"####); +parse_expr_snapshot!(quant_expr_2, r####"map x in collection {x + 1}"####); +parse_expr_snapshot!(quant_expr_3, r####"filter x in collection {x > 1}"####); +parse_expr_snapshot!(quant_expr_4, r####"filter x in collection {x > 1}"####); +parse_expr_snapshot!( + quant_expr_5, + r####"map i, e in [{k1 = "v1", k2 = "v2"}] { e }"#### +); +parse_expr_snapshot!( + quant_expr_6, + r####"map i, e in [{k1 = "v1", k2 = "v2"}] { e if i > 0 }"#### +); +parse_expr_snapshot!(lambda_expr_0, r####"lambda {}"####); +parse_expr_snapshot!(lambda_expr_1, r####"lambda x {}"####); +parse_expr_snapshot!(lambda_expr_2, r####"lambda x: int -> int {x}"####); +parse_expr_snapshot!( + lambda_expr_3, + r####"lambda { + if True: + _a = 1 + else: + _a = 2 + _a +}"#### +); +parse_expr_snapshot!( + config_expr_0, + r####"{ + "name" = { + "name": "alice" + }, + "gender" = "female" +}"#### +); +parse_expr_snapshot!( + config_expr_1, + r####"{ + "name" = { + "name": "alice" + } + "gender" = "female", +}"#### +); +parse_expr_snapshot!( + config_expr_2, + r####"{ + "name" = { + "name": "alice", + } + "gender" = "female" +}"#### +); +parse_expr_snapshot!( + config_if_expr_0, + r####"{ + if True: + a = 1 +}"#### +); +parse_expr_snapshot!( + config_if_expr_1, + r####"{ + if True: + a = 1 + else: + a = 2 +}"#### +); +parse_expr_snapshot!( + config_if_expr_2, + r####"{ + if True: + a = 1 + elif x > 1: + a = 2 + else: + a = 3 +}"#### +); +parse_expr_snapshot!( + config_if_expr_3, + r####"{ + if True: + if False: + a = 1 +}"#### +); +parse_expr_snapshot!(schema_expr_0, r####"Schema {}"####); +parse_expr_snapshot!(schema_expr_1, r####"Schema {k=v}"####); +parse_expr_snapshot!(schema_expr_2, r####"Schema () {k=v}"####); +parse_expr_snapshot!(schema_expr_3, r####"Schema (1, 2) {k=v}"####); +parse_expr_snapshot!( + schema_expr_4, + r####"Schema (1, 2) { + k=v +}"#### +); +parse_expr_snapshot!( + line_continue, + r####"1 + \ +2 +"#### +); +parse_expr_snapshot!(parse_joined_string_0, r####"'${123+200}'"####); +parse_expr_snapshot!(parse_joined_string_1, r####"'abc${a+1}cde'"####); +parse_expr_snapshot!(expr_with_paren_0, r####"(2+3)"####); +parse_expr_snapshot!(expr_with_paren_1, r####"((2+3)"####); +parse_expr_snapshot!(expr_with_paren_2, r####"(2+3))"####); +parse_expr_snapshot!(expr_with_bracket_0, r####"[2,3]"####); +parse_expr_snapshot!(expr_with_bracket_1, r####"[[2,3]"####); +parse_expr_snapshot!(expr_with_bracket_2, r####"[2,3]]"####); +parse_expr_snapshot!(expr_with_bracket_3, r####"[2,3"####); +parse_expr_snapshot!(expr_with_bracket_4, r####"["####); +parse_expr_snapshot!( + expr_with_bracket_5, + r####"[ + 1 + 2, +] + "#### +); +parse_expr_snapshot!( + expr_with_bracket_6, + r####"[ + 1,2, +] + "#### +); +parse_expr_snapshot!( + expr_with_bracket_7, + r####"[ + 1,2, + + "#### +); +parse_expr_snapshot!(expr_with_brace_0, r####"{a=2}"####); +parse_expr_snapshot!(expr_with_brace_1, r####"{a=2}}"####); +parse_expr_snapshot!(expr_with_delim_0, r####"({a=2}"####); +parse_expr_snapshot!(expr_with_delim_1, r####"({a=(2}"####); +parse_expr_snapshot!(expr_with_delim_2, r####"{a=[2]"####); +parse_expr_snapshot!(expr_with_delim_3, r####"[{a=2}"####); +parse_expr_snapshot!(expr_with_delim_4, r####"({a=[2}"####); +parse_expr_snapshot!(expr_with_delim_5, r####"{"####); +parse_expr_snapshot!( + expr_with_delim_6, + r####"{ + a = 1 +}"#### +); +parse_expr_snapshot!( + expr_with_delim_7, + r####"{ + a = 1 +"#### +); diff --git a/kclvm/parser/src/tests/file.rs b/kclvm/parser/src/tests/file.rs new file mode 100644 index 000000000..83baf2e10 --- /dev/null +++ b/kclvm/parser/src/tests/file.rs @@ -0,0 +1,19 @@ +use crate::tests::parse_file_snapshot; + +parse_file_snapshot!(assert_1, "testdata/assert-01.k"); +parse_file_snapshot!(assert_2, "testdata/assert-02.k"); +parse_file_snapshot!(assert_3, "testdata/assert-03.k"); +parse_file_snapshot!(assert_if_0, "testdata/assert-if-0.k"); +parse_file_snapshot!(assert_if_1, "testdata/assert-if-1.k"); +parse_file_snapshot!(assert_if_2, "testdata/assert-if-2.k"); +parse_file_snapshot!(assign_1, "testdata/assign-01.k"); +parse_file_snapshot!(config_expr_1, "testdata/config_expr-01.k"); +parse_file_snapshot!(config_expr_2, "testdata/config_expr-02.k"); +parse_file_snapshot!(config_expr_3, "testdata/config_expr-03.k"); +parse_file_snapshot!(config_expr_4, "testdata/config_expr-04.k"); +parse_file_snapshot!(import_1, "testdata/import-01.k"); +parse_file_snapshot!(if_1, "testdata/if-01.k"); +parse_file_snapshot!(if_2, "testdata/if-02.k"); +parse_file_snapshot!(if_3, "testdata/if-03.k"); +parse_file_snapshot!(type_1, "testdata/type-01.k"); +parse_file_snapshot!(hello_win, "testdata/hello_win.k"); diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__assign_stmt.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__assign_stmt.snap new file mode 100644 index 000000000..28e67a473 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__assign_stmt.snap @@ -0,0 +1,62 @@ +--- +source: parser/src/tests/ast.rs +expression: "crate::tests::parsing_file_ast_json(\"hello.k\", r####\"a=123\"####)" +--- +{ + "filename": "hello.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 123 + } + }, + "filename": "hello.k", + "line": 1, + "column": 2, + "end_line": 1, + "end_column": 5 + }, + "ty": null + }, + "filename": "hello.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 5 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__basic_stmt.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__basic_stmt.snap new file mode 100644 index 000000000..84642f4ef --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__basic_stmt.snap @@ -0,0 +1,201 @@ +--- +source: parser/src/tests/ast.rs +expression: "crate::tests::parsing_file_ast_json(\"hello.k\",\n r####\"\n# comment1\na = 1\n# comment22\nb = 2\n# comment333\nc = 3 # comment4444\n \"####)" +--- +{ + "filename": "hello.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 5 + }, + "ty": null + }, + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 5 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "hello.k", + "line": 5, + "column": 4, + "end_line": 5, + "end_column": 5 + }, + "ty": null + }, + "filename": "hello.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 5 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "c", + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 3 + } + }, + "filename": "hello.k", + "line": 7, + "column": 4, + "end_line": 7, + "end_column": 5 + }, + "ty": null + }, + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 5 + } + ], + "comments": [ + { + "node": { + "text": "# comment1" + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 10 + }, + { + "node": { + "text": "# comment22" + }, + "filename": "hello.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 11 + }, + { + "node": { + "text": "# comment333" + }, + "filename": "hello.k", + "line": 6, + "column": 0, + "end_line": 6, + "end_column": 12 + }, + { + "node": { + "text": "# comment4444" + }, + "filename": "hello.k", + "line": 7, + "column": 6, + "end_line": 7, + "end_column": 19 + } + ] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_0.snap new file mode 100644 index 000000000..d7cc9954f --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_0.snap @@ -0,0 +1,571 @@ +--- +source: parser/src/tests/ast.rs +expression: "crate::tests::parsing_file_ast_json(\"hello.k\",\n r####\"\na = 10\nb = 12\n_condition = 0\nif a == 11 or b == 13: _condition = 1\nelif a == 10 and b == 12: _condition = 2\ncondition = _condition\n \"####)" +--- +{ + "filename": "hello.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 10 + } + }, + "filename": "hello.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 6 + }, + "ty": null + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 6 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 12 + } + }, + "filename": "hello.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 6 + }, + "ty": null + }, + "filename": "hello.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 6 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_condition", + "filename": "hello.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 10 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 10 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 0 + } + }, + "filename": "hello.k", + "line": 4, + "column": 13, + "end_line": 4, + "end_column": 14 + }, + "ty": null + }, + "filename": "hello.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 14 + }, + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_condition", + "filename": "hello.k", + "line": 5, + "column": 23, + "end_line": 5, + "end_column": 33 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 5, + "column": 23, + "end_line": 5, + "end_column": 33 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 5, + "column": 36, + "end_line": 5, + "end_column": 37 + }, + "ty": null + }, + "filename": "hello.k", + "line": 5, + "column": 23, + "end_line": 5, + "end_column": 37 + } + ], + "cond": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 5, + "column": 3, + "end_line": 5, + "end_column": 4 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 5, + "column": 3, + "end_line": 5, + "end_column": 4 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 11 + } + }, + "filename": "hello.k", + "line": 5, + "column": 8, + "end_line": 5, + "end_column": 10 + } + ] + }, + "filename": "hello.k", + "line": 5, + "column": 3, + "end_line": 5, + "end_column": 21 + }, + "op": "Or", + "right": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 5, + "column": 14, + "end_line": 5, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 5, + "column": 14, + "end_line": 5, + "end_column": 15 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 13 + } + }, + "filename": "hello.k", + "line": 5, + "column": 19, + "end_line": 5, + "end_column": 21 + } + ] + }, + "filename": "hello.k", + "line": 5, + "column": 14, + "end_line": 5, + "end_column": 21 + } + }, + "filename": "hello.k", + "line": 5, + "column": 3, + "end_line": 5, + "end_column": 21 + }, + "orelse": [ + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_condition", + "filename": "hello.k", + "line": 6, + "column": 26, + "end_line": 6, + "end_column": 36 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 6, + "column": 26, + "end_line": 6, + "end_column": 36 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "hello.k", + "line": 6, + "column": 39, + "end_line": 6, + "end_column": 40 + }, + "ty": null + }, + "filename": "hello.k", + "line": 6, + "column": 26, + "end_line": 6, + "end_column": 40 + } + ], + "cond": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 6 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 10 + } + }, + "filename": "hello.k", + "line": 6, + "column": 10, + "end_line": 6, + "end_column": 12 + } + ] + }, + "filename": "hello.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 24 + }, + "op": "And", + "right": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 6, + "column": 17, + "end_line": 6, + "end_column": 18 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 6, + "column": 17, + "end_line": 6, + "end_column": 18 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 12 + } + }, + "filename": "hello.k", + "line": 6, + "column": 22, + "end_line": 6, + "end_column": 24 + } + ] + }, + "filename": "hello.k", + "line": 6, + "column": 17, + "end_line": 6, + "end_column": 24 + } + }, + "filename": "hello.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 24 + }, + "orelse": [] + }, + "filename": "hello.k", + "line": 6, + "column": 0, + "end_line": 7, + "end_column": 0 + } + ] + }, + "filename": "hello.k", + "line": 5, + "column": 0, + "end_line": 7, + "end_column": 0 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "condition", + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 9 + } + ], + "value": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_condition", + "filename": "hello.k", + "line": 7, + "column": 12, + "end_line": 7, + "end_column": 22 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 7, + "column": 12, + "end_line": 7, + "end_column": 22 + }, + "ty": null + }, + "filename": "hello.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 22 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_1.snap new file mode 100644 index 000000000..7f721f719 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__if_stmt_1.snap @@ -0,0 +1,329 @@ +--- +source: parser/src/tests/ast.rs +expression: "crate::tests::parsing_file_ast_json(\"hello.k\",\n r####\"\ndata2 = {\n **{key = \"value1\"}\n if a == 123: if b == 456: key = \"value2\"\n}\n \"####)" +--- +{ + "filename": "hello.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "data2", + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 5 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 5 + } + ], + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": null, + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "key", + "filename": "hello.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 10 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 10 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + }, + "filename": "hello.k", + "line": 3, + "column": 13, + "end_line": 3, + "end_column": 21 + }, + "operation": "Override", + "insert_index": -1 + }, + "filename": "hello.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 21 + } + ] + }, + "filename": "hello.k", + "line": 3, + "column": 6, + "end_line": 3, + "end_column": 22 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "hello.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 22 + }, + { + "node": { + "key": null, + "value": { + "node": { + "type": "ConfigIfEntry", + "if_cond": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 8 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 8 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 123 + } + }, + "filename": "hello.k", + "line": 4, + "column": 12, + "end_line": 4, + "end_column": 15 + } + ] + }, + "filename": "hello.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 15 + }, + "items": [ + { + "node": { + "key": null, + "value": { + "node": { + "type": "ConfigIfEntry", + "if_cond": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 4, + "column": 20, + "end_line": 4, + "end_column": 21 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 4, + "column": 20, + "end_line": 4, + "end_column": 21 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 456 + } + }, + "filename": "hello.k", + "line": 4, + "column": 25, + "end_line": 4, + "end_column": 28 + } + ] + }, + "filename": "hello.k", + "line": 4, + "column": 20, + "end_line": 4, + "end_column": 28 + }, + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "key", + "filename": "hello.k", + "line": 4, + "column": 30, + "end_line": 4, + "end_column": 33 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 4, + "column": 30, + "end_line": 4, + "end_column": 33 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"value2\"", + "value": "value2" + }, + "filename": "hello.k", + "line": 4, + "column": 36, + "end_line": 4, + "end_column": 44 + }, + "operation": "Override", + "insert_index": -1 + }, + "filename": "hello.k", + "line": 4, + "column": 30, + "end_line": 4, + "end_column": 44 + } + ], + "orelse": null + }, + "filename": "hello.k", + "line": 4, + "column": 17, + "end_line": 5, + "end_column": 0 + }, + "operation": "Override", + "insert_index": -1 + }, + "filename": "hello.k", + "line": 4, + "column": 17, + "end_line": 5, + "end_column": 0 + } + ], + "orelse": null + }, + "filename": "hello.k", + "line": 4, + "column": 4, + "end_line": 5, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "hello.k", + "line": 4, + "column": 4, + "end_line": 5, + "end_column": 0 + } + ] + }, + "filename": "hello.k", + "line": 2, + "column": 8, + "end_line": 5, + "end_column": 1 + }, + "ty": null + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 5, + "end_column": 1 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__schema_stmt.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__schema_stmt.snap new file mode 100644 index 000000000..fe180f810 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__ast__schema_stmt.snap @@ -0,0 +1,915 @@ +--- +source: parser/src/tests/ast.rs +expression: "crate::tests::parsing_file_ast_json(\"hello.k\",\n r####\"\nschema TestBool:\n []\n [str ]: int\n [a: str]: int\n [a: ...str]: int\n [...str]: int\n a: int\n b?: str\n c: int = 0\n d?: str = \"\"\n\n [a]\n [a, b, c]\n [\n 1\n ]\n [\n a\n ]\n [a for a in [1, 2, 3]]\n [\n a for a in [1, 2, 3]\n ]\n\n check:\n a > 1, \"msg\"\n name not None, \"we fail here\"\n \"####)" +--- +{ + "filename": "hello.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "TestBool", + "filename": "hello.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 15 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "List", + "elts": [], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 6 + } + ] + }, + "filename": "hello.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 6 + }, + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "a", + "filename": "hello.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 5 + }, + "op": null, + "value": null, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "hello.k", + "line": 8, + "column": 7, + "end_line": 8, + "end_column": 10 + } + }, + "filename": "hello.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 10 + }, + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "b", + "filename": "hello.k", + "line": 9, + "column": 4, + "end_line": 9, + "end_column": 5 + }, + "op": null, + "value": null, + "is_optional": true, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "hello.k", + "line": 9, + "column": 8, + "end_line": 9, + "end_column": 11 + } + }, + "filename": "hello.k", + "line": 9, + "column": 4, + "end_line": 10, + "end_column": 0 + }, + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "c", + "filename": "hello.k", + "line": 10, + "column": 4, + "end_line": 10, + "end_column": 5 + }, + "op": "Assign", + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 0 + } + }, + "filename": "hello.k", + "line": 10, + "column": 13, + "end_line": 10, + "end_column": 14 + }, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "hello.k", + "line": 10, + "column": 7, + "end_line": 10, + "end_column": 10 + } + }, + "filename": "hello.k", + "line": 10, + "column": 4, + "end_line": 10, + "end_column": 14 + }, + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "d", + "filename": "hello.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 5 + }, + "op": "Assign", + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"\"", + "value": "" + }, + "filename": "hello.k", + "line": 11, + "column": 14, + "end_line": 11, + "end_column": 16 + }, + "is_optional": true, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "hello.k", + "line": 11, + "column": 8, + "end_line": 11, + "end_column": 11 + } + }, + "filename": "hello.k", + "line": 11, + "column": 4, + "end_line": 13, + "end_column": 0 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 13, + "column": 5, + "end_line": 13, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 13, + "column": 5, + "end_line": 13, + "end_column": 6 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 13, + "column": 4, + "end_line": 13, + "end_column": 7 + } + ] + }, + "filename": "hello.k", + "line": 13, + "column": 4, + "end_line": 13, + "end_column": 7 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 14, + "column": 5, + "end_line": 14, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 14, + "column": 5, + "end_line": 14, + "end_column": 6 + }, + { + "node": { + "type": "Identifier", + "names": [ + { + "node": "b", + "filename": "hello.k", + "line": 14, + "column": 8, + "end_line": 14, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 14, + "column": 8, + "end_line": 14, + "end_column": 9 + }, + { + "node": { + "type": "Identifier", + "names": [ + { + "node": "c", + "filename": "hello.k", + "line": 14, + "column": 11, + "end_line": 14, + "end_column": 12 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 14, + "column": 11, + "end_line": 14, + "end_column": 12 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 14, + "column": 4, + "end_line": 14, + "end_column": 13 + } + ] + }, + "filename": "hello.k", + "line": 14, + "column": 4, + "end_line": 14, + "end_column": 13 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 16, + "column": 8, + "end_line": 16, + "end_column": 9 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 15, + "column": 4, + "end_line": 17, + "end_column": 5 + } + ] + }, + "filename": "hello.k", + "line": 15, + "column": 4, + "end_line": 17, + "end_column": 5 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 19, + "column": 8, + "end_line": 19, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 19, + "column": 8, + "end_line": 19, + "end_column": 9 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 18, + "column": 4, + "end_line": 20, + "end_column": 5 + } + ] + }, + "filename": "hello.k", + "line": 18, + "column": 4, + "end_line": 20, + "end_column": 5 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "ListComp", + "elt": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 21, + "column": 5, + "end_line": 21, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 21, + "column": 5, + "end_line": 21, + "end_column": 6 + }, + "generators": [ + { + "node": { + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 21, + "column": 11, + "end_line": 21, + "end_column": 12 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 21, + "column": 11, + "end_line": 21, + "end_column": 12 + } + ], + "iter": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 21, + "column": 17, + "end_line": 21, + "end_column": 18 + }, + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "hello.k", + "line": 21, + "column": 20, + "end_line": 21, + "end_column": 21 + }, + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 3 + } + }, + "filename": "hello.k", + "line": 21, + "column": 23, + "end_line": 21, + "end_column": 24 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 21, + "column": 16, + "end_line": 21, + "end_column": 25 + }, + "ifs": [] + }, + "filename": "hello.k", + "line": 21, + "column": 7, + "end_line": 21, + "end_column": 25 + } + ] + }, + "filename": "hello.k", + "line": 21, + "column": 4, + "end_line": 21, + "end_column": 26 + } + ] + }, + "filename": "hello.k", + "line": 21, + "column": 4, + "end_line": 21, + "end_column": 26 + }, + { + "node": { + "type": "Expr", + "exprs": [ + { + "node": { + "type": "ListComp", + "elt": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 23, + "column": 8, + "end_line": 23, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 23, + "column": 8, + "end_line": 23, + "end_column": 9 + }, + "generators": [ + { + "node": { + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 23, + "column": 14, + "end_line": 23, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 23, + "column": 14, + "end_line": 23, + "end_column": 15 + } + ], + "iter": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 23, + "column": 20, + "end_line": 23, + "end_column": 21 + }, + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "hello.k", + "line": 23, + "column": 23, + "end_line": 23, + "end_column": 24 + }, + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 3 + } + }, + "filename": "hello.k", + "line": 23, + "column": 26, + "end_line": 23, + "end_column": 27 + } + ], + "ctx": "Load" + }, + "filename": "hello.k", + "line": 23, + "column": 19, + "end_line": 23, + "end_column": 28 + }, + "ifs": [] + }, + "filename": "hello.k", + "line": 23, + "column": 10, + "end_line": 24, + "end_column": 0 + } + ] + }, + "filename": "hello.k", + "line": 22, + "column": 4, + "end_line": 24, + "end_column": 5 + } + ] + }, + "filename": "hello.k", + "line": 22, + "column": 4, + "end_line": 24, + "end_column": 5 + } + ], + "decorators": [], + "checks": [ + { + "node": { + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "hello.k", + "line": 27, + "column": 8, + "end_line": 27, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 27, + "column": 8, + "end_line": 27, + "end_column": 9 + }, + "ops": [ + "Gt" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "hello.k", + "line": 27, + "column": 12, + "end_line": 27, + "end_column": 13 + } + ] + }, + "filename": "hello.k", + "line": 27, + "column": 8, + "end_line": 27, + "end_column": 13 + }, + "if_cond": null, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"msg\"", + "value": "msg" + }, + "filename": "hello.k", + "line": 27, + "column": 15, + "end_line": 27, + "end_column": 20 + } + }, + "filename": "hello.k", + "line": 27, + "column": 8, + "end_line": 27, + "end_column": 20 + }, + { + "node": { + "test": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "name", + "filename": "hello.k", + "line": 28, + "column": 8, + "end_line": 28, + "end_column": 12 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello.k", + "line": 28, + "column": 8, + "end_line": 28, + "end_column": 12 + }, + "if_cond": null, + "msg": null + }, + "filename": "hello.k", + "line": 28, + "column": 8, + "end_line": 28, + "end_column": 12 + }, + { + "node": { + "test": { + "node": { + "type": "Unary", + "op": "Not", + "operand": { + "node": { + "type": "NameConstantLit", + "value": "None" + }, + "filename": "hello.k", + "line": 28, + "column": 17, + "end_line": 28, + "end_column": 21 + } + }, + "filename": "hello.k", + "line": 28, + "column": 13, + "end_line": 28, + "end_column": 21 + }, + "if_cond": null, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"we fail here\"", + "value": "we fail here" + }, + "filename": "hello.k", + "line": 28, + "column": 23, + "end_line": 28, + "end_column": 37 + } + }, + "filename": "hello.k", + "line": 28, + "column": 13, + "end_line": 28, + "end_column": 37 + } + ], + "index_signature": { + "node": { + "key_name": null, + "value": null, + "any_other": true, + "key_ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "hello.k", + "line": 7, + "column": 8, + "end_line": 7, + "end_column": 11 + }, + "value_ty": { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "hello.k", + "line": 7, + "column": 14, + "end_line": 7, + "end_column": 17 + } + }, + "filename": "hello.k", + "line": 7, + "column": 4, + "end_line": 8, + "end_column": 0 + } + }, + "filename": "hello.k", + "line": 2, + "column": 0, + "end_line": 29, + "end_column": 8 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_0.snap index 3b954a7e2..0e563b4aa 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_0.snap @@ -5,7 +5,7 @@ expression: "crate::tests::parsing_module_string(r#\"assert\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_1.snap index 4c1772cb4..b8f640899 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_1.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 157 expression: "crate::tests::parsing_module_string(r#\"assert a.\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -16,8 +15,22 @@ Module { node: Identifier( Identifier { names: [ - "a", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + Node { + node: "", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_2.snap index 268fdb8fc..66f232e90 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_2.snap @@ -5,7 +5,7 @@ expression: "crate::tests::parsing_module_string(r#\"assert True,,, 'msg'\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_3.snap index ef733ae31..bc04b5ace 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assert_stmt_recovery_3.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 159 expression: "crate::tests::parsing_module_string(r#\"assert True if data else 'msg'\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -29,7 +28,14 @@ Module { node: Identifier( Identifier { names: [ - "data", + Node { + node: "data", + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 19, + }, ], pkgpath: "", ctx: Load, @@ -59,7 +65,14 @@ Module { node: Identifier( Identifier { names: [ - "else", + Node { + node: "else", + filename: "", + line: 1, + column: 20, + end_line: 1, + end_column: 24, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_0.snap index 816185317..de7843857 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_0.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 170 expression: "crate::tests::parsing_module_string(r#\"a = \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,7 +16,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Store, @@ -37,7 +45,6 @@ Module { end_line: 1, end_column: 4, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_1.snap index c18262818..017872b98 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_1.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 146 expression: "crate::tests::parsing_module_string(r#\" = 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_10.snap index ed5445a68..bc681b829 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_10.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 171 expression: "crate::tests::parsing_module_string(r#\"a[0] -= 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_2.snap index 574e5a445..c14a848ec 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_2.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 172 expression: "crate::tests::parsing_module_string(r#\"a: int =\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,7 +16,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Store, @@ -37,16 +45,6 @@ Module { end_line: 1, end_column: 8, }, - type_annotation: Some( - Node { - node: "int", - filename: "", - line: 1, - column: 3, - end_line: 1, - end_column: 6, - }, - ), ty: Some( Node { node: Basic( diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_3.snap index cf3936b8e..ae525294e 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_3.snap @@ -1,12 +1,12 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 148 +assertion_line: 173 expression: "crate::tests::parsing_module_string(r#\"a: a = 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -16,7 +16,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Store, @@ -43,22 +50,19 @@ Module { end_line: 1, end_column: 8, }, - type_annotation: Some( - Node { - node: "a", - filename: "", - line: 1, - column: 3, - end_line: 1, - end_column: 4, - }, - ), ty: Some( Node { node: Named( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_4.snap index 67d801d81..713264e42 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_4.snap @@ -1,14 +1,69 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 149 +assertion_line: 174 expression: "crate::tests::parsing_module_string(r#\"a:\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", - body: [], + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, + ty: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], comments: [], } diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_5.snap index f43dd11fe..a269227ee 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_5.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 175 expression: "crate::tests::parsing_module_string(r#\"a = b = \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,7 +16,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Store, @@ -29,7 +37,14 @@ Module { Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Store, @@ -51,7 +66,6 @@ Module { end_line: 1, end_column: 8, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_6.snap index ac01fe91c..0a9b5bada 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_6.snap @@ -1,12 +1,12 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 151 +assertion_line: 176 expression: "crate::tests::parsing_module_string(r#\"a() = b. = c\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -28,8 +28,22 @@ Module { Node { node: Identifier { names: [ - "b", - "", + Node { + node: "b", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + Node { + node: "", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Store, @@ -45,7 +59,14 @@ Module { node: Identifier( Identifier { names: [ - "c", + Node { + node: "c", + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, ], pkgpath: "", ctx: Load, @@ -57,7 +78,6 @@ Module { end_line: 1, end_column: 12, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_7.snap index b6e68092a..80ef40aef 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_7.snap @@ -1,39 +1,75 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 152 +assertion_line: 177 expression: "crate::tests::parsing_module_string(r#\"a: () = 0\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { - node: Expr( - ExprStmt { - exprs: [ + node: Assign( + AssignStmt { + targets: [ Node { - node: NumberLit( - NumberLit { - binary_suffix: None, - value: Int( - 0, - ), + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: None, + ret_ty: None, }, ), filename: "", line: 1, - column: 8, + column: 3, end_line: 1, - end_column: 9, + end_column: 5, }, - ], + ), }, ), filename: "", line: 1, - column: 8, + column: 0, end_line: 1, end_column: 9, }, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_8.snap index 59d6f12f7..40632b2db 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_8.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_8.snap @@ -1,39 +1,75 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 153 +assertion_line: 178 expression: "crate::tests::parsing_module_string(r#\"a: () = 0\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { - node: Expr( - ExprStmt { - exprs: [ + node: Assign( + AssignStmt { + targets: [ Node { - node: NumberLit( - NumberLit { - binary_suffix: None, - value: Int( - 0, - ), + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: None, + ret_ty: None, }, ), filename: "", line: 1, - column: 8, + column: 3, end_line: 1, - end_column: 9, + end_column: 5, }, - ], + ), }, ), filename: "", line: 1, - column: 8, + column: 0, end_line: 1, end_column: 9, }, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_9.snap index 173b84ef8..cdf76703f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_9.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__assign_stmt_recovery_9.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 154 expression: "crate::tests::parsing_module_string(r#\"a ++= 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_0.snap index 3b1bef3ac..bd7c6ee1d 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_0.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 63 expression: "crate::tests::parsing_expr_string(r#\"a not is b\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_1.snap index 486f01f7a..c216df331 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 64 expression: "crate::tests::parsing_expr_string(r#\"a is is not b\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -30,7 +36,14 @@ Node { node: Identifier( Identifier { names: [ - "is", + Node { + node: "is", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_2.snap index 4c6aa7372..977b93b43 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_2.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 65 expression: "crate::tests::parsing_expr_string(r#\"a not b\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_3.snap index 1adbcb8ba..bf68b34e3 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_3.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 66 expression: "crate::tests::parsing_expr_string(r#\"a not is in b\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_4.snap index d92242b9e..d4b9948ff 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 67 expression: "crate::tests::parsing_expr_string(r#\"a in in b\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -30,7 +36,14 @@ Node { node: Identifier( Identifier { names: [ - "in", + Node { + node: "in", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_5.snap index 50f32141c..c597b6281 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 68 expression: "crate::tests::parsing_expr_string(r#\"a ++ b\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -22,9 +28,7 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Unary( UnaryExpr { @@ -33,7 +37,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_6.snap index 6e7ca10ed..ad0ad2629 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_6.snap @@ -12,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -24,9 +31,7 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Sub, - ), + op: Sub, right: Node { node: Unary( UnaryExpr { @@ -57,14 +62,19 @@ Node { end_line: 1, end_column: 6, }, - op: Bin( - Sub, - ), + op: Sub, right: Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_7.snap index 15d1d32d6..1f0594d49 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_7.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 70 expression: "crate::tests::parsing_expr_string(r#\"a +is b\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -22,14 +28,19 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Identifier( Identifier { names: [ - "is", + Node { + node: "is", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_8.snap index 6f758f811..e76e3f815 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_8.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__binary_recovery_8.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 71 expression: "crate::tests::parsing_expr_string(r#\"a +=+ b\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_0.snap index 6eecf95e2..765f62e31 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_0.snap @@ -9,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_1.snap index a816d63c6..bdfd9fb5a 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 113 expression: "crate::tests::parsing_expr_string(r#\"a(]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_2.snap index f7a79b3b3..f6572f600 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_2.snap @@ -9,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -26,7 +33,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_3.snap index 25be34297..e853ca663 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 115 expression: "crate::tests::parsing_expr_string(r#\"a.b(a=1,2)\"#)" --- Node { @@ -10,8 +9,22 @@ Node { node: Identifier( Identifier { names: [ - "a", - "b", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "b", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, @@ -46,7 +59,14 @@ Node { arg: Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_4.snap index b6f4e6236..174c24666 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 116 expression: "crate::tests::parsing_expr_string(r#\"a(a.ba=1,2)\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -45,8 +51,22 @@ Node { arg: Node { node: Identifier { names: [ - "a", - "ba", + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + Node { + node: "ba", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_5.snap index fb4911774..b279a496b 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 117 expression: "crate::tests::parsing_expr_string(r#\"a(a.b+a=1,2)\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_6.snap index de789f580..0b7e629f4 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 118 expression: "crate::tests::parsing_expr_string(r#\"a(a-1.b=1)\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_7.snap index 723bad9e6..064b56799 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__call_recovery_7.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 144 expression: "crate::tests::parsing_expr_string(r#\"a(type=\"list\", \"key\")\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -44,7 +50,14 @@ Node { arg: Node { node: Identifier { names: [ - "type", + Node { + node: "type", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_0.snap index 2c3b84950..8a232b432 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_0.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 71 expression: "crate::tests::parsing_expr_string(\"[i for i in [1,2,3]]\")" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -29,7 +35,14 @@ Node { Node { node: Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_1.snap index eb394815c..4d07d7700 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 72 expression: "crate::tests::parsing_expr_string(\"[i, j for i in [1,2,3]]\")" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -29,7 +35,14 @@ Node { Node { node: Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_3.snap index 0df1e55ad..823289713 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 74 expression: "crate::tests::parsing_expr_string(\"{i for i in [1,2,3]}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -34,7 +40,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_4.snap index d6f5f4cdb..5f23dacbc 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 75 expression: "crate::tests::parsing_expr_string(\"{i: for i in [1,2,3]}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -31,7 +37,14 @@ Node { node: Identifier( Identifier { names: [ - "for", + Node { + node: "for", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, @@ -62,7 +75,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_5.snap index 0bf399bf3..5f6f6520e 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__comp_clause_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 76 expression: "crate::tests::parsing_expr_string(\"{i: 1, j for i in [1,2,3]}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -58,7 +64,14 @@ Node { node: Identifier( Identifier { names: [ - "j", + Node { + node: "j", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, @@ -78,7 +91,14 @@ Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_0.snap index dd7b2ca60..a64d0b4e7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_0.snap @@ -9,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -40,7 +47,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_1.snap index 5fdafedad..d75e31cfd 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 73 expression: "crate::tests::parsing_expr_string(r#\"a < !b >!1\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -35,7 +41,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_2.snap index d9abd32f9..d75e31cfd 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 74 expression: "crate::tests::parsing_expr_string(r#\"a < !b >!1\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -35,7 +41,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_3.snap index f89c3c9c4..d7b4ce34f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_3.snap @@ -12,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -24,9 +31,7 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - LShift, - ), + op: LShift, right: Node { node: Missing( MissingExpr, @@ -53,7 +58,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_4.snap index 63861ae45..180757482 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_4.snap @@ -9,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -52,7 +59,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_5.snap index 2a8dcf32d..3b231aeec 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 77 expression: "crate::tests::parsing_expr_string(r#\"a >+ b\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -34,7 +40,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_6.snap index 48a874d6a..d0df0d26a 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__compare_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 78 expression: "crate::tests::parsing_expr_string(r#\"+ b\"#)" --- Node { @@ -25,7 +24,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -45,7 +51,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_1.snap index 6ab627e0e..d608c7b68 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 15 expression: "crate::tests::parsing_expr_string(\"{a = 1\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_10.snap index 7facff34b..88b7b2924 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_10.snap @@ -13,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -50,14 +57,19 @@ Node { end_line: 1, end_column: 7, }, - op: Bin( - Mul, - ), + op: Mul, right: Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_11.snap index 702db6551..0a85fd535 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_11.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_11.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 69 expression: "crate::tests::parsing_expr_string(\"{if True: a = , b = 2}\")" --- Node { @@ -33,7 +32,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, @@ -61,7 +67,7 @@ Node { }, filename: "", line: 1, - column: 14, + column: 10, end_line: 1, end_column: 15, }, @@ -71,9 +77,9 @@ Node { ), filename: "", line: 1, - column: 10, + column: 1, end_line: 1, - end_column: 13, + end_column: 15, }, operation: Union, insert_index: -1, @@ -91,7 +97,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 17, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_12.snap index 897a66ec5..9c2b072c7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_12.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_12.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 70 expression: "crate::tests::parsing_expr_string(\"{if True: *a, b = 2}\")" --- Node { @@ -42,14 +41,19 @@ Node { end_line: 1, end_column: 11, }, - op: Bin( - Mul, - ), + op: Mul, right: Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, ], pkgpath: "", ctx: Load, @@ -85,7 +89,7 @@ Node { }, filename: "", line: 1, - column: 12, + column: 10, end_line: 1, end_column: 13, }, @@ -95,9 +99,9 @@ Node { ), filename: "", line: 1, - column: 10, + column: 1, end_line: 1, - end_column: 12, + end_column: 13, }, operation: Union, insert_index: -1, @@ -115,7 +119,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_13.snap index 181c8aff6..858f13649 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_13.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_13.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 71 expression: "crate::tests::parsing_expr_string(\"{if True: key: {}}\")" --- Node { @@ -33,7 +32,14 @@ Node { node: Identifier( Identifier { names: [ - "key", + Node { + node: "key", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, @@ -63,7 +69,7 @@ Node { }, filename: "", line: 1, - column: 15, + column: 10, end_line: 1, end_column: 17, }, @@ -73,9 +79,9 @@ Node { ), filename: "", line: 1, - column: 10, + column: 1, end_line: 1, - end_column: 17, + end_column: 18, }, operation: Union, insert_index: -1, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_14.snap index b3db187b9..339870ddd 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_14.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_14.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 72 expression: "crate::tests::parsing_expr_string(\"{if True: key: []}\")" --- Node { @@ -33,7 +32,14 @@ Node { node: Identifier( Identifier { names: [ - "key", + Node { + node: "key", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, @@ -64,7 +70,7 @@ Node { }, filename: "", line: 1, - column: 15, + column: 10, end_line: 1, end_column: 17, }, @@ -74,9 +80,9 @@ Node { ), filename: "", line: 1, - column: 10, + column: 1, end_line: 1, - end_column: 17, + end_column: 18, }, operation: Union, insert_index: -1, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_15.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_15.snap new file mode 100644 index 000000000..6af1cafc7 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_15.snap @@ -0,0 +1,65 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 73 +expression: "crate::tests::parsing_expr_string(\"{你好\")" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "你好", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_2.snap index fad62a544..f04db9f45 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 16 expression: "crate::tests::parsing_expr_string(\"{a = 1, b = 2\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -58,7 +64,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_3.snap index 943ef87e2..ffe8fd510 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 17 expression: "crate::tests::parsing_expr_string(\"{a = {a = 1}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -38,7 +44,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_4.snap index d452826d8..47f298ace 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 18 expression: "crate::tests::parsing_expr_string(\"{a = {a = 1\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -38,7 +44,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_5.snap index 24a8138ce..16f955e71 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 19 expression: "crate::tests::parsing_expr_string(r#\"{\n a = 1\n b = 2\n \"#)" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, ], pkgpath: "", ctx: Load, @@ -58,7 +64,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 5, + }, ], pkgpath: "", ctx: Load, @@ -95,6 +108,39 @@ Node { end_line: 3, end_column: 9, }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 4, + column: 4, + end_line: 4, + end_column: 4, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 4, + column: 4, + end_line: 4, + end_column: 4, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 4, + column: 4, + end_line: 4, + end_column: 4, + }, ], }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_6.snap index 65a6b5194..26b784328 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 64 expression: "crate::tests::parsing_expr_string(\"{a = 1 b = 2}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -58,7 +64,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_7.snap index 9f2d22cdb..a1b7d7b23 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_7.snap @@ -13,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -68,7 +75,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_8.snap index 6d4b02d17..2ceb8cd02 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_8.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_8.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 66 expression: "crate::tests::parsing_expr_string(\"{a = 1 ~ b = 2}\")" --- Node { @@ -14,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -62,7 +68,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_9.snap index 4341c7db9..a7a132f69 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_9.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__config_recovery_9.snap @@ -22,14 +22,19 @@ Node { end_line: 1, end_column: 2, }, - op: Bin( - Mul, - ), + op: Mul, right: Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, @@ -63,14 +68,19 @@ Node { end_line: 1, end_column: 7, }, - op: Bin( - Pow, - ), + op: Pow, right: Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_0.snap new file mode 100644 index 000000000..cc0ed2331 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_0.snap @@ -0,0 +1,85 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 303 +expression: "crate::tests::parsing_module_string(r#\"a:(\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Any, + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_1.snap new file mode 100644 index 000000000..e49b03b5b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_1.snap @@ -0,0 +1,108 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 304 +expression: "crate::tests::parsing_module_string(r#\"a:(i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_10.snap new file mode 100644 index 000000000..73cb8778e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_10.snap @@ -0,0 +1,108 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 313 +expression: "crate::tests::parsing_module_string(r#\"a:({\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, + ), + value_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_11.snap new file mode 100644 index 000000000..5cfbba9c7 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_11.snap @@ -0,0 +1,123 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 314 +expression: "crate::tests::parsing_module_string(r#\"a:({i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 5, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_12.snap new file mode 100644 index 000000000..0eb248a85 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_12.snap @@ -0,0 +1,123 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 315 +expression: "crate::tests::parsing_module_string(r#\"a:({i:\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_13.snap new file mode 100644 index 000000000..68ec7d35f --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_13.snap @@ -0,0 +1,138 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 316 +expression: "crate::tests::parsing_module_string(r#\"a:({i:i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 7, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_14.snap new file mode 100644 index 000000000..31246010e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_14.snap @@ -0,0 +1,125 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 317 +expression: "crate::tests::parsing_module_string(r#\"a:({i:int\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 9, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 9, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_15.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_15.snap new file mode 100644 index 000000000..3731cbe38 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_15.snap @@ -0,0 +1,133 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 318 +expression: "crate::tests::parsing_module_string(r#\"a:({i:int]\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 10, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 10, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 10, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_16.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_16.snap new file mode 100644 index 000000000..02ae0f14a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_16.snap @@ -0,0 +1,120 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 319 +expression: "crate::tests::parsing_module_string(r#\"a:({str:int]\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 12, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 12, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 12, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 12, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_17.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_17.snap new file mode 100644 index 000000000..99eba5b4a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_17.snap @@ -0,0 +1,120 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 320 +expression: "crate::tests::parsing_module_string(r#\"a:({str:int}\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 12, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 12, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 12, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 12, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_18.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_18.snap new file mode 100644 index 000000000..fd30dc8de --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_18.snap @@ -0,0 +1,128 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 321 +expression: "crate::tests::parsing_module_string(r#\"a:({str:int} ->\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 15, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 12, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 15, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 15, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 15, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_19.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_19.snap new file mode 100644 index 000000000..fafafc948 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_19.snap @@ -0,0 +1,136 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 322 +expression: "crate::tests::parsing_module_string(r#\"a:({str:int}) -> i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 18, + end_line: 1, + end_column: 18, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + value_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 12, + }, + ], + ), + ret_ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 18, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_2.snap new file mode 100644 index 000000000..9886a7c98 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_2.snap @@ -0,0 +1,95 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 305 +expression: "crate::tests::parsing_module_string(r#\"a:(int\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_20.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_20.snap new file mode 100644 index 000000000..4643f67e5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_20.snap @@ -0,0 +1,134 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 323 +expression: "crate::tests::parsing_module_string(r#\"a:(str|int) -> i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 16, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 10, + }, + ], + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + ], + ), + ret_ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 16, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_21.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_21.snap new file mode 100644 index 000000000..b3ccd5a8a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_21.snap @@ -0,0 +1,144 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 324 +expression: "crate::tests::parsing_module_string(r#\"a:(str|int, int) -> i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 21, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 10, + }, + ], + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 15, + }, + ], + ), + ret_ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 20, + end_line: 1, + end_column: 21, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 20, + end_line: 1, + end_column: 21, + }, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 21, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_22.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_22.snap new file mode 100644 index 000000000..7cf0505a3 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_22.snap @@ -0,0 +1,141 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 325 +expression: "crate::tests::parsing_module_string(r#\"a:(str|int, int|\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 16, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 10, + }, + ], + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 15, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 16, + }, + ], + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 16, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 16, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_23.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_23.snap new file mode 100644 index 000000000..27c647d88 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_23.snap @@ -0,0 +1,157 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 326 +expression: "crate::tests::parsing_module_string(r#\"a:(str|int, int|) ->\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 20, + end_line: 1, + end_column: 20, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 10, + }, + ], + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 15, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 17, + }, + ], + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 17, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 18, + end_line: 1, + end_column: 20, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 20, + end_line: 1, + end_column: 20, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 20, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_3.snap new file mode 100644 index 000000000..089985ad5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_3.snap @@ -0,0 +1,84 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 306 +expression: "crate::tests::parsing_module_string(r#\"a:i)\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_4.snap new file mode 100644 index 000000000..7090fb529 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_4.snap @@ -0,0 +1,113 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 307 +expression: "crate::tests::parsing_module_string(r#\"a:([i\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 5, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_5.snap new file mode 100644 index 000000000..dce820c2b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_5.snap @@ -0,0 +1,121 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 308 +expression: "crate::tests::parsing_module_string(r#\"a:([i:\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_6.snap new file mode 100644 index 000000000..1958b3b5d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_6.snap @@ -0,0 +1,121 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 309 +expression: "crate::tests::parsing_module_string(r#\"a:([i]\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_7.snap new file mode 100644 index 000000000..0c72fe05e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_7.snap @@ -0,0 +1,108 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 310 +expression: "crate::tests::parsing_module_string(r#\"a:([int]\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 8, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 8, + }, + Node { + node: Any, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 8, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 8, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_8.snap new file mode 100644 index 000000000..98a37fc95 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_8.snap @@ -0,0 +1,100 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 311 +expression: "crate::tests::parsing_module_string(r#\"a:([int\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 7, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_9.snap new file mode 100644 index 000000000..0105b2ad3 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__fn_ty_annotation_recovery_9.snap @@ -0,0 +1,108 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 312 +expression: "crate::tests::parsing_module_string(r#\"a:({}\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, + ty: Some( + Node { + node: Function( + FunctionType { + params_ty: Some( + [ + Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + value_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 5, + }, + ], + ), + ret_ty: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_recovery_4.snap index 7d02a1e8e..ccc877766 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_recovery_4.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 83 expression: "crate::tests::parsing_expr_string(r#\"if True else\"#)" --- Node { node: Identifier( Identifier { names: [ - "if", + Node { + node: "if", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_0.snap index 7d3f16201..2a542bb56 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_0.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 199 expression: "crate::tests::parsing_module_string(r#\"if True a = 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -44,7 +45,6 @@ Module { end_line: 1, end_column: 13, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_1.snap index fc49ee799..d53a4c341 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_1.snap @@ -1,12 +1,12 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 175 +assertion_line: 200 expression: "crate::tests::parsing_module_string(r#\"if True: a = 1 else if b = 2\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -20,7 +20,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, ], pkgpath: "", ctx: Store, @@ -47,7 +54,6 @@ Module { end_line: 1, end_column: 14, }, - type_annotation: None, ty: None, }, ), @@ -78,7 +84,14 @@ Module { Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 24, + }, ], pkgpath: "", ctx: Store, @@ -105,7 +118,6 @@ Module { end_line: 1, end_column: 28, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_2.snap index b27b13695..0825e61de 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_2.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 201 expression: "crate::tests::parsing_module_string(r#\"if : a = 1\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -19,7 +20,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Store, @@ -46,7 +54,6 @@ Module { end_line: 1, end_column: 10, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_3.snap index ddd46d631..08649b203 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_3.snap @@ -1,11 +1,12 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 202 expression: "crate::tests::parsing_module_string(r#\"if True: a = 1 else b = 2\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -19,7 +20,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, ], pkgpath: "", ctx: Store, @@ -46,7 +54,6 @@ Module { end_line: 1, end_column: 14, }, - type_annotation: None, ty: None, }, ), @@ -102,7 +109,6 @@ Module { end_line: 1, end_column: 25, }, - type_annotation: None, ty: None, }, ), diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_4.snap index 8eae18937..1919ee82f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_4.snap @@ -1,12 +1,12 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 178 +assertion_line: 203 expression: "crate::tests::parsing_module_string(r#\"if True: else: b = 2\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -20,7 +20,14 @@ Module { Node { node: Identifier { names: [ - "else", + Node { + node: "else", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Store, @@ -47,22 +54,19 @@ Module { end_line: 1, end_column: 20, }, - type_annotation: Some( - Node { - node: "b", - filename: "", - line: 1, - column: 15, - end_line: 1, - end_column: 16, - }, - ), ty: Some( Node { node: Named( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_5.snap index 6409c75b0..3e5f79f13 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_5.snap @@ -5,7 +5,7 @@ expression: "crate::tests::parsing_module_string(r#\"if\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_6.snap index 458592bf4..fa9ef7dd6 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_6.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 180 expression: "crate::tests::parsing_module_string(r#\"if else\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -41,7 +40,14 @@ Module { node: Identifier( Identifier { names: [ - "else", + Node { + node: "else", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_7.snap new file mode 100644 index 000000000..c2d9dc939 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_7.snap @@ -0,0 +1,39 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_module_string(r#\"if True:\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: If( + IfStmt { + body: [], + cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, + orelse: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_8.snap new file mode 100644 index 000000000..c667f9165 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_8.snap @@ -0,0 +1,157 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 207 +expression: "crate::tests::parsing_module_string(r#\"if True: a = 1\nelse if False: b = 1\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: If( + IfStmt { + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ty: None, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 14, + }, + ], + cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, + orelse: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 2, + column: 8, + end_line: 2, + end_column: 13, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 19, + end_line: 2, + end_column: 20, + }, + ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 2, + column: 15, + end_line: 2, + end_column: 16, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 15, + end_line: 2, + end_column: 16, + }, + ), + }, + ), + filename: "", + line: 2, + column: 8, + end_line: 2, + end_column: 20, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 2, + end_column: 20, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_9.snap new file mode 100644 index 000000000..44c97c538 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__if_stmt_recovery_9.snap @@ -0,0 +1,157 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 209 +expression: "crate::tests::parsing_module_string(r#\"if True: a = 1\nelse False: b = 1\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: If( + IfStmt { + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ty: None, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 14, + }, + ], + cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 7, + }, + orelse: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 11, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 16, + end_line: 2, + end_column: 17, + }, + ty: Some( + Node { + node: Named( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 2, + column: 12, + end_line: 2, + end_column: 13, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 12, + end_line: 2, + end_column: 13, + }, + ), + }, + ), + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 17, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 2, + end_column: 17, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_recovery_0.snap new file mode 100644 index 000000000..2e07fd5ae --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_recovery_0.snap @@ -0,0 +1,37 @@ +--- +source: parser/src/tests/error_recovery.rs +expression: "crate::tests::parsing_module_string(r#\"import json as j.a\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Import( + ImportStmt { + path: Node { + node: "json", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 11, + }, + rawpath: "json", + name: "json", + asname: None, + pkg_name: "", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 18, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_0.snap index 5285bca1d..d8bee29dd 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_0.snap @@ -5,13 +5,20 @@ expression: "crate::tests::parsing_module_string(r#\"import\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "", + path: Node { + node: "", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, rawpath: "", name: "", asname: None, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_1.snap index 2500a2ee2..0fcc1117b 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_1.snap @@ -5,13 +5,20 @@ expression: "crate::tests::parsing_module_string(r#\"import 'pkg_path'\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "", + path: Node { + node: "", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 6, + }, rawpath: "", name: "", asname: None, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_2.snap index 2e6f73acf..731f2e915 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_2.snap @@ -5,13 +5,20 @@ expression: "crate::tests::parsing_module_string(r#\"import pkg_path.\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "pkg_path.", + path: Node { + node: "pkg_path.", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 16, + }, rawpath: "pkg_path.", name: "", asname: None, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_3.snap index a8e038b6a..ebbc792ed 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_3.snap @@ -5,13 +5,20 @@ expression: "crate::tests::parsing_module_string(r#\"import pkg_path[0]\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "pkg_path", + path: Node { + node: "pkg_path", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 15, + }, rawpath: "pkg_path", name: "pkg_path", asname: None, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_4.snap index b6caf5299..657f42f79 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_4.snap @@ -5,13 +5,20 @@ expression: "crate::tests::parsing_module_string(r#\"import .pkg_path.\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: ".pkg_path.", + path: Node { + node: ".pkg_path.", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 17, + }, rawpath: ".pkg_path.", name: "", asname: None, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_5.snap index 82ee0d157..714829607 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_5.snap @@ -5,17 +5,31 @@ expression: "crate::tests::parsing_module_string(r#\"import pkg_path as \"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "pkg_path", + path: Node { + node: "pkg_path", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 15, + }, rawpath: "pkg_path", name: "", asname: Some( - "", + Node { + node: "", + filename: "", + line: 1, + column: 19, + end_line: 1, + end_column: 19, + }, ), pkg_name: "", }, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_6.snap index a15108865..dd46cb3d0 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__import_stmt_recovery_6.snap @@ -5,17 +5,31 @@ expression: "crate::tests::parsing_module_string(r#\"import pkg_path as 'data'\" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Import( ImportStmt { - path: "pkg_path", + path: Node { + node: "pkg_path", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 15, + }, rawpath: "pkg_path", name: "", asname: Some( - "", + Node { + node: "", + filename: "", + line: 1, + column: 19, + end_line: 1, + end_column: 19, + }, ), pkg_name: "", }, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_1.snap index 1c3dc5d81..9e1a8683e 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 152 expression: "crate::tests::parsing_expr_string(r#\"'${a +}'\"#)" --- Node { @@ -19,7 +18,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -31,9 +37,7 @@ Node { end_line: 1, end_column: 4, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Missing( MissingExpr, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_2.snap index 6f2ec641f..7bdb64047 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 153 expression: "crate::tests::parsing_expr_string(r#\"'${(a +}'\"#)" --- Node { @@ -22,7 +21,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, @@ -34,9 +40,7 @@ Node { end_line: 1, end_column: 5, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Missing( MissingExpr, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_5.snap index 3fc7db29c..c974dedbf 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 155 expression: "crate::tests::parsing_expr_string(r#\"'${a + 1 = }'\"#)" --- Node { @@ -19,7 +18,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -31,9 +37,7 @@ Node { end_line: 1, end_column: 4, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: NumberLit( NumberLit { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_6.snap index d5e6c8b4d..466ccce34 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 156 expression: "crate::tests::parsing_expr_string(r#\"'${a: json}'\"#)" --- Node { @@ -16,7 +15,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_7.snap new file mode 100644 index 000000000..5a7e5cefa --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_7.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 158 +expression: "crate::tests::parsing_expr_string(r#\"'\\n${a: #json}'\"#)" +--- +Node { + node: JoinedString( + JoinedString { + is_long_string: false, + values: [ + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\n", + value: "\n", + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 1, + }, + Node { + node: FormattedValue( + FormattedValue { + is_long_string: false, + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + format_spec: Some( + "#json", + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 12, + }, + ], + raw_value: "'\\n${a: #json}'", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 15, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_8.snap new file mode 100644 index 000000000..ecd382291 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__joined_string_recovery_8.snap @@ -0,0 +1,87 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 159 +expression: "crate::tests::parsing_expr_string(r#\"'a\\nb${a: #json}\\n'\"#)" +--- +Node { + node: JoinedString( + JoinedString { + is_long_string: false, + values: [ + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "a\nb", + value: "a\nb", + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 1, + }, + Node { + node: FormattedValue( + FormattedValue { + is_long_string: false, + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + format_spec: Some( + "#json", + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 14, + }, + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\n", + value: "\n", + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 1, + }, + ], + raw_value: "'a\\nb${a: #json}\\n'", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 19, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_0.snap new file mode 100644 index 000000000..72e7e6216 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_0.snap @@ -0,0 +1,33 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 161 +expression: "crate::tests::parsing_expr_string(r#\"lambda\"#)" +--- +Node { + node: Lambda( + LambdaExpr { + args: Some( + Node { + node: Arguments { + args: [], + defaults: [], + ty_list: [], + }, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, + ), + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_1.snap new file mode 100644 index 000000000..01fc43f47 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_1.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 162 +expression: "crate::tests::parsing_expr_string(r#\"lambda {\"#)" +--- +Node { + node: Lambda( + LambdaExpr { + args: None, + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_2.snap new file mode 100644 index 000000000..d591a8a1b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_2.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 163 +expression: "crate::tests::parsing_expr_string(r#\"lambda {}\"#)" +--- +Node { + node: Lambda( + LambdaExpr { + args: None, + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_3.snap new file mode 100644 index 000000000..4995fa293 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_3.snap @@ -0,0 +1,95 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 164 +expression: "crate::tests::parsing_expr_string(r#\"{lambda}\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Lambda( + LambdaExpr { + args: Some( + Node { + node: Arguments { + args: [ + Node { + node: Identifier { + names: [ + Node { + node: "", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 7, + }, + ], + defaults: [ + None, + ], + ty_list: [ + None, + ], + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ), + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 8, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 8, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 8, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_4.snap new file mode 100644 index 000000000..b125d7154 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_4.snap @@ -0,0 +1,56 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 165 +expression: "crate::tests::parsing_expr_string(r#\"{lambda{}\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Lambda( + LambdaExpr { + args: None, + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 9, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 9, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_5.snap new file mode 100644 index 000000000..97642b554 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__lambda_recovery_5.snap @@ -0,0 +1,95 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 166 +expression: "crate::tests::parsing_expr_string(r#\"{lambda a{}\"#)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Lambda( + LambdaExpr { + args: Some( + Node { + node: Arguments { + args: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ], + defaults: [ + None, + ], + ty_list: [ + None, + ], + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ), + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 11, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_2.snap index 3a2f277ea..90d980588 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 23 expression: "crate::tests::parsing_expr_string(r#\"'a' + \\\n'b'\n\"#)" --- Node { @@ -20,9 +19,7 @@ Node { end_line: 1, end_column: 3, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: StringLit( StringLit { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_3.snap index 15a6a49fb..560f44c0f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__line_continue_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 26 expression: "crate::tests::parsing_expr_string(r#\"'a' + \\1\n'b'\n\"#)" --- Node { @@ -20,9 +19,7 @@ Node { end_line: 1, end_column: 3, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: NumberLit( NumberLit { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_10.snap index 4bc767631..47087d246 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_10.snap @@ -19,14 +19,19 @@ Node { end_line: 1, end_column: 3, }, - op: Bin( - Pow, - ), + op: Pow, right: Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -53,7 +58,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_11.snap index 48d5ed406..637195280 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_11.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_11.snap @@ -1,7 +1,6 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 53 -expression: "crate::tests::parsing_expr_string(r#\"[if True: a, b]\"#)" +expression: "crate::tests::parsing_expr_string(\"[if True: a, b]\")" --- Node { node: List( @@ -27,7 +26,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, @@ -53,7 +59,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_12.snap index 4a397e4be..452d8d6fa 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_12.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_12.snap @@ -35,14 +35,19 @@ Node { end_line: 1, end_column: 12, }, - op: Bin( - Pow, - ), + op: Pow, right: Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, @@ -76,7 +81,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_9.snap index 2b65148ce..9d6ba6afb 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_9.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__list_recovery_9.snap @@ -13,7 +13,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, @@ -47,14 +54,19 @@ Node { end_line: 1, end_column: 7, }, - op: Bin( - Pow, - ), + op: Pow, right: Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_0.snap index b8047cb25..658e897e8 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_0.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 3 expression: "crate::tests::parsing_expr_string(\"(a\")" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_1.snap index 14bc70a3b..c5ab49249 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 4 expression: "crate::tests::parsing_expr_string(\"(a + 1\")" --- Node { @@ -13,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -25,9 +31,7 @@ Node { end_line: 1, end_column: 2, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: NumberLit( NumberLit { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_4.snap index 477b1e0af..371a9181f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 35 expression: "crate::tests::parsing_expr_string(r#\"(a\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_5.snap index 3ad71240b..de670e6df 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__paren_recovery_5.snap @@ -12,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, @@ -24,9 +31,7 @@ Node { end_line: 1, end_column: 2, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Missing( MissingExpr, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_0.snap index 30398a626..3fc5d9f81 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_0.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 235 expression: "crate::tests::parsing_module_string(r#\"rule\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_1.snap index 4bb8c6a38..49c016809 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_1.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 236 expression: "crate::tests::parsing_module_string(r#\"rule A\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_2.snap index d0a8053f4..ab4335251 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_2.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 237 +assertion_line: 292 expression: "crate::tests::parsing_module_string(r#\"rule A[\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -29,7 +29,6 @@ Module { node: Arguments { args: [], defaults: [], - type_annotation_list: [], ty_list: [], }, filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_3.snap index fbc048913..bedad302e 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_3.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"rule A::\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_4.snap index c64922282..7ff5d7da5 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_4.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"rule A:B\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_5.snap index c091cafa6..d5d182acf 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_5.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"rule A(:\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_6.snap index 2bfbe5869..d23d36f27 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_6.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 241 expression: "crate::tests::parsing_module_string(r#\"\nrule A:\n True \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_7.snap index 4eb5f0c33..f2d8bb320 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__rule_stmt_recovery_7.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"\nrule A:\n @\n\"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Rule( RuleStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_0.snap index 1b69ce416..5f6e442ad 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_0.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 119 expression: "crate::tests::parsing_expr_string(r#\"s {\"#)" --- Node { @@ -9,7 +8,14 @@ Node { name: Node { node: Identifier { names: [ - "s", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_1.snap index 9307c0f49..b592bbc4f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 120 expression: "crate::tests::parsing_expr_string(r#\"s {a=1\"#)" --- Node { @@ -9,7 +8,14 @@ Node { name: Node { node: Identifier { names: [ - "s", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -33,7 +39,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_2.snap index 542ccc3d8..d601fb18f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_2.snap @@ -1,14 +1,27 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 121 expression: "crate::tests::parsing_expr_string(r#\"s.0 {a=1}\"#)" --- Node { node: Identifier( Identifier { names: [ - "s", - "", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_3.snap index 0193a494b..3e5dc5123 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 148 expression: "crate::tests::parsing_expr_string(r#\"s?.a {a=1}\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "s", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -25,7 +31,14 @@ Node { attr: Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_4.snap index 979504c2a..99c0c29b9 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 123 expression: "crate::tests::parsing_expr_string(r#\"s. {a=1}\"#)" --- Node { @@ -9,8 +8,22 @@ Node { name: Node { node: Identifier { names: [ - "s", - "", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, @@ -34,7 +47,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_5.snap index fd4f97652..2907944f9 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 124 expression: "crate::tests::parsing_expr_string(r#\"s( {a=1}\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "s", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -34,7 +40,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_6.snap index b6eaa091b..04fe34bef 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 125 expression: "crate::tests::parsing_expr_string(r#\"s(] {a=1}\"#)" --- Node { @@ -9,7 +8,14 @@ Node { name: Node { node: Identifier { names: [ - "s", + Node { + node: "s", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -33,7 +39,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_0.snap index 0758a3123..f94cff29f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_0.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 181 expression: "crate::tests::parsing_module_string(r#\"schema\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_1.snap index 4dd515836..13d501d58 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_1.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 182 expression: "crate::tests::parsing_module_string(r#\"schema A\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_10.snap index dce39430a..1b41e73ba 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_10.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 194 +assertion_line: 220 expression: "crate::tests::parsing_module_string(r#\"schema A:\n[str:]: []\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,6 +39,55 @@ Module { end_line: 2, end_column: 0, }, + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 6, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 10, + }, + ty: Some( + Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 2, + column: 8, + end_line: 2, + end_column: 10, + }, + ), + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 6, + }, ], comments: [], } diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_11.snap index 884d6ce56..dedaa1e66 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_11.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_11.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 222 expression: "crate::tests::parsing_module_string(r#\"schema A:\n[str]: str = \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -65,16 +66,6 @@ Module { end_line: 2, end_column: 13, }, - type_annotation: Some( - Node { - node: "str", - filename: "", - line: 2, - column: 7, - end_line: 2, - end_column: 10, - }, - ), ty: Some( Node { node: Basic( diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_12.snap index 85c02e831..fd8aa72d7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_12.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_12.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 224 expression: "crate::tests::parsing_module_string(r#\"schema A:\n[str]: = \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -65,16 +66,6 @@ Module { end_line: 2, end_column: 9, }, - type_annotation: Some( - Node { - node: "any", - filename: "", - line: 2, - column: 7, - end_line: 2, - end_column: 6, - }, - ), ty: Some( Node { node: Any, @@ -82,7 +73,7 @@ Module { line: 2, column: 7, end_line: 2, - end_column: 6, + end_column: 8, }, ), }, @@ -91,7 +82,7 @@ Module { line: 2, column: 0, end_line: 2, - end_column: 8, + end_column: 5, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_13.snap index edd1aff07..b20085b14 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_13.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_13.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 226 expression: "crate::tests::parsing_module_string(r#\"schema A:\n[str]: ''= \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -65,16 +66,6 @@ Module { end_line: 2, end_column: 11, }, - type_annotation: Some( - Node { - node: "\"\"", - filename: "", - line: 2, - column: 7, - end_line: 2, - end_column: 9, - }, - ), ty: Some( Node { node: Literal( diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_14.snap index 28fe08c4a..3c5808425 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_14.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_14.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 202 expression: "crate::tests::parsing_module_string(r#\"schema A:\na??: int \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -47,7 +46,14 @@ Module { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -76,7 +82,14 @@ Module { node: Identifier( Identifier { names: [ - "int", + Node { + node: "int", + filename: "", + line: 2, + column: 5, + end_line: 2, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_15.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_15.snap index dc51a66dc..05b00dd33 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_15.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_15.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"schema A:\na!: int \"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -46,7 +46,14 @@ Module { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -110,7 +117,14 @@ Module { node: Identifier( Identifier { names: [ - "int", + Node { + node: "int", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_16.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_16.snap index 2e13a431d..989c4159f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_16.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_16.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"schema A:\na!!: int \"#)" Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -46,7 +46,14 @@ Module { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -145,7 +152,14 @@ Module { node: Identifier( Identifier { names: [ - "int", + Node { + node: "int", + filename: "", + line: 2, + column: 5, + end_line: 2, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_17.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_17.snap index 3fb382f8d..9841b3f98 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_17.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_17.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 208 +assertion_line: 234 expression: "crate::tests::parsing_module_string(r#\"schema A:\na: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,6 +39,60 @@ Module { end_line: 2, end_column: 0, }, + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 3, + end_line: 2, + end_column: 3, + }, + ty: Some( + Node { + node: Any, + filename: "", + line: 2, + column: 3, + end_line: 2, + end_column: 3, + }, + ), + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, ], comments: [], } diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_19.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_19.snap index 873ddc802..a456bde77 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_19.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_19.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 210 +assertion_line: 236 expression: "crate::tests::parsing_module_string(r#\"@deprecated\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -40,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -58,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -66,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -76,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_2.snap index 9e2848ca6..1869dbab7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_2.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 183 +assertion_line: 209 expression: "crate::tests::parsing_module_string(r#\"schema A[\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -30,7 +30,6 @@ Module { node: Arguments { args: [], defaults: [], - type_annotation_list: [], ty_list: [], }, filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_20.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_20.snap index 4b486b891..f25921168 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_20.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_20.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 239 expression: "crate::tests::parsing_module_string(r#\"@deprecated(\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -57,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -65,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -75,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_21.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_21.snap index 4b486b891..f5fc62b5c 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_21.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_21.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 242 expression: "crate::tests::parsing_module_string(r#\"@deprecated(\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -57,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -65,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -75,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_22.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_22.snap index 6fedcaa4a..cdd1cdef6 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_22.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_22.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 219 +assertion_line: 245 expression: "crate::tests::parsing_module_string(r#\"@deprecated(a\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -40,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -58,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -66,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -76,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, @@ -93,7 +92,14 @@ Module { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_23.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_23.snap index 39fdcfb21..71c00d226 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_23.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_23.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 248 expression: "crate::tests::parsing_module_string(r#\"@deprecated(a,\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -57,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -65,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -75,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, @@ -92,7 +92,14 @@ Module { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_24.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_24.snap index 2dfa47ba4..0bb76d007 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_24.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_24.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 251 expression: "crate::tests::parsing_module_string(r#\"@deprecated((),\nschema A:\n a: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,14 +40,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 7, - end_line: 3, - end_column: 6, - }, op: None, value: None, is_optional: false, @@ -57,7 +50,7 @@ Module { line: 3, column: 7, end_line: 3, - end_column: 6, + end_column: 7, }, }, ), @@ -65,7 +58,7 @@ Module { line: 3, column: 4, end_line: 3, - end_column: 6, + end_column: 7, }, ], decorators: [ @@ -75,7 +68,14 @@ Module { node: Identifier( Identifier { names: [ - "deprecated", + Node { + node: "deprecated", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_25.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_25.snap index fb42df657..ea0098709 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_25.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_25.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 228 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n check: \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -58,8 +57,8 @@ Module { filename: "", line: 2, column: 0, - end_line: 3, - end_column: 11, + end_line: 4, + end_column: 0, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_26.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_26.snap index b6b56650b..4668c6775 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_26.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_26.snap @@ -5,13 +5,13 @@ expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n check: \n Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_27.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_27.snap index 886cbd9f0..26a7501ef 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_27.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_27.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 248 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n [.str]: str \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -48,7 +47,14 @@ Module { attr: Node { node: Identifier { names: [ - "str", + Node { + node: "str", + filename: "", + line: 3, + column: 6, + end_line: 3, + end_column: 9, + }, ], pkgpath: "", ctx: Load, @@ -101,6 +107,29 @@ Module { end_line: 3, end_column: 10, }, + Node { + node: Expr( + ExprStmt { + exprs: [ + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 16, + end_line: 3, + end_column: 16, + }, + ], + }, + ), + filename: "", + line: 3, + column: 16, + end_line: 3, + end_column: 16, + }, ], decorators: [], checks: [], @@ -110,8 +139,8 @@ Module { filename: "", line: 2, column: 0, - end_line: 3, - end_column: 16, + end_line: 4, + end_column: 0, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_28.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_28.snap index bc7a184ed..a03501873 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_28.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_28.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 251 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n [....str]: str \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -71,7 +70,14 @@ Module { attr: Node { node: Identifier { names: [ - "str", + Node { + node: "str", + filename: "", + line: 3, + column: 9, + end_line: 3, + end_column: 12, + }, ], pkgpath: "", ctx: Load, @@ -124,6 +130,29 @@ Module { end_line: 3, end_column: 13, }, + Node { + node: Expr( + ExprStmt { + exprs: [ + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 3, + column: 19, + end_line: 3, + end_column: 19, + }, + ], + }, + ), + filename: "", + line: 3, + column: 19, + end_line: 3, + end_column: 19, + }, ], decorators: [], checks: [], @@ -133,8 +162,8 @@ Module { filename: "", line: 2, column: 0, - end_line: 3, - end_column: 19, + end_line: 4, + end_column: 0, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_29.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_29.snap index 3297f6bc4..af9dc19f1 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_29.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_29.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 254 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n @\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -40,14 +39,6 @@ Module { end_line: 3, end_column: 5, }, - type_str: Node { - node: "any", - filename: "", - line: 3, - column: 5, - end_line: 3, - end_column: 5, - }, op: None, value: None, is_optional: false, @@ -77,8 +68,8 @@ Module { filename: "", line: 2, column: 0, - end_line: 3, - end_column: 5, + end_line: 4, + end_column: 0, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_3.snap index 11dafe15c..58ca309cd 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_3.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 184 expression: "crate::tests::parsing_module_string(r#\"schema A::\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_30.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_30.snap index 8d2d3c25d..f16793e95 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_30.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_30.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 257 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n .\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -48,7 +47,14 @@ Module { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 3, + column: 5, + end_line: 3, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_31.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_31.snap index dfdad6639..c6be13f8f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_31.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_31.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 262 +assertion_line: 273 expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n [str]: str\n [str]: int\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -34,24 +34,31 @@ Module { Node { node: SchemaIndexSignature { key_name: None, - key_type: Node { - node: "str", + value: None, + any_other: false, + key_ty: Node { + node: Named( + Identifier { + names: [ + Node { + node: "str", + filename: "", + line: 4, + column: 5, + end_line: 4, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), filename: "", line: 4, column: 5, end_line: 4, end_column: 8, }, - value_type: Node { - node: "int", - filename: "", - line: 4, - column: 11, - end_line: 4, - end_column: 14, - }, - value: None, - any_other: false, value_ty: Node { node: Basic( Int, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_32.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_32.snap new file mode 100644 index 000000000..e8eaa3848 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_32.snap @@ -0,0 +1,80 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 277 +expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n \"attr\": str\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Schema( + SchemaStmt { + doc: None, + name: Node { + node: "A", + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 8, + }, + parent_name: None, + for_host_name: None, + is_mixin: false, + is_protocol: false, + args: None, + mixins: [], + body: [ + Node { + node: SchemaAttr( + SchemaAttr { + doc: "", + name: Node { + node: "attr", + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 10, + }, + op: None, + value: None, + is_optional: false, + decorators: [], + ty: Node { + node: Basic( + Str, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 15, + }, + }, + ), + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 15, + }, + ], + decorators: [], + checks: [], + index_signature: None, + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 3, + end_column: 15, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_33.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_33.snap new file mode 100644 index 000000000..30f0e4146 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_33.snap @@ -0,0 +1,89 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 280 +expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n \"\"\"Schema Doc\"\"\"\n \"attr\": str\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Schema( + SchemaStmt { + doc: Some( + Node { + node: "\"\"\"Schema Doc\"\"\"", + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 20, + }, + ), + name: Node { + node: "A", + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 8, + }, + parent_name: None, + for_host_name: None, + is_mixin: false, + is_protocol: false, + args: None, + mixins: [], + body: [ + Node { + node: SchemaAttr( + SchemaAttr { + doc: "", + name: Node { + node: "attr", + filename: "", + line: 4, + column: 4, + end_line: 4, + end_column: 10, + }, + op: None, + value: None, + is_optional: false, + decorators: [], + ty: Node { + node: Basic( + Str, + ), + filename: "", + line: 4, + column: 12, + end_line: 4, + end_column: 15, + }, + }, + ), + filename: "", + line: 4, + column: 4, + end_line: 4, + end_column: 15, + }, + ], + decorators: [], + checks: [], + index_signature: None, + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 4, + end_column: 15, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_34.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_34.snap new file mode 100644 index 000000000..8b6008a50 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_34.snap @@ -0,0 +1,54 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 284 +expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n \"attr: str\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Schema( + SchemaStmt { + doc: Some( + Node { + node: "\"attr: str", + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 14, + }, + ), + name: Node { + node: "A", + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 8, + }, + parent_name: None, + for_host_name: None, + is_mixin: false, + is_protocol: false, + args: None, + mixins: [], + body: [], + decorators: [], + checks: [], + index_signature: None, + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 3, + end_column: 14, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_35.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_35.snap new file mode 100644 index 000000000..5d5215a7b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_35.snap @@ -0,0 +1,78 @@ +--- +source: parser/src/tests/error_recovery.rs +assertion_line: 287 +expression: "crate::tests::parsing_module_string(r#\"\nschema A:\n \"attr\":\"#)" +--- +Module { + filename: "", + pkg: "", + doc: None, + name: "", + body: [ + Node { + node: Schema( + SchemaStmt { + doc: None, + name: Node { + node: "A", + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 8, + }, + parent_name: None, + for_host_name: None, + is_mixin: false, + is_protocol: false, + args: None, + mixins: [], + body: [ + Node { + node: SchemaAttr( + SchemaAttr { + doc: "", + name: Node { + node: "attr", + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 10, + }, + op: None, + value: None, + is_optional: false, + decorators: [], + ty: Node { + node: Any, + filename: "", + line: 3, + column: 11, + end_line: 3, + end_column: 11, + }, + }, + ), + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 11, + }, + ], + decorators: [], + checks: [], + index_signature: None, + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 3, + end_column: 11, + }, + ], + comments: [], +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_4.snap index 1a1d19920..968e818fe 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_4.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 185 expression: "crate::tests::parsing_module_string(r#\"schema A:B\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -47,7 +46,14 @@ Module { node: Identifier( Identifier { names: [ - "B", + Node { + node: "B", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 10, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_5.snap index 9aba9f49b..16fc98cdc 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_5.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 186 expression: "crate::tests::parsing_module_string(r#\"schema A(:\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -25,7 +24,14 @@ Module { Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_6.snap index a66f002e6..fc1dcfd5a 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_6.snap @@ -1,18 +1,17 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 187 expression: "crate::tests::parsing_module_string(r#\"schema A():\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -25,7 +24,14 @@ Module { Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_7.snap index 44cda624b..a235208a7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_7.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 188 +assertion_line: 214 expression: "crate::tests::parsing_module_string(r#\"schema A:\na:: int\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,6 +39,60 @@ Module { end_line: 2, end_column: 0, }, + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 7, + }, + ty: Some( + Node { + node: Any, + filename: "", + line: 2, + column: 2, + end_line: 2, + end_column: 3, + }, + ), + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, Node { node: Expr( ExprStmt { @@ -47,7 +101,14 @@ Module { node: Identifier( Identifier { names: [ - "int", + Node { + node: "int", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_8.snap index cb61c6ea5..4e7515c44 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_8.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_8.snap @@ -1,17 +1,18 @@ --- source: parser/src/tests/error_recovery.rs +assertion_line: 216 expression: "crate::tests::parsing_module_string(r#\"schema A:\na: int =\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -45,7 +46,14 @@ Module { Node { node: Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, ], pkgpath: "", ctx: Store, @@ -67,16 +75,6 @@ Module { end_line: 2, end_column: 8, }, - type_annotation: Some( - Node { - node: "int", - filename: "", - line: 2, - column: 3, - end_line: 2, - end_column: 6, - }, - ), ty: Some( Node { node: Basic( diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_9.snap index e0bef0d5d..7cc92559f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_9.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__schema_stmt_recovery_9.snap @@ -1,18 +1,18 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 192 +assertion_line: 218 expression: "crate::tests::parsing_module_string(r#\"schema A:\n[]: []\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { node: Schema( SchemaStmt { - doc: "", + doc: None, name: Node { node: "A", filename: "", @@ -39,6 +39,55 @@ Module { end_line: 2, end_column: 0, }, + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 2, + }, + ], + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 6, + end_line: 2, + end_column: 6, + }, + ty: Some( + Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 2, + }, ], comments: [], } diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_0.snap index cb4864d88..bbe003c51 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_0.snap @@ -1,14 +1,27 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 97 expression: "crate::tests::parsing_expr_string(r#\"a.\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_1.snap index 1f7b8919f..97847cd0c 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_1.snap @@ -1,15 +1,35 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 98 expression: "crate::tests::parsing_expr_string(r#\"a.b.\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", - "b", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "b", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + Node { + node: "", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_10.snap index cd8646e56..35c0b2f28 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_10.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 132 expression: "crate::tests::parsing_expr_string(r#\"a?.b?\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -25,7 +31,14 @@ Node { attr: Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_11.snap index ab5eb759e..615b8a3db 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_11.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_11.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 133 expression: "crate::tests::parsing_expr_string(r#\"a?.b?.c?\"#)" --- Node { @@ -13,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -28,7 +34,14 @@ Node { attr: Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -52,7 +65,14 @@ Node { attr: Node { node: Identifier { names: [ - "c", + Node { + node: "c", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_12.snap index d7b1323d1..7deefffd2 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_12.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_12.snap @@ -1,14 +1,27 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 109 expression: "crate::tests::parsing_expr_string(r#\"a.0\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_13.snap index af9f4e8ca..0f7564c77 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_13.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_13.snap @@ -1,15 +1,35 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 110 expression: "crate::tests::parsing_expr_string(r#\"a..0\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", - "", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 2, + }, + Node { + node: "", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_14.snap index 9a5b4cf15..9a683650f 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_14.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_14.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 111 expression: "crate::tests::parsing_expr_string(r#\"a...\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_2.snap index d11e41436..ad5c2dd8d 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_2.snap @@ -1,16 +1,43 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 99 expression: "crate::tests::parsing_expr_string(r#\"a.b.c.\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", - "b", - "c", - "", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "b", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + Node { + node: "c", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: "", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_3.snap index 950ffee84..992848968 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 125 expression: "crate::tests::parsing_expr_string(r#\"''.\"#)" --- Node { @@ -23,7 +22,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_4.snap index 2dba80df1..45ff29d11 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 126 expression: "crate::tests::parsing_expr_string(r#\"''.lower\"#)" --- Node { @@ -23,7 +22,14 @@ Node { attr: Node { node: Identifier { names: [ - "lower", + Node { + node: "lower", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_5.snap index 66985055c..484388876 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 127 expression: "crate::tests::parsing_expr_string(r#\"''.lower().\"#)" --- Node { @@ -29,7 +28,14 @@ Node { attr: Node { node: Identifier { names: [ - "lower", + Node { + node: "lower", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, @@ -63,7 +69,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 11, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_6.snap index 92f80ac92..675b0e19b 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 128 expression: "crate::tests::parsing_expr_string(r#\"a?.\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -25,7 +31,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_7.snap index 8d2f9cf8b..20d302127 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_7.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 129 expression: "crate::tests::parsing_expr_string(r#\"a?.b?.\"#)" --- Node { @@ -13,7 +12,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -28,7 +34,14 @@ Node { attr: Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -52,7 +65,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_8.snap index 0b72f3c28..202dd5709 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_8.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_8.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 130 expression: "crate::tests::parsing_expr_string(r#\"a?.b?.c?.\"#)" --- Node { @@ -16,7 +15,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -31,7 +37,14 @@ Node { attr: Node { node: Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -55,7 +68,14 @@ Node { attr: Node { node: Identifier { names: [ - "c", + Node { + node: "c", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, @@ -79,7 +99,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 9, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_9.snap index 195dc0927..25cc39e66 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_9.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__select_recovery_9.snap @@ -1,13 +1,19 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 106 expression: "crate::tests::parsing_expr_string(r#\"a?\"#)" --- Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_0.snap index d01279057..7acd7bdf8 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_0.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 109 expression: "crate::tests::parsing_expr_string(r#\"a[b 1]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_1.snap index e70e97e1f..6877c8670 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_1.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 110 expression: "crate::tests::parsing_expr_string(r#\"a[1,b]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_10.snap index 387493556..c0b5ac715 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_10.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_10.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 119 expression: "crate::tests::parsing_expr_string(r#\"[0]?.[0]\"#)" --- Node { @@ -41,7 +40,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 5, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_12.snap index c668bfa9f..d68841a4b 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_12.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_12.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 121 expression: "crate::tests::parsing_expr_string(r#\"[0].?[0]\"#)" --- Node { @@ -41,7 +40,14 @@ Node { attr: Node { node: Identifier { names: [ - "", + Node { + node: "", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_2.snap index 9c68da6f3..034165107 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 111 expression: "crate::tests::parsing_expr_string(r#\"a[b;;b]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, @@ -27,7 +33,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_3.snap index 9c5a58260..6e6a2f491 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 112 expression: "crate::tests::parsing_expr_string(r#\"a[b[b]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_4.snap index 413332403..53b3104ed 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_4.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 113 expression: "crate::tests::parsing_expr_string(r#\"a[:::]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_5.snap index 7b1b9eb23..45d2cd7cc 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_5.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 114 expression: "crate::tests::parsing_expr_string(r#\"a[:1:2:]\"#)" --- Node { @@ -10,7 +9,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_6.snap index 6f6c74f97..b250a5626 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__subscript_recovery_6.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 115 expression: "crate::tests::parsing_expr_string(r#\"[][a:b:c:d]\"#)" --- Node { @@ -25,7 +24,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, ], pkgpath: "", ctx: Load, @@ -43,7 +49,14 @@ Node { node: Identifier( Identifier { names: [ - "b", + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, ], pkgpath: "", ctx: Load, @@ -61,7 +74,14 @@ Node { node: Identifier( Identifier { names: [ - "c", + Node { + node: "c", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_0.snap index 5abfb0868..7a0ed7d64 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_0.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 167 expression: "crate::tests::parsing_module_string(r#\"type\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_1.snap index a89a00df3..01dc17c63 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_1.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_1.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 168 expression: "crate::tests::parsing_module_string(r#\"type 'pkg_path'\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_2.snap index bbc096f88..746fbccdb 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_2.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 169 expression: "crate::tests::parsing_module_string(r#\"type pkg_path.\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,8 +14,22 @@ Module { type_name: Node { node: Identifier { names: [ - "pkg_path", - "", + Node { + node: "pkg_path", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 13, + }, + Node { + node: "", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 14, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_3.snap index 4a30a26e2..f30ae2784 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_3.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 170 expression: "crate::tests::parsing_module_string(r#\"type pkg_path[0]\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_4.snap index 3a6b0078c..2ed5a48c0 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_4.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_4.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 171 expression: "crate::tests::parsing_module_string(r#\"type .pkg_path.\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_5.snap index 4af33f775..5441492f3 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_5.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 172 expression: "crate::tests::parsing_module_string(r#\"type pkg_path = \"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,7 +14,14 @@ Module { type_name: Node { node: Identifier { names: [ - "pkg_path", + Node { + node: "pkg_path", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, @@ -32,7 +38,7 @@ Module { line: 1, column: 16, end_line: 1, - end_column: 15, + end_column: 16, }, ty: Node { node: Any, @@ -40,7 +46,7 @@ Module { line: 1, column: 16, end_line: 1, - end_column: 15, + end_column: 16, }, }, ), @@ -48,7 +54,7 @@ Module { line: 1, column: 5, end_line: 1, - end_column: 15, + end_column: 16, }, ], comments: [], diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_6.snap index 1e93cb421..0367449a7 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__type_alias_recovery_6.snap @@ -1,12 +1,11 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 173 expression: "crate::tests::parsing_module_string(r#\"type pkg_path = 'data'\"#)" --- Module { filename: "", pkg: "", - doc: "", + doc: None, name: "", body: [ Node { @@ -15,7 +14,14 @@ Module { type_name: Node { node: Identifier { names: [ - "pkg_path", + Node { + node: "pkg_path", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 13, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_0.snap index 144ed743f..82b3cdaa4 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_0.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_0.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 55 expression: "crate::tests::parsing_expr_string(r#\"!a\"#)" --- Node { @@ -11,7 +10,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_2.snap index 5e246c367..dbe5ca25a 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_2.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_2.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 57 expression: "crate::tests::parsing_expr_string(r#\"not (!a)\"#)" --- Node { @@ -18,7 +17,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_3.snap index 8121da9b4..c564377bc 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_3.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_3.snap @@ -1,6 +1,5 @@ --- source: parser/src/tests/error_recovery.rs -assertion_line: 58 expression: "crate::tests::parsing_expr_string(r#\"! (not a)\"#)" --- Node { @@ -18,7 +17,14 @@ Node { node: Identifier( Identifier { names: [ - "a", + Node { + node: "a", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_5.snap index b18119d8e..b81c0b0e6 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_5.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_5.snap @@ -27,14 +27,19 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_6.snap index 7685fb8e4..4d52ae56e 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_6.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_6.snap @@ -27,14 +27,19 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Sub, - ), + op: Sub, right: Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_7.snap index 6eb7e2113..986f87af6 100644 --- a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_7.snap +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__error_recovery__unary_recovery_7.snap @@ -27,14 +27,19 @@ Node { end_line: 1, end_column: 1, }, - op: Bin( - Add, - ), + op: Add, right: Node { node: Identifier( Identifier { names: [ - "i", + Node { + node: "i", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, ], pkgpath: "", ctx: Load, diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_0.snap new file mode 100644 index 000000000..5eff3ea53 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_0.snap @@ -0,0 +1,74 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1+2+3\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_1.snap new file mode 100644 index 000000000..332c5dcc2 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_1.snap @@ -0,0 +1,101 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1+2*3-4\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Add, + right: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + op: Mul, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + op: Sub, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 4, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_10.snap new file mode 100644 index 000000000..97c2bc28e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_10.snap @@ -0,0 +1,90 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1 + a and b\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Add, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + op: And, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_2.snap new file mode 100644 index 000000000..d401b95d2 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_2.snap @@ -0,0 +1,101 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1+2*3/4\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Add, + right: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + op: Mul, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + op: Div, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 4, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_3.snap new file mode 100644 index 000000000..90eafbf74 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_3.snap @@ -0,0 +1,63 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a or b\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Or, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_4.snap new file mode 100644 index 000000000..2f4355574 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_4.snap @@ -0,0 +1,102 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"x == a or b\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + Eq, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, + }, + op: Or, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_5.snap new file mode 100644 index 000000000..390202c20 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_5.snap @@ -0,0 +1,109 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"22 > 11 and 111 < 222\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 22, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 2, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 11, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 7, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 21, + }, + op: And, + right: Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 111, + ), + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 15, + }, + ops: [ + Lt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 222, + ), + }, + ), + filename: "", + line: 1, + column: 18, + end_line: 1, + end_column: 21, + }, + ], + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 21, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 21, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_6.snap new file mode 100644 index 000000000..cd1469496 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_6.snap @@ -0,0 +1,170 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"int(e.value) > 1 and i == 0\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Compare( + Compare { + left: Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "int", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + args: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "e", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: "value", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 11, + }, + ], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 12, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, + }, + op: And, + right: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ops: [ + Eq, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 26, + end_line: 1, + end_column: 27, + }, + ], + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 27, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_7.snap new file mode 100644 index 000000000..7f48f3a65 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_7.snap @@ -0,0 +1,72 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"key in ['key']\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "key", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ops: [ + In, + ], + comparators: [ + Node { + node: List( + ListExpr { + elts: [ + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "'key'", + value: "key", + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 13, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 14, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_8.snap new file mode 100644 index 000000000..1bb4f300a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_8.snap @@ -0,0 +1,72 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"key not in ['key']\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "key", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ops: [ + NotIn, + ], + comparators: [ + Node { + node: List( + ListExpr { + elts: [ + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "'key'", + value: "key", + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 17, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 18, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 18, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_9.snap new file mode 100644 index 000000000..416b34223 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_9.snap @@ -0,0 +1,109 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1 is 1 and 11 is not 22\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + Is, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 23, + }, + op: And, + right: Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 11, + ), + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 13, + }, + ops: [ + IsNot, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 22, + ), + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 23, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 23, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_with_paren.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_with_paren.snap new file mode 100644 index 000000000..b370c6def --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__binary_expr_with_paren.snap @@ -0,0 +1,112 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1*(2+3)-4\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Mul, + right: Node { + node: Paren( + ParenExpr { + expr: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, + }, + op: Sub, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 4, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_0.snap new file mode 100644 index 000000000..44b34d0df --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_0.snap @@ -0,0 +1,41 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"func0()\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "func0", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + args: [], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_1.snap new file mode 100644 index 000000000..7f53f5a9e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_1.snap @@ -0,0 +1,57 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"func1(1)\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "func1", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_2.snap new file mode 100644 index 000000000..365a54fd2 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_2.snap @@ -0,0 +1,89 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"func2(x=2)\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "func2", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + args: [], + keywords: [ + Node { + node: Keyword { + arg: Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + value: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ), + }, + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 10, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_3.snap new file mode 100644 index 000000000..abe42a4cb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__call_expr_3.snap @@ -0,0 +1,105 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"func3(1,x=2)\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "func3", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + keywords: [ + Node { + node: Keyword { + arg: Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + value: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ), + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 12, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_0.snap new file mode 100644 index 000000000..9368a7f64 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_0.snap @@ -0,0 +1,140 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n \"name\" = {\n \"name\": \"alice\"\n },\n \"gender\" = \"female\"\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 10, + }, + ), + value: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"alice\"", + value: "alice", + }, + ), + filename: "", + line: 3, + column: 16, + end_line: 3, + end_column: 23, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 2, + column: 13, + end_line: 4, + end_column: 5, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 5, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"gender\"", + value: "gender", + }, + ), + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 12, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"female\"", + value: "female", + }, + ), + filename: "", + line: 5, + column: 15, + end_line: 5, + end_column: 23, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 6, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_1.snap new file mode 100644 index 000000000..6c3076fa3 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_1.snap @@ -0,0 +1,140 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n \"name\" = {\n \"name\": \"alice\"\n }\n \"gender\" = \"female\",\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 10, + }, + ), + value: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"alice\"", + value: "alice", + }, + ), + filename: "", + line: 3, + column: 16, + end_line: 3, + end_column: 23, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 2, + column: 13, + end_line: 4, + end_column: 5, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 5, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"gender\"", + value: "gender", + }, + ), + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 12, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"female\"", + value: "female", + }, + ), + filename: "", + line: 5, + column: 15, + end_line: 5, + end_column: 23, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 6, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_2.snap new file mode 100644 index 000000000..dbab80146 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_expr_2.snap @@ -0,0 +1,140 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n \"name\" = {\n \"name\": \"alice\",\n }\n \"gender\" = \"female\"\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 10, + }, + ), + value: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"name\"", + value: "name", + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"alice\"", + value: "alice", + }, + ), + filename: "", + line: 3, + column: 16, + end_line: 3, + end_column: 23, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 2, + column: 13, + end_line: 4, + end_column: 5, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 5, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"gender\"", + value: "gender", + }, + ), + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 12, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"female\"", + value: "female", + }, + ), + filename: "", + line: 5, + column: 15, + end_line: 5, + end_column: 23, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 5, + column: 4, + end_line: 5, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 6, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_0.snap new file mode 100644 index 000000000..8262d6a38 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_0.snap @@ -0,0 +1,107 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n if True:\n a = 1\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 13, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 4, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_1.snap new file mode 100644 index 000000000..3077aef2c --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_1.snap @@ -0,0 +1,172 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n if True:\n a = 1\n else:\n a = 2\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 13, + }, + ], + orelse: Some( + Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 5, + column: 12, + end_line: 5, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 13, + }, + ], + }, + ), + filename: "", + line: 4, + column: 4, + end_line: 6, + end_column: 0, + }, + ), + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 6, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 6, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 6, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_2.snap new file mode 100644 index 000000000..65871797e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_2.snap @@ -0,0 +1,292 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n if True:\n a = 1\n elif x > 1:\n a = 2\n else:\n a = 3\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 3, + column: 12, + end_line: 3, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 13, + }, + ], + orelse: Some( + Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 4, + column: 9, + end_line: 4, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 4, + column: 9, + end_line: 4, + end_column: 10, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 4, + column: 13, + end_line: 4, + end_column: 14, + }, + ], + }, + ), + filename: "", + line: 4, + column: 9, + end_line: 4, + end_column: 14, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 5, + column: 12, + end_line: 5, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 13, + }, + ], + orelse: Some( + Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 7, + column: 8, + end_line: 7, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 7, + column: 8, + end_line: 7, + end_column: 9, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 7, + column: 12, + end_line: 7, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 7, + column: 8, + end_line: 7, + end_column: 13, + }, + ], + }, + ), + filename: "", + line: 6, + column: 4, + end_line: 8, + end_column: 0, + }, + ), + }, + ), + filename: "", + line: 4, + column: 4, + end_line: 6, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 8, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 8, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 8, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_3.snap new file mode 100644 index 000000000..1102a3fe4 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__config_if_expr_3.snap @@ -0,0 +1,145 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n if True:\n if False:\n a = 1\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + items: [ + Node { + node: ConfigEntry { + key: None, + value: Node { + node: ConfigIfEntry( + ConfigIfEntryExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: False, + }, + ), + filename: "", + line: 3, + column: 11, + end_line: 3, + end_column: 16, + }, + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 4, + column: 12, + end_line: 4, + end_column: 13, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 4, + column: 12, + end_line: 4, + end_column: 13, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 4, + column: 16, + end_line: 4, + end_column: 17, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 4, + column: 12, + end_line: 4, + end_column: 17, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 5, + end_column: 0, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 3, + column: 8, + end_line: 5, + end_column: 0, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 5, + end_column: 0, + }, + operation: Union, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 5, + end_column: 0, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 5, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_comp_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_comp_expr.snap new file mode 100644 index 000000000..6ee12cdb1 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_comp_expr.snap @@ -0,0 +1,266 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{k: v + 1 for k, v in {k1 = 1, k2 = 2}}\"####)" +--- +Node { + node: DictComp( + DictComp { + entry: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ), + value: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 9, + }, + operation: Union, + insert_index: -1, + }, + generators: [ + Node { + node: CompClause { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, + Node { + node: Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ], + iter: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k1", + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 25, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 25, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 28, + end_line: 1, + end_column: 29, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 29, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k2", + filename: "", + line: 1, + column: 31, + end_line: 1, + end_column: 33, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 31, + end_line: 1, + end_column: 33, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 36, + end_line: 1, + end_column: 37, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 31, + end_line: 1, + end_column: 37, + }, + ], + }, + ), + filename: "", + line: 1, + column: 22, + end_line: 1, + end_column: 38, + }, + ifs: [], + }, + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 38, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 39, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_expr.snap new file mode 100644 index 000000000..091ef3644 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__dict_expr.snap @@ -0,0 +1,136 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{k0=v0, k1=v1}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k0", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v0", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 6, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k1", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 10, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v1", + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 13, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 13, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 13, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_0.snap new file mode 100644 index 000000000..ad2a5a0cf --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_0.snap @@ -0,0 +1,69 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{a=2}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_1.snap new file mode 100644 index 000000000..9fb8ad972 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_brace_1.snap @@ -0,0 +1,69 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{a=2}}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_0.snap new file mode 100644 index 000000000..5f61ac170 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_0.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[2,3]\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_1.snap new file mode 100644 index 000000000..8540a6417 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_1.snap @@ -0,0 +1,63 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[[2,3]\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_2.snap new file mode 100644 index 000000000..974638b56 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_2.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[2,3]]\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_3.snap new file mode 100644 index 000000000..f00b8be1a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_3.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[2,3\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_4.snap new file mode 100644 index 000000000..1caf60fff --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_4.snap @@ -0,0 +1,18 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[\"####)" +--- +Node { + node: List( + ListExpr { + elts: [], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_5.snap new file mode 100644 index 000000000..aa4f7fe96 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_5.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[\n 1\n 2,\n]\n \"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 3, + column: 4, + end_line: 3, + end_column: 5, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_6.snap new file mode 100644 index 000000000..ca20c1f26 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_6.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[\n 1,2,\n]\n \"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 2, + column: 6, + end_line: 2, + end_column: 7, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 3, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_7.snap new file mode 100644 index 000000000..9ae683dfa --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_bracket_7.snap @@ -0,0 +1,49 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[\n 1,2,\n\n \"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 2, + column: 6, + end_line: 2, + end_column: 7, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 4, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_0.snap new file mode 100644 index 000000000..bcb6bdaff --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_0.snap @@ -0,0 +1,80 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"({a=2}\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ], + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_1.snap new file mode 100644 index 000000000..909f52bcf --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_1.snap @@ -0,0 +1,91 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"({a=(2}\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: Paren( + ParenExpr { + expr: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + ], + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_2.snap new file mode 100644 index 000000000..086df811c --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_2.snap @@ -0,0 +1,83 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{a=[2]\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ), + value: Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_3.snap new file mode 100644 index 000000000..47ac7d93d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_3.snap @@ -0,0 +1,83 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[{a=2}\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ], + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_4.snap new file mode 100644 index 000000000..de2f05aab --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_4.snap @@ -0,0 +1,94 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"({a=[2}\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + value: Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 7, + }, + ], + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_5.snap new file mode 100644 index 000000000..e69e0ea93 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_5.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_6.snap new file mode 100644 index 000000000..f65835076 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_6.snap @@ -0,0 +1,69 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n a = 1\n}\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 8, + end_line: 2, + end_column: 9, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 9, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 3, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_7.snap new file mode 100644 index 000000000..d027279ca --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_delim_7.snap @@ -0,0 +1,102 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"{\n a = 1\n\"####)" +--- +Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ), + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 2, + column: 8, + end_line: 2, + end_column: 9, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 9, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 10, + }, + ), + value: Node { + node: Missing( + MissingExpr, + ), + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 10, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 10, + end_line: 2, + end_column: 10, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 2, + end_column: 10, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_0.snap new file mode 100644 index 000000000..6c6715bc5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_0.snap @@ -0,0 +1,58 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"(2+3)\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_1.snap new file mode 100644 index 000000000..5a29b6407 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_1.snap @@ -0,0 +1,69 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"((2+3)\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Paren( + ParenExpr { + expr: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_2.snap new file mode 100644 index 000000000..c353720ce --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__expr_with_paren_2.snap @@ -0,0 +1,58 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"(2+3))\"####)" +--- +Node { + node: Paren( + ParenExpr { + expr: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__if_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__if_expr.snap new file mode 100644 index 000000000..6d43c32c0 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__if_expr.snap @@ -0,0 +1,69 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1 if true else 2\"####)" +--- +Node { + node: If( + IfExpr { + body: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + cond: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "true", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 9, + }, + orelse: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 16, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_0.snap new file mode 100644 index 000000000..0d919f9bc --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_0.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/expr.rs +assertion_line: 79 +expression: "crate::tests::parsing_expr_string(r####\"lambda {}\"####)" +--- +Node { + node: Lambda( + LambdaExpr { + args: None, + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_1.snap new file mode 100644 index 000000000..f6415f382 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_1.snap @@ -0,0 +1,59 @@ +--- +source: parser/src/tests/expr.rs +assertion_line: 80 +expression: "crate::tests::parsing_expr_string(r####\"lambda x {}\"####)" +--- +Node { + node: Lambda( + LambdaExpr { + args: Some( + Node { + node: Arguments { + args: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + defaults: [ + None, + ], + ty_list: [ + None, + ], + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ), + body: [], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_2.snap new file mode 100644 index 000000000..0364c43ef --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_2.snap @@ -0,0 +1,118 @@ +--- +source: parser/src/tests/expr.rs +assertion_line: 81 +expression: "crate::tests::parsing_expr_string(r####\"lambda x: int -> int {x}\"####)" +--- +Node { + node: Lambda( + LambdaExpr { + args: Some( + Node { + node: Arguments { + args: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + defaults: [ + None, + ], + ty_list: [ + Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 13, + }, + ), + ], + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 13, + }, + ), + body: [ + Node { + node: Expr( + ExprStmt { + exprs: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 22, + end_line: 1, + end_column: 23, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 22, + end_line: 1, + end_column: 23, + }, + ], + }, + ), + filename: "", + line: 1, + column: 22, + end_line: 1, + end_column: 23, + }, + ], + return_ty: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 20, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 24, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_3.snap new file mode 100644 index 000000000..db438a698 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__lambda_expr_3.snap @@ -0,0 +1,184 @@ +--- +source: parser/src/tests/expr.rs +assertion_line: 82 +expression: "crate::tests::parsing_expr_string(r####\"lambda {\n if True:\n _a = 1\n else:\n _a = 2\n _a\n}\"####)" +--- +Node { + node: Lambda( + LambdaExpr { + args: None, + body: [ + Node { + node: If( + IfStmt { + body: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "_a", + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 10, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 3, + column: 13, + end_line: 3, + end_column: 14, + }, + ty: None, + }, + ), + filename: "", + line: 3, + column: 8, + end_line: 3, + end_column: 14, + }, + ], + cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 2, + column: 7, + end_line: 2, + end_column: 11, + }, + orelse: [ + Node { + node: Assign( + AssignStmt { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "_a", + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 10, + }, + ], + pkgpath: "", + ctx: Store, + }, + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 10, + }, + ], + value: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 5, + column: 13, + end_line: 5, + end_column: 14, + }, + ty: None, + }, + ), + filename: "", + line: 5, + column: 8, + end_line: 5, + end_column: 14, + }, + ], + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 6, + end_column: 4, + }, + Node { + node: Expr( + ExprStmt { + exprs: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "_a", + filename: "", + line: 6, + column: 4, + end_line: 6, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 6, + column: 4, + end_line: 6, + end_column: 6, + }, + ], + }, + ), + filename: "", + line: 6, + column: 4, + end_line: 6, + end_column: 6, + }, + ], + return_ty: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 7, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__line_continue.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__line_continue.snap new file mode 100644 index 000000000..a563e4cd8 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__line_continue.snap @@ -0,0 +1,47 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1 + \\\n2\n\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 2, + column: 0, + end_line: 2, + end_column: 1, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 2, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_0.snap new file mode 100644 index 000000000..c6f7cc855 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_0.snap @@ -0,0 +1,160 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[x ** 2 for x in [1, 2, 3]]\"####)" +--- +Node { + node: ListComp( + ListComp { + elt: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + op: Pow, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 7, + }, + generators: [ + Node { + node: CompClause { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, + ], + iter: Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 18, + end_line: 1, + end_column: 19, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 25, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 26, + }, + ifs: [], + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 26, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_1.snap new file mode 100644 index 000000000..724c18610 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_comp_expr_1.snap @@ -0,0 +1,188 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[i for i in [1, 2, 3] if i > 2]\"####)" +--- +Node { + node: ListComp( + ListComp { + elt: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + generators: [ + Node { + node: CompClause { + targets: [ + Node { + node: Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + iter: Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 17, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 19, + end_line: 1, + end_column: 20, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 21, + }, + ifs: [ + Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 26, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 26, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 29, + end_line: 1, + end_column: 30, + }, + ], + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 30, + }, + ], + }, + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 30, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 31, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_0.snap new file mode 100644 index 000000000..356ee9454 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_0.snap @@ -0,0 +1,64 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[1, 2, 3]\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_1.snap new file mode 100644 index 000000000..3401d3c7f --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__list_expr_1.snap @@ -0,0 +1,90 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"[1, if True: 2, 3]\"####)" +--- +Node { + node: List( + ListExpr { + elts: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + Node { + node: ListIfItem( + ListIfItemExpr { + if_cond: Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 11, + }, + exprs: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ], + orelse: None, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 14, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 16, + end_line: 1, + end_column: 17, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 18, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_0.snap new file mode 100644 index 000000000..6f3ba2059 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_0.snap @@ -0,0 +1,75 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"0 < a < 100\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + Lt, + Lt, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 100, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_1.snap new file mode 100644 index 000000000..a5f7197a3 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_1.snap @@ -0,0 +1,110 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"0 < a < 100 + a\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + Lt, + Lt, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 100, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + op: Add, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 15, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 15, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_2.snap new file mode 100644 index 000000000..b8df91bfb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_2.snap @@ -0,0 +1,75 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"100 > a > 0\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 100, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ops: [ + Gt, + Gt, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_3.snap new file mode 100644 index 000000000..1116355bb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_3.snap @@ -0,0 +1,110 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"100 + a > a > 0\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 100, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + op: Add, + right: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, + }, + ops: [ + Gt, + Gt, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 15, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 15, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_4.snap new file mode 100644 index 000000000..4d1179f19 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_4.snap @@ -0,0 +1,67 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a is b\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + Is, + ], + comparators: [ + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_5.snap new file mode 100644 index 000000000..45e278b7b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_5.snap @@ -0,0 +1,56 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a is not True\"####)" +--- +Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ops: [ + IsNot, + ], + comparators: [ + Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 13, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 13, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_6.snap new file mode 100644 index 000000000..b848314b7 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__logic_expr_6.snap @@ -0,0 +1,158 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"not False or a > 0 and b is True\"####)" +--- +Node { + node: Binary( + BinaryExpr { + left: Node { + node: Unary( + UnaryExpr { + op: Not, + operand: Node { + node: NameConstantLit( + NameConstantLit { + value: False, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 9, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, + }, + op: Or, + right: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ], + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 32, + }, + op: And, + right: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 24, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 24, + }, + ops: [ + Is, + ], + comparators: [ + Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 28, + end_line: 1, + end_column: 32, + }, + ], + }, + ), + filename: "", + line: 1, + column: 23, + end_line: 1, + end_column: 32, + }, + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 32, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 32, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_0.snap new file mode 100644 index 000000000..7de5ef740 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_0.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"Undefined\")" +--- +Node { + node: NameConstantLit( + NameConstantLit { + value: Undefined, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_1.snap new file mode 100644 index 000000000..7f5c7ef9d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_1.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"None\")" +--- +Node { + node: NameConstantLit( + NameConstantLit { + value: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_2.snap new file mode 100644 index 000000000..2da8eaa4c --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_2.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"True\")" +--- +Node { + node: NameConstantLit( + NameConstantLit { + value: True, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_3.snap new file mode 100644 index 000000000..2f6bf66cc --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__named_literal_expr_3.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"False\")" +--- +Node { + node: NameConstantLit( + NameConstantLit { + value: False, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__nonstring_literal_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__nonstring_literal_expr.snap new file mode 100644 index 000000000..565de3ff4 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__nonstring_literal_expr.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1234\"####)" +--- +Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1234, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__number_bin_suffix_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__number_bin_suffix_expr.snap new file mode 100644 index 000000000..5082423ff --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__number_bin_suffix_expr.snap @@ -0,0 +1,22 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"1234Ki\"####)" +--- +Node { + node: NumberLit( + NumberLit { + binary_suffix: Some( + Ki, + ), + value: Int( + 1234, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_0.snap new file mode 100644 index 000000000..9de6c12ec --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_0.snap @@ -0,0 +1,75 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"'${123+200}'\"####)" +--- +Node { + node: JoinedString( + JoinedString { + is_long_string: false, + values: [ + Node { + node: FormattedValue( + FormattedValue { + is_long_string: false, + value: Node { + node: Binary( + BinaryExpr { + left: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 123, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 6, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 200, + ), + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 10, + }, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + format_spec: None, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 10, + }, + ], + raw_value: "'${123+200}'", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 12, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_1.snap new file mode 100644 index 000000000..5fa01f670 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__parse_joined_string_1.snap @@ -0,0 +1,111 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"'abc${a+1}cde'\"####)" +--- +Node { + node: JoinedString( + JoinedString { + is_long_string: false, + values: [ + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "abc", + value: "abc", + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 1, + }, + Node { + node: FormattedValue( + FormattedValue { + is_long_string: false, + value: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + format_spec: None, + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "cde", + value: "cde", + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 1, + }, + ], + raw_value: "'abc${a+1}cde'", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_0.snap new file mode 100644 index 000000000..a028192b6 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_0.snap @@ -0,0 +1,44 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a.b.c\"####)" +--- +Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + Node { + node: "b", + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + Node { + node: "c", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_1.snap new file mode 100644 index 000000000..df2ad88f0 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_1.snap @@ -0,0 +1,82 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"'{}'.format(1)\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Selector( + SelectorExpr { + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "'{}'", + value: "{}", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, + }, + attr: Node { + node: Identifier { + names: [ + Node { + node: "format", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 11, + }, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 11, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 13, + }, + ], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_2.snap new file mode 100644 index 000000000..45416f506 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__primary_expr_2.snap @@ -0,0 +1,104 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"str(1).isdigit()\"####)" +--- +Node { + node: Call( + CallExpr { + func: Node { + node: Selector( + SelectorExpr { + value: Node { + node: Call( + CallExpr { + func: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "str", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + attr: Node { + node: Identifier { + names: [ + Node { + node: "isdigit", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 14, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 14, + }, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, + }, + args: [], + keywords: [], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 16, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_0.snap new file mode 100644 index 000000000..2da80a01e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_0.snap @@ -0,0 +1,119 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"all x in collection {x > 0}\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "collection", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + op: All, + test: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 26, + }, + ], + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 26, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_1.snap new file mode 100644 index 000000000..2191519ad --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_1.snap @@ -0,0 +1,119 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"any y in collection {y < 0}\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "collection", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "y", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + op: Any, + test: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "y", + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ops: [ + Lt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 26, + }, + ], + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 26, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_2.snap new file mode 100644 index 000000000..e969f0cc3 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_2.snap @@ -0,0 +1,115 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"map x in collection {x + 1}\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "collection", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 19, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + op: Map, + test: Node { + node: Binary( + BinaryExpr { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 22, + }, + op: Add, + right: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 26, + }, + }, + ), + filename: "", + line: 1, + column: 21, + end_line: 1, + end_column: 26, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 27, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_3.snap new file mode 100644 index 000000000..272131f54 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_3.snap @@ -0,0 +1,119 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"filter x in collection {x > 1}\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "collection", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 22, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + op: Filter, + test: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 25, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 25, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 28, + end_line: 1, + end_column: 29, + }, + ], + }, + ), + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 29, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 30, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_4.snap new file mode 100644 index 000000000..272131f54 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_4.snap @@ -0,0 +1,119 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"filter x in collection {x > 1}\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "collection", + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 22, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 22, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + op: Filter, + test: Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "x", + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 25, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 25, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 28, + end_line: 1, + end_column: 29, + }, + ], + }, + ), + filename: "", + line: 1, + column: 24, + end_line: 1, + end_column: 29, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 30, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_5.snap new file mode 100644 index 000000000..b80e8af80 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_5.snap @@ -0,0 +1,213 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"map i, e in [{k1 = \"v1\", k2 = \"v2\"}] { e }\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: List( + ListExpr { + elts: [ + Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k1", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 16, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 16, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"v1\"", + value: "v1", + }, + ), + filename: "", + line: 1, + column: 19, + end_line: 1, + end_column: 23, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 23, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k2", + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 27, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 27, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"v2\"", + value: "v2", + }, + ), + filename: "", + line: 1, + column: 30, + end_line: 1, + end_column: 34, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 34, + }, + ], + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 35, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 36, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: Identifier { + names: [ + Node { + node: "e", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + op: Map, + test: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "e", + filename: "", + line: 1, + column: 39, + end_line: 1, + end_column: 40, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 39, + end_line: 1, + end_column: 40, + }, + if_cond: None, + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 42, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_6.snap new file mode 100644 index 000000000..6112b0f13 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__quant_expr_6.snap @@ -0,0 +1,268 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"map i, e in [{k1 = \"v1\", k2 = \"v2\"}] { e if i > 0 }\"####)" +--- +Node { + node: Quant( + QuantExpr { + target: Node { + node: List( + ListExpr { + elts: [ + Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k1", + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 16, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 16, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"v1\"", + value: "v1", + }, + ), + filename: "", + line: 1, + column: 19, + end_line: 1, + end_column: 23, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 23, + }, + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k2", + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 27, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 27, + }, + ), + value: Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"v2\"", + value: "v2", + }, + ), + filename: "", + line: 1, + column: 30, + end_line: 1, + end_column: 34, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 25, + end_line: 1, + end_column: 34, + }, + ], + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 35, + }, + ], + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 36, + }, + variables: [ + Node { + node: Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + Node { + node: Identifier { + names: [ + Node { + node: "e", + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 8, + }, + ], + op: Map, + test: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "e", + filename: "", + line: 1, + column: 39, + end_line: 1, + end_column: 40, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 39, + end_line: 1, + end_column: 40, + }, + if_cond: Some( + Node { + node: Compare( + Compare { + left: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "i", + filename: "", + line: 1, + column: 44, + end_line: 1, + end_column: 45, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 44, + end_line: 1, + end_column: 45, + }, + ops: [ + Gt, + ], + comparators: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 48, + end_line: 1, + end_column: 49, + }, + ], + }, + ), + filename: "", + line: 1, + column: 44, + end_line: 1, + end_column: 49, + }, + ), + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 51, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_0.snap new file mode 100644 index 000000000..ca2d929a2 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_0.snap @@ -0,0 +1,51 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"Schema {}\"####)" +--- +Node { + node: Schema( + SchemaExpr { + name: Node { + node: Identifier { + names: [ + Node { + node: "Schema", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + args: [], + kwargs: [], + config: Node { + node: Config( + ConfigExpr { + items: [], + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 9, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 9, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_1.snap new file mode 100644 index 000000000..e73ebd8fd --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_1.snap @@ -0,0 +1,111 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"Schema {k=v}\"####)" +--- +Node { + node: Schema( + SchemaExpr { + name: Node { + node: Identifier { + names: [ + Node { + node: "Schema", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + args: [], + kwargs: [], + config: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 11, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 11, + }, + ], + }, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 12, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 12, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_2.snap new file mode 100644 index 000000000..8d63ad2c7 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_2.snap @@ -0,0 +1,111 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"Schema () {k=v}\"####)" +--- +Node { + node: Schema( + SchemaExpr { + name: Node { + node: Identifier { + names: [ + Node { + node: "Schema", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + args: [], + kwargs: [], + config: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 13, + end_line: 1, + end_column: 14, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 14, + }, + ], + }, + ), + filename: "", + line: 1, + column: 10, + end_line: 1, + end_column: 15, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 15, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_3.snap new file mode 100644 index 000000000..01fcebee5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_3.snap @@ -0,0 +1,142 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"Schema (1, 2) {k=v}\"####)" +--- +Node { + node: Schema( + SchemaExpr { + name: Node { + node: Identifier { + names: [ + Node { + node: "Schema", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, + ], + kwargs: [], + config: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 16, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 18, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 1, + column: 15, + end_line: 1, + end_column: 18, + }, + ], + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 1, + end_column: 19, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 19, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_4.snap new file mode 100644 index 000000000..9fa625d2e --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__schema_expr_4.snap @@ -0,0 +1,142 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"Schema (1, 2) {\n k=v\n}\"####)" +--- +Node { + node: Schema( + SchemaExpr { + name: Node { + node: Identifier { + names: [ + Node { + node: "Schema", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + args: [ + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 8, + end_line: 1, + end_column: 9, + }, + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 11, + end_line: 1, + end_column: 12, + }, + ], + kwargs: [], + config: Node { + node: Config( + ConfigExpr { + items: [ + Node { + node: ConfigEntry { + key: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "k", + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 5, + }, + ), + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "v", + filename: "", + line: 2, + column: 6, + end_line: 2, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 2, + column: 6, + end_line: 2, + end_column: 7, + }, + operation: Override, + insert_index: -1, + }, + filename: "", + line: 2, + column: 4, + end_line: 2, + end_column: 7, + }, + ], + }, + ), + filename: "", + line: 1, + column: 14, + end_line: 3, + end_column: 1, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 3, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_0.snap new file mode 100644 index 000000000..896509e1b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_0.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"1\\n\")" +--- +Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_1.snap new file mode 100644 index 000000000..2e7abca86 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__smoke_test_parsing_expr_1.snap @@ -0,0 +1,19 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(\"\\\"1\\\"\\n\")" +--- +Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"1\"", + value: "1", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_0.snap new file mode 100644 index 000000000..6c8c37538 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_0.snap @@ -0,0 +1,19 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"'1234'\"####)" +--- +Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "'1234'", + value: "1234", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_1.snap new file mode 100644 index 000000000..1f108e406 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_1.snap @@ -0,0 +1,19 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"\"1234\"\"####)" +--- +Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"1234\"", + value: "1234", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_2.snap new file mode 100644 index 000000000..a5f3e2e53 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__string_literal_expr_2.snap @@ -0,0 +1,19 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"\"1234\\n\"\"####)" +--- +Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"1234\\n\"", + value: "1234\n", + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_0.snap new file mode 100644 index 000000000..3752cbeac --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_0.snap @@ -0,0 +1,61 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[0]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + lower: None, + upper: None, + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_1.snap new file mode 100644 index 000000000..9b32e231a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_1.snap @@ -0,0 +1,60 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"b[\"k\"]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "b", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: Some( + Node { + node: StringLit( + StringLit { + is_long_string: false, + raw_value: "\"k\"", + value: "k", + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ), + lower: None, + upper: None, + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_10.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_10.snap new file mode 100644 index 000000000..ce08b1682 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_10.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[::-1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: None, + upper: None, + step: Some( + Node { + node: Unary( + UnaryExpr { + op: USub, + operand: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 6, + }, + ), + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_11.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_11.snap new file mode 100644 index 000000000..a5cc8ab34 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_11.snap @@ -0,0 +1,77 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1::2]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: None, + step: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ), + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_12.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_12.snap new file mode 100644 index 000000000..f6cfe4beb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_12.snap @@ -0,0 +1,77 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[:2:1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: None, + upper: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ), + step: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + ), + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_13.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_13.snap new file mode 100644 index 000000000..61b668cca --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_13.snap @@ -0,0 +1,77 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1:2:]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 2, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_14.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_14.snap new file mode 100644 index 000000000..001416f3a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_14.snap @@ -0,0 +1,93 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1:3:1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 3, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + ), + step: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 7, + }, + ), + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_2.snap new file mode 100644 index 000000000..1c4f15312 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_2.snap @@ -0,0 +1,61 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"c?[1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "c", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ), + lower: None, + upper: None, + step: None, + ctx: Load, + has_question: true, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_3.snap new file mode 100644 index 000000000..a288ead99 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_3.snap @@ -0,0 +1,61 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1:]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: None, + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_4.snap new file mode 100644 index 000000000..d65b89649 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_4.snap @@ -0,0 +1,73 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[:-1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: None, + upper: Some( + Node { + node: Unary( + UnaryExpr { + op: USub, + operand: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 5, + }, + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 5, + }, + ), + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_5.snap new file mode 100644 index 000000000..d095deb1f --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_5.snap @@ -0,0 +1,85 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1:len]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: Some( + Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "len", + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ), + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 8, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_6.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_6.snap new file mode 100644 index 000000000..16596547b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_6.snap @@ -0,0 +1,89 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[0:-1]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: Some( + Node { + node: Unary( + UnaryExpr { + op: USub, + operand: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 6, + }, + }, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 6, + }, + ), + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_7.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_7.snap new file mode 100644 index 000000000..efdc7b695 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_7.snap @@ -0,0 +1,45 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[::]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: None, + upper: None, + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_8.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_8.snap new file mode 100644 index 000000000..6a16c990c --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_8.snap @@ -0,0 +1,61 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[1::]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 3, + }, + ), + upper: None, + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_9.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_9.snap new file mode 100644 index 000000000..14164675c --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__subscript_expr_9.snap @@ -0,0 +1,61 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"a[:0:]\"####)" +--- +Node { + node: Subscript( + Subscript { + value: Node { + node: Identifier( + Identifier { + names: [ + Node { + node: "a", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 1, + }, + index: None, + lower: None, + upper: Some( + Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 0, + ), + }, + ), + filename: "", + line: 1, + column: 3, + end_line: 1, + end_column: 4, + }, + ), + step: None, + ctx: Load, + has_question: false, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__unary_expr.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__unary_expr.snap new file mode 100644 index 000000000..174b7eeec --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__expr__unary_expr.snap @@ -0,0 +1,32 @@ +--- +source: parser/src/tests/expr.rs +expression: "crate::tests::parsing_expr_string(r####\"+1\"####)" +--- +Node { + node: Unary( + UnaryExpr { + op: UAdd, + operand: Node { + node: NumberLit( + NumberLit { + binary_suffix: None, + value: Int( + 1, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 2, + }, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 2, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_1.snap new file mode 100644 index 000000000..7b8712908 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_1.snap @@ -0,0 +1,102 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-01.k\")" +--- +{ + "filename": "assert-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-01.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 8 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 8 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "assert-01.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 8 + }, + "if_cond": null, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"msg\"", + "value": "msg" + }, + "filename": "assert-01.k", + "line": 2, + "column": 10, + "end_line": 2, + "end_column": 15 + } + }, + "filename": "assert-01.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 15 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-01.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 11 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-01.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 11 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_2.snap new file mode 100644 index 000000000..e24e18208 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_2.snap @@ -0,0 +1,202 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-02.k\")" +--- +{ + "filename": "assert-02.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-02.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 11 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 11 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-02.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 8 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-02.k", + "line": 2, + "column": 12, + "end_line": 2, + "end_column": 13 + } + ] + }, + "filename": "assert-02.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 13 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-02.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 13 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_x", + "filename": "assert-02.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-02.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-02.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 16 + }, + "ty": null + }, + "filename": "assert-02.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 16 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-02.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-02.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-02.k", + "line": 4, + "column": 13, + "end_line": 4, + "end_column": 24 + } + ] + }, + "filename": "assert-02.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 24 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-02.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 24 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_3.snap new file mode 100644 index 000000000..59faefaf9 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_3.snap @@ -0,0 +1,274 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-03.k\")" +--- +{ + "filename": "assert-03.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-03.k", + "line": 2, + "column": 11, + "end_line": 2, + "end_column": 15 + }, + "if_cond": null, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"Error messgae\"", + "value": "Error messgae" + }, + "filename": "assert-03.k", + "line": 2, + "column": 17, + "end_line": 2, + "end_column": 32 + } + }, + "filename": "assert-03.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 32 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-03.k", + "line": 3, + "column": 11, + "end_line": 3, + "end_column": 12 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-03.k", + "line": 3, + "column": 16, + "end_line": 3, + "end_column": 17 + } + ] + }, + "filename": "assert-03.k", + "line": 3, + "column": 11, + "end_line": 3, + "end_column": 17 + }, + "if_cond": null, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"\"", + "value": "" + }, + "filename": "assert-03.k", + "line": 3, + "column": 19, + "end_line": 3, + "end_column": 21 + } + }, + "filename": "assert-03.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 21 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_x", + "filename": "assert-03.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-03.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-03.k", + "line": 4, + "column": 9, + "end_line": 4, + "end_column": 20 + }, + "ty": null + }, + "filename": "assert-03.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 20 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-03.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 13 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-03.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 13 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-03.k", + "line": 5, + "column": 17, + "end_line": 5, + "end_column": 28 + } + ] + }, + "filename": "assert-03.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 28 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-03.k", + "line": 5, + "column": 4, + "end_line": 5, + "end_column": 28 + } + ], + "cond": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-03.k", + "line": 1, + "column": 3, + "end_line": 1, + "end_column": 7 + }, + "orelse": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "False" + }, + "filename": "assert-03.k", + "line": 7, + "column": 11, + "end_line": 7, + "end_column": 16 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-03.k", + "line": 7, + "column": 4, + "end_line": 7, + "end_column": 16 + } + ] + }, + "filename": "assert-03.k", + "line": 1, + "column": 0, + "end_line": 8, + "end_column": 1 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_0.snap new file mode 100644 index 000000000..0495e654d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_0.snap @@ -0,0 +1,245 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-if-0.k\")" +--- +{ + "filename": "assert-if-0.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-if-0.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 11 + }, + "if_cond": null, + "msg": null + }, + "filename": "assert-if-0.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 11 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-0.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 8 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-0.k", + "line": 2, + "column": 12, + "end_line": 2, + "end_column": 13 + } + ] + }, + "filename": "assert-if-0.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 13 + }, + "if_cond": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-if-0.k", + "line": 2, + "column": 17, + "end_line": 2, + "end_column": 21 + }, + "msg": null + }, + "filename": "assert-if-0.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 21 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_x", + "filename": "assert-if-0.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-if-0.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-0.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 16 + }, + "ty": null + }, + "filename": "assert-if-0.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 16 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-0.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 13, + "end_line": 4, + "end_column": 24 + } + ] + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 24 + }, + "if_cond": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-0.k", + "line": 4, + "column": 28, + "end_line": 4, + "end_column": 30 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 28, + "end_line": 4, + "end_column": 30 + }, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"_x need to be 'good case'\"", + "value": "_x need to be 'good case'" + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 32, + "end_line": 4, + "end_column": 59 + } + }, + "filename": "assert-if-0.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 59 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_1.snap new file mode 100644 index 000000000..110f9d077 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_1.snap @@ -0,0 +1,266 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-if-1.k\")" +--- +{ + "filename": "assert-if-1.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-if-1.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 11 + }, + "if_cond": { + "node": { + "type": "NameConstantLit", + "value": "False" + }, + "filename": "assert-if-1.k", + "line": 1, + "column": 15, + "end_line": 1, + "end_column": 20 + }, + "msg": null + }, + "filename": "assert-if-1.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 20 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-1.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 8 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-1.k", + "line": 2, + "column": 12, + "end_line": 2, + "end_column": 13 + } + ] + }, + "filename": "assert-if-1.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 13 + }, + "if_cond": { + "node": { + "type": "NameConstantLit", + "value": "False" + }, + "filename": "assert-if-1.k", + "line": 2, + "column": 17, + "end_line": 2, + "end_column": 22 + }, + "msg": null + }, + "filename": "assert-if-1.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 22 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_x", + "filename": "assert-if-1.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-if-1.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 2 + } + ], + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-1.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 16 + }, + "ty": null + }, + "filename": "assert-if-1.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 16 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-1.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 9 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 13, + "end_line": 4, + "end_column": 24 + } + ] + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 7, + "end_line": 4, + "end_column": 24 + }, + "if_cond": { + "node": { + "type": "Unary", + "op": "Not", + "operand": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-1.k", + "line": 4, + "column": 32, + "end_line": 4, + "end_column": 34 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 32, + "end_line": 4, + "end_column": 34 + } + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 28, + "end_line": 4, + "end_column": 34 + }, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"_x need to be 'good case'\"", + "value": "_x need to be 'good case'" + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 36, + "end_line": 4, + "end_column": 63 + } + }, + "filename": "assert-if-1.k", + "line": 4, + "column": 0, + "end_line": 4, + "end_column": 63 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_2.snap new file mode 100644 index 000000000..592458159 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assert_if_2.snap @@ -0,0 +1,374 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assert-if-2.k\")" +--- +{ + "filename": "assert-if-2.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "Data", + "filename": "assert-if-2.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 11 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "assert-if-2.k", + "line": 2, + "column": 11, + "end_line": 2, + "end_column": 15 + }, + "if_cond": { + "node": { + "type": "NameConstantLit", + "value": "False" + }, + "filename": "assert-if-2.k", + "line": 2, + "column": 19, + "end_line": 2, + "end_column": 24 + }, + "msg": null + }, + "filename": "assert-if-2.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 24 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-2.k", + "line": 3, + "column": 11, + "end_line": 3, + "end_column": 12 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assert-if-2.k", + "line": 3, + "column": 16, + "end_line": 3, + "end_column": 17 + } + ] + }, + "filename": "assert-if-2.k", + "line": 3, + "column": 11, + "end_line": 3, + "end_column": 17 + }, + "if_cond": { + "node": { + "type": "NameConstantLit", + "value": "False" + }, + "filename": "assert-if-2.k", + "line": 3, + "column": 21, + "end_line": 3, + "end_column": 26 + }, + "msg": null + }, + "filename": "assert-if-2.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 26 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_x", + "filename": "assert-if-2.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-if-2.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-2.k", + "line": 4, + "column": 9, + "end_line": 4, + "end_column": 20 + }, + "ty": null + }, + "filename": "assert-if-2.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 20 + }, + { + "node": { + "type": "Assert", + "test": { + "node": { + "type": "Compare", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-2.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 13 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 13 + }, + "ops": [ + "Eq" + ], + "comparators": [ + { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"good case\"", + "value": "good case" + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 17, + "end_line": 5, + "end_column": 28 + } + ] + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 28 + }, + "if_cond": { + "node": { + "type": "Unary", + "op": "Not", + "operand": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_x", + "filename": "assert-if-2.k", + "line": 5, + "column": 36, + "end_line": 5, + "end_column": 38 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 36, + "end_line": 5, + "end_column": 38 + } + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 32, + "end_line": 5, + "end_column": 38 + }, + "msg": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"_x need to be 'good case'\"", + "value": "_x need to be 'good case'" + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 40, + "end_line": 5, + "end_column": 67 + } + }, + "filename": "assert-if-2.k", + "line": 5, + "column": 4, + "end_line": 5, + "end_column": 67 + } + ], + "decorators": [], + "checks": [], + "index_signature": null + }, + "filename": "assert-if-2.k", + "line": 1, + "column": 0, + "end_line": 7, + "end_column": 0 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "data", + "filename": "assert-if-2.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 4 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assert-if-2.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 4 + } + ], + "value": { + "node": { + "type": "Schema", + "name": { + "node": { + "names": [ + { + "node": "Data", + "filename": "assert-if-2.k", + "line": 7, + "column": 7, + "end_line": 7, + "end_column": 11 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "assert-if-2.k", + "line": 7, + "column": 7, + "end_line": 7, + "end_column": 11 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "type": "Config", + "items": [] + }, + "filename": "assert-if-2.k", + "line": 7, + "column": 12, + "end_line": 7, + "end_column": 14 + } + }, + "filename": "assert-if-2.k", + "line": 7, + "column": 7, + "end_line": 7, + "end_column": 14 + }, + "ty": null + }, + "filename": "assert-if-2.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 14 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assign_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assign_1.snap new file mode 100644 index 000000000..56467d8a7 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__assign_1.snap @@ -0,0 +1,238 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/assign-01.k\")" +--- +{ + "filename": "assign-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "assign-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assign-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assign-01.k", + "line": 1, + "column": 2, + "end_line": 1, + "end_column": 3 + }, + "ty": null + }, + "filename": "assign-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 3 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "b", + "filename": "assign-01.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assign-01.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "assign-01.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 5 + }, + "op": "Add", + "right": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "assign-01.k", + "line": 2, + "column": 8, + "end_line": 2, + "end_column": 9 + } + }, + "filename": "assign-01.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 9 + }, + "ty": null + }, + "filename": "assign-01.k", + "line": 2, + "column": 0, + "end_line": 2, + "end_column": 9 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "c", + "filename": "assign-01.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "assign-01.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "assign-01.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 5 + }, + "op": "Add", + "right": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "assign-01.k", + "line": 3, + "column": 8, + "end_line": 3, + "end_column": 9 + }, + "op": "Mul", + "right": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 3 + } + }, + "filename": "assign-01.k", + "line": 3, + "column": 10, + "end_line": 3, + "end_column": 11 + } + }, + "filename": "assign-01.k", + "line": 3, + "column": 8, + "end_line": 3, + "end_column": 11 + } + }, + "filename": "assign-01.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 11 + }, + "ty": null + }, + "filename": "assign-01.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 11 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_1.snap new file mode 100644 index 000000000..af4a785c8 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_1.snap @@ -0,0 +1,58 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/config_expr-01.k\")" +--- +{ + "filename": "config_expr-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "config", + "filename": "config_expr-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "config_expr-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "Config", + "items": [] + }, + "filename": "config_expr-01.k", + "line": 1, + "column": 9, + "end_line": 2, + "end_column": 1 + }, + "ty": null + }, + "filename": "config_expr-01.k", + "line": 1, + "column": 0, + "end_line": 2, + "end_column": 1 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_2.snap new file mode 100644 index 000000000..c0f8a8faf --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_2.snap @@ -0,0 +1,155 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/config_expr-02.k\")" +--- +{ + "filename": "config_expr-02.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "config", + "filename": "config_expr-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "config_expr-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "k1", + "filename": "config_expr-02.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-02.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 6 + }, + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 111 + } + }, + "filename": "config_expr-02.k", + "line": 2, + "column": 9, + "end_line": 2, + "end_column": 12 + }, + "operation": "Override", + "insert_index": -1 + }, + "filename": "config_expr-02.k", + "line": 2, + "column": 4, + "end_line": 2, + "end_column": 12 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "k2", + "filename": "config_expr-02.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-02.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 6 + }, + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 222 + } + }, + "filename": "config_expr-02.k", + "line": 3, + "column": 9, + "end_line": 3, + "end_column": 12 + }, + "operation": "Override", + "insert_index": -1 + }, + "filename": "config_expr-02.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 12 + } + ] + }, + "filename": "config_expr-02.k", + "line": 1, + "column": 9, + "end_line": 4, + "end_column": 1 + }, + "ty": null + }, + "filename": "config_expr-02.k", + "line": 1, + "column": 0, + "end_line": 4, + "end_column": 1 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_3.snap new file mode 100644 index 000000000..c87d218f0 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_3.snap @@ -0,0 +1,460 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/config_expr-03.k\")" +--- +{ + "filename": "config_expr-03.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "config", + "filename": "config_expr-03.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "config_expr-03.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "main", + "filename": "config_expr-03.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 8 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 8 + }, + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "env", + "filename": "config_expr-03.k", + "line": 5, + "column": 8, + "end_line": 5, + "end_column": 11 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 5, + "column": 8, + "end_line": 5, + "end_column": 11 + }, + "value": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "name", + "filename": "config_expr-03.k", + "line": 6, + "column": 13, + "end_line": 6, + "end_column": 17 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 13, + "end_line": 6, + "end_column": 17 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"ENV_1\"", + "value": "ENV_1" + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 19, + "end_line": 6, + "end_column": 26 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 13, + "end_line": 6, + "end_column": 26 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "value", + "filename": "config_expr-03.k", + "line": 6, + "column": 28, + "end_line": 6, + "end_column": 33 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 28, + "end_line": 6, + "end_column": 33 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"1\"", + "value": "1" + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 35, + "end_line": 6, + "end_column": 38 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 28, + "end_line": 6, + "end_column": 38 + } + ] + }, + "filename": "config_expr-03.k", + "line": 6, + "column": 12, + "end_line": 6, + "end_column": 39 + } + ], + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 5, + "column": 13, + "end_line": 7, + "end_column": 9 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 5, + "column": 8, + "end_line": 7, + "end_column": 9 + } + ] + }, + "filename": "config_expr-03.k", + "line": 4, + "column": 10, + "end_line": 8, + "end_column": 5 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 4, + "column": 4, + "end_line": 8, + "end_column": 5 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "main", + "filename": "config_expr-03.k", + "line": 9, + "column": 4, + "end_line": 9, + "end_column": 8 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 9, + "column": 4, + "end_line": 9, + "end_column": 8 + }, + "value": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "env", + "filename": "config_expr-03.k", + "line": 10, + "column": 8, + "end_line": 10, + "end_column": 11 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 10, + "column": 8, + "end_line": 10, + "end_column": 11 + }, + "value": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "name", + "filename": "config_expr-03.k", + "line": 11, + "column": 13, + "end_line": 11, + "end_column": 17 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 13, + "end_line": 11, + "end_column": 17 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"ENV_2\"", + "value": "ENV_2" + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 19, + "end_line": 11, + "end_column": 26 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 13, + "end_line": 11, + "end_column": 26 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "value", + "filename": "config_expr-03.k", + "line": 11, + "column": 28, + "end_line": 11, + "end_column": 33 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 28, + "end_line": 11, + "end_column": 33 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"2\"", + "value": "2" + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 35, + "end_line": 11, + "end_column": 38 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 28, + "end_line": 11, + "end_column": 38 + } + ] + }, + "filename": "config_expr-03.k", + "line": 11, + "column": 12, + "end_line": 11, + "end_column": 39 + } + ], + "ctx": "Load" + }, + "filename": "config_expr-03.k", + "line": 10, + "column": 15, + "end_line": 12, + "end_column": 9 + }, + "operation": "Insert", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 10, + "column": 8, + "end_line": 12, + "end_column": 9 + } + ] + }, + "filename": "config_expr-03.k", + "line": 9, + "column": 10, + "end_line": 13, + "end_column": 5 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-03.k", + "line": 9, + "column": 4, + "end_line": 13, + "end_column": 5 + } + ] + }, + "filename": "config_expr-03.k", + "line": 3, + "column": 9, + "end_line": 14, + "end_column": 1 + }, + "ty": null + }, + "filename": "config_expr-03.k", + "line": 3, + "column": 0, + "end_line": 14, + "end_column": 1 + } + ], + "comments": [ + { + "node": { + "text": "# test/grammar/attr_operator/config_inside/insert/dict_0/main.k" + }, + "filename": "config_expr-03.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 63 + } + ] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_4.snap new file mode 100644 index 000000000..1f4a8ab74 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__config_expr_4.snap @@ -0,0 +1,879 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/config_expr-04.k\")" +--- +{ + "filename": "config_expr-04.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "Env", + "filename": "config_expr-04.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 10 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "name", + "filename": "config_expr-04.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 8 + }, + "op": null, + "value": null, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "config_expr-04.k", + "line": 4, + "column": 10, + "end_line": 4, + "end_column": 13 + } + }, + "filename": "config_expr-04.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 13 + }, + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "value", + "filename": "config_expr-04.k", + "line": 5, + "column": 4, + "end_line": 5, + "end_column": 9 + }, + "op": null, + "value": null, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "config_expr-04.k", + "line": 5, + "column": 11, + "end_line": 5, + "end_column": 14 + } + }, + "filename": "config_expr-04.k", + "line": 5, + "column": 4, + "end_line": 5, + "end_column": 14 + } + ], + "decorators": [], + "checks": [], + "index_signature": null + }, + "filename": "config_expr-04.k", + "line": 3, + "column": 0, + "end_line": 7, + "end_column": 0 + }, + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "Main", + "filename": "config_expr-04.k", + "line": 7, + "column": 7, + "end_line": 7, + "end_column": 11 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "env", + "filename": "config_expr-04.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 7 + }, + "op": null, + "value": null, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "List", + "value": { + "inner_type": { + "node": { + "type": "Named", + "value": { + "names": [ + { + "node": "Env", + "filename": "config_expr-04.k", + "line": 8, + "column": 10, + "end_line": 8, + "end_column": 13 + } + ], + "pkgpath": "", + "ctx": "Load" + } + }, + "filename": "config_expr-04.k", + "line": 8, + "column": 10, + "end_line": 8, + "end_column": 13 + } + } + }, + "filename": "config_expr-04.k", + "line": 8, + "column": 9, + "end_line": 8, + "end_column": 14 + } + }, + "filename": "config_expr-04.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 14 + } + ], + "decorators": [], + "checks": [], + "index_signature": null + }, + "filename": "config_expr-04.k", + "line": 7, + "column": 0, + "end_line": 10, + "end_column": 0 + }, + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "Config", + "filename": "config_expr-04.k", + "line": 10, + "column": 7, + "end_line": 10, + "end_column": 13 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "main", + "filename": "config_expr-04.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 8 + }, + "op": null, + "value": null, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Named", + "value": { + "names": [ + { + "node": "Main", + "filename": "config_expr-04.k", + "line": 11, + "column": 10, + "end_line": 11, + "end_column": 14 + } + ], + "pkgpath": "", + "ctx": "Load" + } + }, + "filename": "config_expr-04.k", + "line": 11, + "column": 10, + "end_line": 11, + "end_column": 14 + } + }, + "filename": "config_expr-04.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 14 + } + ], + "decorators": [], + "checks": [], + "index_signature": null + }, + "filename": "config_expr-04.k", + "line": 10, + "column": 0, + "end_line": 13, + "end_column": 0 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "_main", + "filename": "config_expr-04.k", + "line": 13, + "column": 0, + "end_line": 13, + "end_column": 5 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "config_expr-04.k", + "line": 13, + "column": 0, + "end_line": 13, + "end_column": 5 + } + ], + "value": { + "node": { + "type": "Schema", + "name": { + "node": { + "names": [ + { + "node": "Main", + "filename": "config_expr-04.k", + "line": 13, + "column": 8, + "end_line": 13, + "end_column": 12 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 13, + "column": 8, + "end_line": 13, + "end_column": 12 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "env", + "filename": "config_expr-04.k", + "line": 14, + "column": 4, + "end_line": 14, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 14, + "column": 4, + "end_line": 14, + "end_column": 7 + }, + "value": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "name", + "filename": "config_expr-04.k", + "line": 15, + "column": 9, + "end_line": 15, + "end_column": 13 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 9, + "end_line": 15, + "end_column": 13 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"ENV_1\"", + "value": "ENV_1" + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 15, + "end_line": 15, + "end_column": 22 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 9, + "end_line": 15, + "end_column": 22 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "value", + "filename": "config_expr-04.k", + "line": 15, + "column": 24, + "end_line": 15, + "end_column": 29 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 24, + "end_line": 15, + "end_column": 29 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"1\"", + "value": "1" + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 31, + "end_line": 15, + "end_column": 34 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 24, + "end_line": 15, + "end_column": 34 + } + ] + }, + "filename": "config_expr-04.k", + "line": 15, + "column": 8, + "end_line": 15, + "end_column": 35 + } + ], + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 14, + "column": 9, + "end_line": 16, + "end_column": 5 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 14, + "column": 4, + "end_line": 16, + "end_column": 5 + } + ] + }, + "filename": "config_expr-04.k", + "line": 13, + "column": 13, + "end_line": 17, + "end_column": 1 + } + }, + "filename": "config_expr-04.k", + "line": 13, + "column": 8, + "end_line": 17, + "end_column": 1 + }, + "ty": null + }, + "filename": "config_expr-04.k", + "line": 13, + "column": 0, + "end_line": 17, + "end_column": 1 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "config", + "filename": "config_expr-04.k", + "line": 19, + "column": 0, + "end_line": 19, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "config_expr-04.k", + "line": 19, + "column": 0, + "end_line": 19, + "end_column": 6 + } + ], + "value": { + "node": { + "type": "Schema", + "name": { + "node": { + "names": [ + { + "node": "Config", + "filename": "config_expr-04.k", + "line": 19, + "column": 9, + "end_line": 19, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 19, + "column": 9, + "end_line": 19, + "end_column": 15 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "main", + "filename": "config_expr-04.k", + "line": 20, + "column": 4, + "end_line": 20, + "end_column": 8 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 20, + "column": 4, + "end_line": 20, + "end_column": 8 + }, + "value": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "_main", + "filename": "config_expr-04.k", + "line": 20, + "column": 10, + "end_line": 20, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 20, + "column": 10, + "end_line": 20, + "end_column": 15 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 20, + "column": 4, + "end_line": 20, + "end_column": 15 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "main", + "filename": "config_expr-04.k", + "line": 21, + "column": 4, + "end_line": 21, + "end_column": 8 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 21, + "column": 4, + "end_line": 21, + "end_column": 8 + }, + "value": { + "node": { + "type": "Schema", + "name": { + "node": { + "names": [ + { + "node": "Main", + "filename": "config_expr-04.k", + "line": 21, + "column": 10, + "end_line": 21, + "end_column": 14 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 21, + "column": 10, + "end_line": 21, + "end_column": 14 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "env", + "filename": "config_expr-04.k", + "line": 22, + "column": 8, + "end_line": 22, + "end_column": 11 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 22, + "column": 8, + "end_line": 22, + "end_column": 11 + }, + "value": { + "node": { + "type": "List", + "elts": [ + { + "node": { + "type": "Config", + "items": [ + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "name", + "filename": "config_expr-04.k", + "line": 23, + "column": 13, + "end_line": 23, + "end_column": 17 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 13, + "end_line": 23, + "end_column": 17 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"ENV_2\"", + "value": "ENV_2" + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 19, + "end_line": 23, + "end_column": 26 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 13, + "end_line": 23, + "end_column": 26 + }, + { + "node": { + "key": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "value", + "filename": "config_expr-04.k", + "line": 23, + "column": 28, + "end_line": 23, + "end_column": 33 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 28, + "end_line": 23, + "end_column": 33 + }, + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"2\"", + "value": "2" + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 35, + "end_line": 23, + "end_column": 38 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 28, + "end_line": 23, + "end_column": 38 + } + ] + }, + "filename": "config_expr-04.k", + "line": 23, + "column": 12, + "end_line": 23, + "end_column": 39 + } + ], + "ctx": "Load" + }, + "filename": "config_expr-04.k", + "line": 22, + "column": 15, + "end_line": 24, + "end_column": 9 + }, + "operation": "Insert", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 22, + "column": 8, + "end_line": 24, + "end_column": 9 + } + ] + }, + "filename": "config_expr-04.k", + "line": 21, + "column": 15, + "end_line": 25, + "end_column": 5 + } + }, + "filename": "config_expr-04.k", + "line": 21, + "column": 10, + "end_line": 25, + "end_column": 5 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "config_expr-04.k", + "line": 21, + "column": 4, + "end_line": 25, + "end_column": 5 + } + ] + }, + "filename": "config_expr-04.k", + "line": 19, + "column": 16, + "end_line": 26, + "end_column": 1 + } + }, + "filename": "config_expr-04.k", + "line": 19, + "column": 9, + "end_line": 26, + "end_column": 1 + }, + "ty": null + }, + "filename": "config_expr-04.k", + "line": 19, + "column": 0, + "end_line": 26, + "end_column": 1 + } + ], + "comments": [ + { + "node": { + "text": "# test/grammar/attr_operator/config_inside/insert/schema_0/main.k" + }, + "filename": "config_expr-04.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 65 + } + ] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__hello_win.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__hello_win.snap new file mode 100644 index 000000000..760a592b0 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__hello_win.snap @@ -0,0 +1,167 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/hello_win.k\")" +--- +{ + "filename": "hello_win.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Schema", + "doc": null, + "name": { + "node": "Person", + "filename": "hello_win.k", + "line": 2, + "column": 7, + "end_line": 2, + "end_column": 13 + }, + "parent_name": null, + "for_host_name": null, + "is_mixin": false, + "is_protocol": false, + "args": null, + "mixins": [], + "body": [ + { + "node": { + "type": "SchemaAttr", + "doc": "", + "name": { + "node": "name", + "filename": "hello_win.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 8 + }, + "op": "Assign", + "value": { + "node": { + "type": "StringLit", + "is_long_string": false, + "raw_value": "\"kcl\"", + "value": "kcl" + }, + "filename": "hello_win.k", + "line": 3, + "column": 16, + "end_line": 3, + "end_column": 21 + }, + "is_optional": false, + "decorators": [], + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "hello_win.k", + "line": 3, + "column": 10, + "end_line": 3, + "end_column": 13 + } + }, + "filename": "hello_win.k", + "line": 3, + "column": 4, + "end_line": 3, + "end_column": 21 + } + ], + "decorators": [], + "checks": [], + "index_signature": null + }, + "filename": "hello_win.k", + "line": 2, + "column": 0, + "end_line": 5, + "end_column": 0 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "x0", + "filename": "hello_win.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 2 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "hello_win.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 2 + } + ], + "value": { + "node": { + "type": "Schema", + "name": { + "node": { + "names": [ + { + "node": "Person", + "filename": "hello_win.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 11 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "hello_win.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 11 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "type": "Config", + "items": [] + }, + "filename": "hello_win.k", + "line": 5, + "column": 12, + "end_line": 5, + "end_column": 14 + } + }, + "filename": "hello_win.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 14 + }, + "ty": null + }, + "filename": "hello_win.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 14 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_1.snap new file mode 100644 index 000000000..b5c56d05a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_1.snap @@ -0,0 +1,146 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/if-01.k\")" +--- +{ + "filename": "if-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "if-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "if-01.k", + "line": 1, + "column": 4, + "end_line": 1, + "end_column": 5 + }, + "ty": null + }, + "filename": "if-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 5 + }, + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "bbb", + "filename": "if-01.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-01.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "if-01.k", + "line": 4, + "column": 10, + "end_line": 4, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-01.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 11 + } + ], + "cond": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "if-01.k", + "line": 3, + "column": 3, + "end_line": 3, + "end_column": 4 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "if-01.k", + "line": 3, + "column": 3, + "end_line": 3, + "end_column": 4 + }, + "orelse": [] + }, + "filename": "if-01.k", + "line": 3, + "column": 0, + "end_line": 4, + "end_column": 12 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_2.snap new file mode 100644 index 000000000..eb9612718 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_2.snap @@ -0,0 +1,467 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/if-02.k\")" +--- +{ + "filename": "if-02.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "if-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 1 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "if-02.k", + "line": 1, + "column": 4, + "end_line": 1, + "end_column": 5 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 5 + }, + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "bbb", + "filename": "if-02.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 2 + } + }, + "filename": "if-02.k", + "line": 4, + "column": 10, + "end_line": 4, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 4, + "column": 4, + "end_line": 4, + "end_column": 11 + } + ], + "cond": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "if-02.k", + "line": 3, + "column": 3, + "end_line": 3, + "end_column": 4 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "if-02.k", + "line": 3, + "column": 3, + "end_line": 3, + "end_column": 4 + }, + "orelse": [ + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "ccc", + "filename": "if-02.k", + "line": 6, + "column": 4, + "end_line": 6, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 6, + "column": 4, + "end_line": 6, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 3 + } + }, + "filename": "if-02.k", + "line": 6, + "column": 10, + "end_line": 6, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 6, + "column": 4, + "end_line": 6, + "end_column": 11 + } + ], + "cond": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "if-02.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "if-02.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 6 + }, + "op": "Add", + "right": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 10 + } + }, + "filename": "if-02.k", + "line": 5, + "column": 9, + "end_line": 5, + "end_column": 11 + } + }, + "filename": "if-02.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 11 + }, + "orelse": [ + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "ddd", + "filename": "if-02.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 4 + } + }, + "filename": "if-02.k", + "line": 8, + "column": 10, + "end_line": 8, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 8, + "column": 4, + "end_line": 8, + "end_column": 11 + } + ], + "cond": { + "node": { + "type": "Binary", + "left": { + "node": { + "type": "Identifier", + "names": [ + { + "node": "a", + "filename": "if-02.k", + "line": 7, + "column": 5, + "end_line": 7, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "if-02.k", + "line": 7, + "column": 5, + "end_line": 7, + "end_column": 6 + }, + "op": "Add", + "right": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 100 + } + }, + "filename": "if-02.k", + "line": 7, + "column": 9, + "end_line": 7, + "end_column": 12 + } + }, + "filename": "if-02.k", + "line": 7, + "column": 5, + "end_line": 7, + "end_column": 12 + }, + "orelse": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "eee", + "filename": "if-02.k", + "line": 10, + "column": 4, + "end_line": 10, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 10, + "column": 4, + "end_line": 10, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 5 + } + }, + "filename": "if-02.k", + "line": 10, + "column": 10, + "end_line": 10, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 10, + "column": 4, + "end_line": 10, + "end_column": 11 + }, + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "fff", + "filename": "if-02.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 7 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-02.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 7 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 6 + } + }, + "filename": "if-02.k", + "line": 11, + "column": 10, + "end_line": 11, + "end_column": 11 + }, + "ty": null + }, + "filename": "if-02.k", + "line": 11, + "column": 4, + "end_line": 11, + "end_column": 11 + } + ] + }, + "filename": "if-02.k", + "line": 7, + "column": 0, + "end_line": 11, + "end_column": 11 + } + ] + }, + "filename": "if-02.k", + "line": 5, + "column": 0, + "end_line": 11, + "end_column": 11 + } + ] + }, + "filename": "if-02.k", + "line": 3, + "column": 0, + "end_line": 11, + "end_column": 12 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_3.snap new file mode 100644 index 000000000..d1db8d1b4 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__if_3.snap @@ -0,0 +1,86 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/if-03.k\")" +--- +{ + "filename": "if-03.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "If", + "body": [ + { + "node": { + "type": "Assign", + "targets": [ + { + "node": { + "names": [ + { + "node": "a", + "filename": "if-03.k", + "line": 1, + "column": 9, + "end_line": 1, + "end_column": 10 + } + ], + "pkgpath": "", + "ctx": "Store" + }, + "filename": "if-03.k", + "line": 1, + "column": 9, + "end_line": 1, + "end_column": 10 + } + ], + "value": { + "node": { + "type": "NumberLit", + "binary_suffix": null, + "value": { + "type": "Int", + "value": 1 + } + }, + "filename": "if-03.k", + "line": 1, + "column": 13, + "end_line": 1, + "end_column": 14 + }, + "ty": null + }, + "filename": "if-03.k", + "line": 1, + "column": 9, + "end_line": 1, + "end_column": 14 + } + ], + "cond": { + "node": { + "type": "NameConstantLit", + "value": "True" + }, + "filename": "if-03.k", + "line": 1, + "column": 3, + "end_line": 1, + "end_column": 7 + }, + "orelse": [] + }, + "filename": "if-03.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 15 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__import_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__import_1.snap new file mode 100644 index 000000000..887c422e5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__import_1.snap @@ -0,0 +1,108 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/import-01.k\")" +--- +{ + "filename": "import-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "Import", + "path": { + "node": "a1", + "filename": "import-01.k", + "line": 1, + "column": 7, + "end_line": 1, + "end_column": 9 + }, + "rawpath": "a1", + "name": "a1", + "asname": null, + "pkg_name": "__main__" + }, + "filename": "import-01.k", + "line": 1, + "column": 0, + "end_line": 1, + "end_column": 9 + }, + { + "node": { + "type": "Import", + "path": { + "node": "a2", + "filename": "import-01.k", + "line": 3, + "column": 7, + "end_line": 3, + "end_column": 9 + }, + "rawpath": "a2", + "name": "a2_pkg", + "asname": { + "node": "a2_pkg", + "filename": "import-01.k", + "line": 3, + "column": 13, + "end_line": 3, + "end_column": 19 + }, + "pkg_name": "__main__" + }, + "filename": "import-01.k", + "line": 3, + "column": 0, + "end_line": 3, + "end_column": 19 + }, + { + "node": { + "type": "Import", + "path": { + "node": "subpkg.b1.c1", + "filename": "import-01.k", + "line": 5, + "column": 7, + "end_line": 5, + "end_column": 19 + }, + "rawpath": "subpkg.b1.c1", + "name": "c1", + "asname": null, + "pkg_name": "__main__" + }, + "filename": "import-01.k", + "line": 5, + "column": 0, + "end_line": 5, + "end_column": 19 + }, + { + "node": { + "type": "Import", + "path": { + "node": "a3", + "filename": "import-01.k", + "line": 7, + "column": 7, + "end_line": 7, + "end_column": 10 + }, + "rawpath": ".a3", + "name": "a3", + "asname": null, + "pkg_name": "__main__" + }, + "filename": "import-01.k", + "line": 7, + "column": 0, + "end_line": 7, + "end_column": 10 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__type_1.snap new file mode 100644 index 000000000..91ac6fa3a --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__file__type_1.snap @@ -0,0 +1,542 @@ +--- +source: parser/src/tests/file.rs +expression: "crate::tests::parsing_file_string(\"testdata/type-01.k\")" +--- +{ + "filename": "type-01.k", + "pkg": "__main__", + "doc": null, + "name": "__main__", + "body": [ + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "a", + "filename": "type-01.k", + "line": 1, + "column": 5, + "end_line": 1, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 1, + "column": 5, + "end_line": 1, + "end_column": 6 + }, + "type_value": { + "node": "any", + "filename": "type-01.k", + "line": 1, + "column": 9, + "end_line": 1, + "end_column": 12 + }, + "ty": { + "node": { + "type": "Any" + }, + "filename": "type-01.k", + "line": 1, + "column": 9, + "end_line": 1, + "end_column": 12 + } + }, + "filename": "type-01.k", + "line": 1, + "column": 5, + "end_line": 1, + "end_column": 12 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "b", + "filename": "type-01.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 6 + }, + "type_value": { + "node": "bool", + "filename": "type-01.k", + "line": 3, + "column": 9, + "end_line": 3, + "end_column": 13 + }, + "ty": { + "node": { + "type": "Basic", + "value": "Bool" + }, + "filename": "type-01.k", + "line": 3, + "column": 9, + "end_line": 3, + "end_column": 13 + } + }, + "filename": "type-01.k", + "line": 3, + "column": 5, + "end_line": 3, + "end_column": 13 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "c", + "filename": "type-01.k", + "line": 4, + "column": 5, + "end_line": 4, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 4, + "column": 5, + "end_line": 4, + "end_column": 6 + }, + "type_value": { + "node": "int", + "filename": "type-01.k", + "line": 4, + "column": 9, + "end_line": 4, + "end_column": 12 + }, + "ty": { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "type-01.k", + "line": 4, + "column": 9, + "end_line": 4, + "end_column": 12 + } + }, + "filename": "type-01.k", + "line": 4, + "column": 5, + "end_line": 4, + "end_column": 12 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "d", + "filename": "type-01.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 6 + }, + "type_value": { + "node": "float", + "filename": "type-01.k", + "line": 5, + "column": 9, + "end_line": 5, + "end_column": 14 + }, + "ty": { + "node": { + "type": "Basic", + "value": "Float" + }, + "filename": "type-01.k", + "line": 5, + "column": 9, + "end_line": 5, + "end_column": 14 + } + }, + "filename": "type-01.k", + "line": 5, + "column": 5, + "end_line": 5, + "end_column": 14 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "e", + "filename": "type-01.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 6 + }, + "type_value": { + "node": "str", + "filename": "type-01.k", + "line": 6, + "column": 9, + "end_line": 6, + "end_column": 12 + }, + "ty": { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "type-01.k", + "line": 6, + "column": 9, + "end_line": 6, + "end_column": 12 + } + }, + "filename": "type-01.k", + "line": 6, + "column": 5, + "end_line": 6, + "end_column": 12 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "type_list1", + "filename": "type-01.k", + "line": 8, + "column": 5, + "end_line": 8, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 8, + "column": 5, + "end_line": 8, + "end_column": 15 + }, + "type_value": { + "node": "[]", + "filename": "type-01.k", + "line": 8, + "column": 18, + "end_line": 8, + "end_column": 20 + }, + "ty": { + "node": { + "type": "List", + "value": { + "inner_type": null + } + }, + "filename": "type-01.k", + "line": 8, + "column": 18, + "end_line": 8, + "end_column": 20 + } + }, + "filename": "type-01.k", + "line": 8, + "column": 5, + "end_line": 8, + "end_column": 20 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "type_list2", + "filename": "type-01.k", + "line": 9, + "column": 5, + "end_line": 9, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 9, + "column": 5, + "end_line": 9, + "end_column": 15 + }, + "type_value": { + "node": "[[]]", + "filename": "type-01.k", + "line": 9, + "column": 18, + "end_line": 9, + "end_column": 22 + }, + "ty": { + "node": { + "type": "List", + "value": { + "inner_type": { + "node": { + "type": "List", + "value": { + "inner_type": null + } + }, + "filename": "type-01.k", + "line": 9, + "column": 19, + "end_line": 9, + "end_column": 21 + } + } + }, + "filename": "type-01.k", + "line": 9, + "column": 18, + "end_line": 9, + "end_column": 22 + } + }, + "filename": "type-01.k", + "line": 9, + "column": 5, + "end_line": 9, + "end_column": 22 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "type_list3", + "filename": "type-01.k", + "line": 10, + "column": 5, + "end_line": 10, + "end_column": 15 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 10, + "column": 5, + "end_line": 10, + "end_column": 15 + }, + "type_value": { + "node": "[int]", + "filename": "type-01.k", + "line": 10, + "column": 18, + "end_line": 10, + "end_column": 23 + }, + "ty": { + "node": { + "type": "List", + "value": { + "inner_type": { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "type-01.k", + "line": 10, + "column": 19, + "end_line": 10, + "end_column": 22 + } + } + }, + "filename": "type-01.k", + "line": 10, + "column": 18, + "end_line": 10, + "end_column": 23 + } + }, + "filename": "type-01.k", + "line": 10, + "column": 5, + "end_line": 10, + "end_column": 23 + }, + { + "node": { + "type": "TypeAlias", + "type_name": { + "node": { + "names": [ + { + "node": "b", + "filename": "type-01.k", + "line": 12, + "column": 5, + "end_line": 12, + "end_column": 6 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "type-01.k", + "line": 12, + "column": 5, + "end_line": 12, + "end_column": 6 + }, + "type_value": { + "node": "int | str | [] | {:}", + "filename": "type-01.k", + "line": 12, + "column": 9, + "end_line": 12, + "end_column": 29 + }, + "ty": { + "node": { + "type": "Union", + "value": { + "type_elements": [ + { + "node": { + "type": "Basic", + "value": "Int" + }, + "filename": "type-01.k", + "line": 12, + "column": 9, + "end_line": 12, + "end_column": 12 + }, + { + "node": { + "type": "Basic", + "value": "Str" + }, + "filename": "type-01.k", + "line": 12, + "column": 15, + "end_line": 12, + "end_column": 18 + }, + { + "node": { + "type": "List", + "value": { + "inner_type": null + } + }, + "filename": "type-01.k", + "line": 12, + "column": 21, + "end_line": 12, + "end_column": 23 + }, + { + "node": { + "type": "Dict", + "value": { + "key_type": null, + "value_type": null + } + }, + "filename": "type-01.k", + "line": 12, + "column": 26, + "end_line": 12, + "end_column": 29 + } + ] + } + }, + "filename": "type-01.k", + "line": 12, + "column": 9, + "end_line": 12, + "end_column": 29 + } + }, + "filename": "type-01.k", + "line": 12, + "column": 5, + "end_line": 12, + "end_column": 29 + } + ], + "comments": [] +} diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__any_type.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__any_type.snap new file mode 100644 index 000000000..5e3e41d28 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__any_type.snap @@ -0,0 +1,13 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"any\"####)" +--- +Node { + node: Any, + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_0.snap new file mode 100644 index 000000000..d7a243058 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_0.snap @@ -0,0 +1,15 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"bool\"####)" +--- +Node { + node: Basic( + Bool, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_1.snap new file mode 100644 index 000000000..335b19217 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_1.snap @@ -0,0 +1,15 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"int\"####)" +--- +Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_2.snap new file mode 100644 index 000000000..7c6ee89d2 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_2.snap @@ -0,0 +1,15 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"float\"####)" +--- +Node { + node: Basic( + Float, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_3.snap new file mode 100644 index 000000000..9d7b59a4b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__basic_type_3.snap @@ -0,0 +1,15 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"str\"####)" +--- +Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_0.snap new file mode 100644 index 000000000..7d0a2bf4b --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_0.snap @@ -0,0 +1,18 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"{:}\"####)" +--- +Node { + node: Dict( + DictType { + key_type: None, + value_type: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_1.snap new file mode 100644 index 000000000..3b4667dcb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_1.snap @@ -0,0 +1,29 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"{str:}\"####)" +--- +Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ), + value_type: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_2.snap new file mode 100644 index 000000000..8165aaed5 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_2.snap @@ -0,0 +1,31 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"{:[]}\"####)" +--- +Node { + node: Dict( + DictType { + key_type: None, + value_type: Some( + Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_3.snap new file mode 100644 index 000000000..c35fb6168 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_3.snap @@ -0,0 +1,54 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"{str:{:float}}\"####)" +--- +Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ), + value_type: Some( + Node { + node: Dict( + DictType { + key_type: None, + value_type: Some( + Node { + node: Basic( + Float, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 12, + }, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 13, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_4.snap new file mode 100644 index 000000000..b98aafcde --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__dict_type_4.snap @@ -0,0 +1,54 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"{str:{:float}, int:[]}\"####)" +--- +Node { + node: Dict( + DictType { + key_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ), + value_type: Some( + Node { + node: Dict( + DictType { + key_type: None, + value_type: Some( + Node { + node: Basic( + Float, + ), + filename: "", + line: 1, + column: 7, + end_line: 1, + end_column: 12, + }, + ), + }, + ), + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 13, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 14, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_0.snap new file mode 100644 index 000000000..c473941af --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_0.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"[]\"####)" +--- +Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 2, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_1.snap new file mode 100644 index 000000000..fd9988b84 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_1.snap @@ -0,0 +1,28 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"[int]\"####)" +--- +Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_2.snap new file mode 100644 index 000000000..73e992119 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_2.snap @@ -0,0 +1,26 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"[any]\"####)" +--- +Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Any, + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 4, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_3.snap new file mode 100644 index 000000000..a3b930896 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_3.snap @@ -0,0 +1,30 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"[[]]\"####)" +--- +Node { + node: List( + ListType { + inner_type: Some( + Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 3, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_4.snap new file mode 100644 index 000000000..518dd31b9 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__list_type_4.snap @@ -0,0 +1,41 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"[[str]]\"####)" +--- +Node { + node: List( + ListType { + inner_type: Some( + Node { + node: List( + ListType { + inner_type: Some( + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 2, + end_line: 1, + end_column: 5, + }, + ), + }, + ), + filename: "", + line: 1, + column: 1, + end_line: 1, + end_column: 6, + }, + ), + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_0.snap new file mode 100644 index 000000000..d7ba0c795 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_0.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"True\"####)" +--- +Node { + node: Literal( + Bool( + true, + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_1.snap new file mode 100644 index 000000000..79951d904 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_1.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"False\"####)" +--- +Node { + node: Literal( + Bool( + false, + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_2.snap new file mode 100644 index 000000000..fe221ef16 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_2.snap @@ -0,0 +1,20 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"123\"####)" +--- +Node { + node: Literal( + Int( + IntLiteralType { + value: 123, + suffix: None, + }, + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_3.snap new file mode 100644 index 000000000..7db780a7d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_3.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"123.0\"####)" +--- +Node { + node: Literal( + Float( + 123.0, + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_4.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_4.snap new file mode 100644 index 000000000..9e368bc0d --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_4.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"\"abc\"\"####)" +--- +Node { + node: Literal( + Str( + "abc", + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 5, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_5.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_5.snap new file mode 100644 index 000000000..886d9b0cb --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__literal_type_5.snap @@ -0,0 +1,17 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"''\"####)" +--- +Node { + node: Literal( + Str( + "", + ), + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 2, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_0.snap new file mode 100644 index 000000000..9c2a9e0a9 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_0.snap @@ -0,0 +1,28 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"Person\"####)" +--- +Node { + node: Named( + Identifier { + names: [ + Node { + node: "Person", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 6, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_1.snap new file mode 100644 index 000000000..ea918caae --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__named_type_1.snap @@ -0,0 +1,44 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"some.pkg.Person\"####)" +--- +Node { + node: Named( + Identifier { + names: [ + Node { + node: "some", + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 4, + }, + Node { + node: "pkg", + filename: "", + line: 1, + column: 5, + end_line: 1, + end_column: 8, + }, + Node { + node: "Person", + filename: "", + line: 1, + column: 9, + end_line: 1, + end_column: 15, + }, + ], + pkgpath: "", + ctx: Load, + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 15, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_0.snap new file mode 100644 index 000000000..fe487c4ab --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_0.snap @@ -0,0 +1,5 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_node_string(r####\"int\"####)" +--- +int diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_1.snap new file mode 100644 index 000000000..b5d050c86 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_1.snap @@ -0,0 +1,5 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_node_string(r####\" int \"####)" +--- +int diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_2.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_2.snap new file mode 100644 index 000000000..f6ceb4f04 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_2.snap @@ -0,0 +1,5 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_node_string(r####\"bool | True | int | str|str\"####)" +--- +bool | True | int | str | str diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_3.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_3.snap new file mode 100644 index 000000000..8d25e81de --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__type_str_3.snap @@ -0,0 +1,5 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_node_string(r####\"[ [{str: float}] | int]\"####)" +--- +[[{str:float}] | int] diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_0.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_0.snap new file mode 100644 index 000000000..d78b2e820 --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_0.snap @@ -0,0 +1,38 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"int|str\"####)" +--- +Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 4, + end_line: 1, + end_column: 7, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 7, +} + diff --git a/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_1.snap b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_1.snap new file mode 100644 index 000000000..4a631d87f --- /dev/null +++ b/kclvm/parser/src/tests/snapshots/kclvm_parser__tests__types__union_type_1.snap @@ -0,0 +1,63 @@ +--- +source: parser/src/tests/types.rs +expression: "crate::tests::parsing_type_string(r####\"int | str | [] | {:}\"####)" +--- +Node { + node: Union( + UnionType { + type_elements: [ + Node { + node: Basic( + Int, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 3, + }, + Node { + node: Basic( + Str, + ), + filename: "", + line: 1, + column: 6, + end_line: 1, + end_column: 9, + }, + Node { + node: List( + ListType { + inner_type: None, + }, + ), + filename: "", + line: 1, + column: 12, + end_line: 1, + end_column: 14, + }, + Node { + node: Dict( + DictType { + key_type: None, + value_type: None, + }, + ), + filename: "", + line: 1, + column: 17, + end_line: 1, + end_column: 20, + }, + ], + }, + ), + filename: "", + line: 1, + column: 0, + end_line: 1, + end_column: 20, +} + diff --git a/kclvm/parser/src/tests/types.rs b/kclvm/parser/src/tests/types.rs new file mode 100644 index 000000000..d1b2ab629 --- /dev/null +++ b/kclvm/parser/src/tests/types.rs @@ -0,0 +1,32 @@ +use crate::tests::{parse_type_node_snapshot, parse_type_snapshot}; + +parse_type_snapshot!(basic_type_0, r####"bool"####); +parse_type_snapshot!(basic_type_1, r####"int"####); +parse_type_snapshot!(basic_type_2, r####"float"####); +parse_type_snapshot!(basic_type_3, r####"str"####); +parse_type_snapshot!(any_type, r####"any"####); +parse_type_snapshot!(list_type_0, r####"[]"####); +parse_type_snapshot!(list_type_1, r####"[int]"####); +parse_type_snapshot!(list_type_2, r####"[any]"####); +parse_type_snapshot!(list_type_3, r####"[[]]"####); +parse_type_snapshot!(list_type_4, r####"[[str]]"####); +parse_type_snapshot!(dict_type_0, r####"{:}"####); +parse_type_snapshot!(dict_type_1, r####"{str:}"####); +parse_type_snapshot!(dict_type_2, r####"{:[]}"####); +parse_type_snapshot!(dict_type_3, r####"{str:{:float}}"####); +parse_type_snapshot!(dict_type_4, r####"{str:{:float}, int:[]}"####); +parse_type_snapshot!(union_type_0, r####"int|str"####); +parse_type_snapshot!(union_type_1, r####"int | str | [] | {:}"####); +parse_type_snapshot!(named_type_0, r####"Person"####); +parse_type_snapshot!(named_type_1, r####"some.pkg.Person"####); +parse_type_snapshot!(literal_type_0, r####"True"####); +parse_type_snapshot!(literal_type_1, r####"False"####); +parse_type_snapshot!(literal_type_2, r####"123"####); +parse_type_snapshot!(literal_type_3, r####"123.0"####); +parse_type_snapshot!(literal_type_4, r####""abc""####); +parse_type_snapshot!(literal_type_5, r####"''"####); + +parse_type_node_snapshot!(type_str_0, r####"int"####); +parse_type_node_snapshot!(type_str_1, r####" int "####); +parse_type_node_snapshot!(type_str_2, r####"bool | True | int | str|str"####); +parse_type_node_snapshot!(type_str_3, r####"[ [{str: float}] | int]"####); diff --git a/kclvm/parser/testdata/Makefile b/kclvm/parser/testdata/Makefile deleted file mode 100644 index ac278ac6b..000000000 --- a/kclvm/parser/testdata/Makefile +++ /dev/null @@ -1,13 +0,0 @@ - -K_FILES=$(wildcard ./*.k) -K_JSON_FILES=$(patsubst %.k,%.k.json,$(K_FILES)) - -default: clean $(K_JSON_FILES) $(K_FMT_JSON_FILES) - @echo "ok" - -clean: - -rm *.k.json - -%.k.json: %.k - cargo run --bin parse_file $< > $@ - diff --git a/kclvm/parser/testdata/assert-01.k.json b/kclvm/parser/testdata/assert-01.k.json deleted file mode 100644 index 75b5a5f19..000000000 --- a/kclvm/parser/testdata/assert-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assert":{"test":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-01.k","line":1,"column":7,"end_line":1,"end_column":8},"if_cond":null,"msg":null}},"filename":"assert-01.k","line":1,"column":0,"end_line":1,"end_column":8},{"node":{"Assert":{"test":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"assert-01.k","line":2,"column":7,"end_line":2,"end_column":8},"if_cond":null,"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"msg\"","value":"msg"}},"filename":"assert-01.k","line":2,"column":10,"end_line":2,"end_column":15}}},"filename":"assert-01.k","line":2,"column":0,"end_line":2,"end_column":15},{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-01.k","line":3,"column":7,"end_line":3,"end_column":11},"if_cond":null,"msg":null}},"filename":"assert-01.k","line":3,"column":0,"end_line":3,"end_column":11}],"comments":[]} diff --git a/kclvm/parser/testdata/assert-02.k.json b/kclvm/parser/testdata/assert-02.k.json deleted file mode 100644 index ff5701f2c..000000000 --- a/kclvm/parser/testdata/assert-02.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-02.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-02.k","line":1,"column":7,"end_line":1,"end_column":11},"if_cond":null,"msg":null}},"filename":"assert-02.k","line":1,"column":0,"end_line":1,"end_column":11},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-02.k","line":2,"column":7,"end_line":2,"end_column":8},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-02.k","line":2,"column":12,"end_line":2,"end_column":13}]}},"filename":"assert-02.k","line":2,"column":7,"end_line":2,"end_column":13},"if_cond":null,"msg":null}},"filename":"assert-02.k","line":2,"column":0,"end_line":2,"end_column":13},{"node":{"Assign":{"targets":[{"node":{"names":["_x"],"pkgpath":"","ctx":"Store"},"filename":"assert-02.k","line":3,"column":0,"end_line":3,"end_column":2}],"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-02.k","line":3,"column":5,"end_line":3,"end_column":16},"type_annotation":null,"ty":null}},"filename":"assert-02.k","line":3,"column":0,"end_line":3,"end_column":16},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-02.k","line":4,"column":7,"end_line":4,"end_column":9},"ops":["Eq"],"comparators":[{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-02.k","line":4,"column":13,"end_line":4,"end_column":24}]}},"filename":"assert-02.k","line":4,"column":7,"end_line":4,"end_column":24},"if_cond":null,"msg":null}},"filename":"assert-02.k","line":4,"column":0,"end_line":4,"end_column":24}],"comments":[]} diff --git a/kclvm/parser/testdata/assert-03.k.json b/kclvm/parser/testdata/assert-03.k.json deleted file mode 100644 index c002fb290..000000000 --- a/kclvm/parser/testdata/assert-03.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-03.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"If":{"body":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-03.k","line":2,"column":11,"end_line":2,"end_column":15},"if_cond":null,"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"Error messgae\"","value":"Error messgae"}},"filename":"assert-03.k","line":2,"column":17,"end_line":2,"end_column":32}}},"filename":"assert-03.k","line":2,"column":4,"end_line":2,"end_column":32},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-03.k","line":3,"column":11,"end_line":3,"end_column":12},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-03.k","line":3,"column":16,"end_line":3,"end_column":17}]}},"filename":"assert-03.k","line":3,"column":11,"end_line":3,"end_column":17},"if_cond":null,"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"\"","value":""}},"filename":"assert-03.k","line":3,"column":19,"end_line":3,"end_column":21}}},"filename":"assert-03.k","line":3,"column":4,"end_line":3,"end_column":21},{"node":{"Assign":{"targets":[{"node":{"names":["_x"],"pkgpath":"","ctx":"Store"},"filename":"assert-03.k","line":4,"column":4,"end_line":4,"end_column":6}],"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-03.k","line":4,"column":9,"end_line":4,"end_column":20},"type_annotation":null,"ty":null}},"filename":"assert-03.k","line":4,"column":4,"end_line":4,"end_column":20},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-03.k","line":5,"column":11,"end_line":5,"end_column":13},"ops":["Eq"],"comparators":[{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-03.k","line":5,"column":17,"end_line":5,"end_column":28}]}},"filename":"assert-03.k","line":5,"column":11,"end_line":5,"end_column":28},"if_cond":null,"msg":null}},"filename":"assert-03.k","line":5,"column":4,"end_line":5,"end_column":28}],"cond":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-03.k","line":1,"column":3,"end_line":1,"end_column":7},"orelse":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"False"}},"filename":"assert-03.k","line":7,"column":11,"end_line":7,"end_column":16},"if_cond":null,"msg":null}},"filename":"assert-03.k","line":7,"column":4,"end_line":7,"end_column":16}]}},"filename":"assert-03.k","line":1,"column":0,"end_line":8,"end_column":1}],"comments":[]} diff --git a/kclvm/parser/testdata/assert-if-0.k.json b/kclvm/parser/testdata/assert-if-0.k.json deleted file mode 100644 index a8ce96f5a..000000000 --- a/kclvm/parser/testdata/assert-if-0.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-if-0.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-if-0.k","line":1,"column":7,"end_line":1,"end_column":11},"if_cond":null,"msg":null}},"filename":"assert-if-0.k","line":1,"column":0,"end_line":1,"end_column":11},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-0.k","line":2,"column":7,"end_line":2,"end_column":8},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-0.k","line":2,"column":12,"end_line":2,"end_column":13}]}},"filename":"assert-if-0.k","line":2,"column":7,"end_line":2,"end_column":13},"if_cond":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-if-0.k","line":2,"column":17,"end_line":2,"end_column":21},"msg":null}},"filename":"assert-if-0.k","line":2,"column":0,"end_line":2,"end_column":21},{"node":{"Assign":{"targets":[{"node":{"names":["_x"],"pkgpath":"","ctx":"Store"},"filename":"assert-if-0.k","line":3,"column":0,"end_line":3,"end_column":2}],"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-0.k","line":3,"column":5,"end_line":3,"end_column":16},"type_annotation":null,"ty":null}},"filename":"assert-if-0.k","line":3,"column":0,"end_line":3,"end_column":16},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-0.k","line":4,"column":7,"end_line":4,"end_column":9},"ops":["Eq"],"comparators":[{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-0.k","line":4,"column":13,"end_line":4,"end_column":24}]}},"filename":"assert-if-0.k","line":4,"column":7,"end_line":4,"end_column":24},"if_cond":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-0.k","line":4,"column":28,"end_line":4,"end_column":30},"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"_x need to be 'good case'\"","value":"_x need to be 'good case'"}},"filename":"assert-if-0.k","line":4,"column":32,"end_line":4,"end_column":59}}},"filename":"assert-if-0.k","line":4,"column":0,"end_line":4,"end_column":59}],"comments":[]} diff --git a/kclvm/parser/testdata/assert-if-1.k.json b/kclvm/parser/testdata/assert-if-1.k.json deleted file mode 100644 index 86f28932d..000000000 --- a/kclvm/parser/testdata/assert-if-1.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-if-1.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-if-1.k","line":1,"column":7,"end_line":1,"end_column":11},"if_cond":{"node":{"NameConstantLit":{"value":"False"}},"filename":"assert-if-1.k","line":1,"column":15,"end_line":1,"end_column":20},"msg":null}},"filename":"assert-if-1.k","line":1,"column":0,"end_line":1,"end_column":20},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-1.k","line":2,"column":7,"end_line":2,"end_column":8},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-1.k","line":2,"column":12,"end_line":2,"end_column":13}]}},"filename":"assert-if-1.k","line":2,"column":7,"end_line":2,"end_column":13},"if_cond":{"node":{"NameConstantLit":{"value":"False"}},"filename":"assert-if-1.k","line":2,"column":17,"end_line":2,"end_column":22},"msg":null}},"filename":"assert-if-1.k","line":2,"column":0,"end_line":2,"end_column":22},{"node":{"Assign":{"targets":[{"node":{"names":["_x"],"pkgpath":"","ctx":"Store"},"filename":"assert-if-1.k","line":3,"column":0,"end_line":3,"end_column":2}],"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-1.k","line":3,"column":5,"end_line":3,"end_column":16},"type_annotation":null,"ty":null}},"filename":"assert-if-1.k","line":3,"column":0,"end_line":3,"end_column":16},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-1.k","line":4,"column":7,"end_line":4,"end_column":9},"ops":["Eq"],"comparators":[{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-1.k","line":4,"column":13,"end_line":4,"end_column":24}]}},"filename":"assert-if-1.k","line":4,"column":7,"end_line":4,"end_column":24},"if_cond":{"node":{"Unary":{"op":"Not","operand":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-1.k","line":4,"column":32,"end_line":4,"end_column":34}}},"filename":"assert-if-1.k","line":4,"column":28,"end_line":4,"end_column":34},"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"_x need to be 'good case'\"","value":"_x need to be 'good case'"}},"filename":"assert-if-1.k","line":4,"column":36,"end_line":4,"end_column":63}}},"filename":"assert-if-1.k","line":4,"column":0,"end_line":4,"end_column":63}],"comments":[]} diff --git a/kclvm/parser/testdata/assert-if-2.k.json b/kclvm/parser/testdata/assert-if-2.k.json deleted file mode 100644 index 483a60eb7..000000000 --- a/kclvm/parser/testdata/assert-if-2.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assert-if-2.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Schema":{"doc":"","name":{"node":"Data","filename":"assert-if-2.k","line":1,"column":7,"end_line":1,"end_column":11},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"Assert":{"test":{"node":{"NameConstantLit":{"value":"True"}},"filename":"assert-if-2.k","line":2,"column":11,"end_line":2,"end_column":15},"if_cond":{"node":{"NameConstantLit":{"value":"False"}},"filename":"assert-if-2.k","line":2,"column":19,"end_line":2,"end_column":24},"msg":null}},"filename":"assert-if-2.k","line":2,"column":4,"end_line":2,"end_column":24},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-2.k","line":3,"column":11,"end_line":3,"end_column":12},"ops":["Eq"],"comparators":[{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assert-if-2.k","line":3,"column":16,"end_line":3,"end_column":17}]}},"filename":"assert-if-2.k","line":3,"column":11,"end_line":3,"end_column":17},"if_cond":{"node":{"NameConstantLit":{"value":"False"}},"filename":"assert-if-2.k","line":3,"column":21,"end_line":3,"end_column":26},"msg":null}},"filename":"assert-if-2.k","line":3,"column":4,"end_line":3,"end_column":26},{"node":{"Assign":{"targets":[{"node":{"names":["_x"],"pkgpath":"","ctx":"Store"},"filename":"assert-if-2.k","line":4,"column":4,"end_line":4,"end_column":6}],"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-2.k","line":4,"column":9,"end_line":4,"end_column":20},"type_annotation":null,"ty":null}},"filename":"assert-if-2.k","line":4,"column":4,"end_line":4,"end_column":20},{"node":{"Assert":{"test":{"node":{"Compare":{"left":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-2.k","line":5,"column":11,"end_line":5,"end_column":13},"ops":["Eq"],"comparators":[{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"good case\"","value":"good case"}},"filename":"assert-if-2.k","line":5,"column":17,"end_line":5,"end_column":28}]}},"filename":"assert-if-2.k","line":5,"column":11,"end_line":5,"end_column":28},"if_cond":{"node":{"Unary":{"op":"Not","operand":{"node":{"Identifier":{"names":["_x"],"pkgpath":"","ctx":"Load"}},"filename":"assert-if-2.k","line":5,"column":36,"end_line":5,"end_column":38}}},"filename":"assert-if-2.k","line":5,"column":32,"end_line":5,"end_column":38},"msg":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"_x need to be 'good case'\"","value":"_x need to be 'good case'"}},"filename":"assert-if-2.k","line":5,"column":40,"end_line":5,"end_column":67}}},"filename":"assert-if-2.k","line":5,"column":4,"end_line":5,"end_column":67}],"decorators":[],"checks":[],"index_signature":null}},"filename":"assert-if-2.k","line":1,"column":0,"end_line":7,"end_column":0},{"node":{"Assign":{"targets":[{"node":{"names":["data"],"pkgpath":"","ctx":"Store"},"filename":"assert-if-2.k","line":7,"column":0,"end_line":7,"end_column":4}],"value":{"node":{"Schema":{"name":{"node":{"names":["Data"],"pkgpath":"","ctx":"Load"},"filename":"assert-if-2.k","line":7,"column":7,"end_line":7,"end_column":11},"args":[],"kwargs":[],"config":{"node":{"Config":{"items":[]}},"filename":"assert-if-2.k","line":7,"column":12,"end_line":7,"end_column":14}}},"filename":"assert-if-2.k","line":7,"column":7,"end_line":7,"end_column":14},"type_annotation":null,"ty":null}},"filename":"assert-if-2.k","line":7,"column":0,"end_line":7,"end_column":14}],"comments":[]} diff --git a/kclvm/parser/testdata/assign-01.k.json b/kclvm/parser/testdata/assign-01.k.json deleted file mode 100644 index a02084218..000000000 --- a/kclvm/parser/testdata/assign-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"assign-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"assign-01.k","line":1,"column":0,"end_line":1,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assign-01.k","line":1,"column":2,"end_line":1,"end_column":3},"type_annotation":null,"ty":null}},"filename":"assign-01.k","line":1,"column":0,"end_line":1,"end_column":3},{"node":{"Assign":{"targets":[{"node":{"names":["b"],"pkgpath":"","ctx":"Store"},"filename":"assign-01.k","line":2,"column":0,"end_line":2,"end_column":1}],"value":{"node":{"Binary":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"assign-01.k","line":2,"column":4,"end_line":2,"end_column":5},"op":{"Bin":"Add"},"right":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"assign-01.k","line":2,"column":8,"end_line":2,"end_column":9}}},"filename":"assign-01.k","line":2,"column":4,"end_line":2,"end_column":9},"type_annotation":null,"ty":null}},"filename":"assign-01.k","line":2,"column":0,"end_line":2,"end_column":9},{"node":{"Assign":{"targets":[{"node":{"names":["c"],"pkgpath":"","ctx":"Store"},"filename":"assign-01.k","line":3,"column":0,"end_line":3,"end_column":1}],"value":{"node":{"Binary":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"assign-01.k","line":3,"column":4,"end_line":3,"end_column":5},"op":{"Bin":"Add"},"right":{"node":{"Binary":{"left":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"assign-01.k","line":3,"column":8,"end_line":3,"end_column":9},"op":{"Bin":"Mul"},"right":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":3}}},"filename":"assign-01.k","line":3,"column":10,"end_line":3,"end_column":11}}},"filename":"assign-01.k","line":3,"column":8,"end_line":3,"end_column":11}}},"filename":"assign-01.k","line":3,"column":4,"end_line":3,"end_column":11},"type_annotation":null,"ty":null}},"filename":"assign-01.k","line":3,"column":0,"end_line":3,"end_column":11}],"comments":[]} diff --git a/kclvm/parser/testdata/config_expr-01.k.json b/kclvm/parser/testdata/config_expr-01.k.json deleted file mode 100644 index 9c8490bd9..000000000 --- a/kclvm/parser/testdata/config_expr-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"config_expr-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["config"],"pkgpath":"","ctx":"Store"},"filename":"config_expr-01.k","line":1,"column":0,"end_line":1,"end_column":6}],"value":{"node":{"Config":{"items":[]}},"filename":"config_expr-01.k","line":1,"column":9,"end_line":2,"end_column":1},"type_annotation":null,"ty":null}},"filename":"config_expr-01.k","line":1,"column":0,"end_line":2,"end_column":1}],"comments":[]} diff --git a/kclvm/parser/testdata/config_expr-02.k.json b/kclvm/parser/testdata/config_expr-02.k.json deleted file mode 100644 index 401df00b1..000000000 --- a/kclvm/parser/testdata/config_expr-02.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"config_expr-02.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["config"],"pkgpath":"","ctx":"Store"},"filename":"config_expr-02.k","line":1,"column":0,"end_line":1,"end_column":6}],"value":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["k1"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-02.k","line":2,"column":4,"end_line":2,"end_column":6},"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":111}}},"filename":"config_expr-02.k","line":2,"column":9,"end_line":2,"end_column":12},"operation":"Override","insert_index":-1},"filename":"config_expr-02.k","line":2,"column":4,"end_line":2,"end_column":12},{"node":{"key":{"node":{"Identifier":{"names":["k2"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-02.k","line":3,"column":4,"end_line":3,"end_column":6},"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":222}}},"filename":"config_expr-02.k","line":3,"column":9,"end_line":3,"end_column":12},"operation":"Override","insert_index":-1},"filename":"config_expr-02.k","line":3,"column":4,"end_line":3,"end_column":12}]}},"filename":"config_expr-02.k","line":1,"column":9,"end_line":4,"end_column":1},"type_annotation":null,"ty":null}},"filename":"config_expr-02.k","line":1,"column":0,"end_line":4,"end_column":1}],"comments":[]} diff --git a/kclvm/parser/testdata/config_expr-03.k.json b/kclvm/parser/testdata/config_expr-03.k.json deleted file mode 100644 index 7007da898..000000000 --- a/kclvm/parser/testdata/config_expr-03.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"config_expr-03.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["config"],"pkgpath":"","ctx":"Store"},"filename":"config_expr-03.k","line":3,"column":0,"end_line":3,"end_column":6}],"value":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":4,"column":4,"end_line":4,"end_column":8},"value":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["env"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":5,"column":8,"end_line":5,"end_column":11},"value":{"node":{"List":{"elts":[{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["name"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":6,"column":13,"end_line":6,"end_column":17},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"ENV_1\"","value":"ENV_1"}},"filename":"config_expr-03.k","line":6,"column":19,"end_line":6,"end_column":26},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":6,"column":13,"end_line":6,"end_column":26},{"node":{"key":{"node":{"Identifier":{"names":["value"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":6,"column":28,"end_line":6,"end_column":33},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"1\"","value":"1"}},"filename":"config_expr-03.k","line":6,"column":35,"end_line":6,"end_column":38},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":6,"column":28,"end_line":6,"end_column":38}]}},"filename":"config_expr-03.k","line":6,"column":12,"end_line":6,"end_column":39}],"ctx":"Load"}},"filename":"config_expr-03.k","line":5,"column":13,"end_line":7,"end_column":9},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":5,"column":8,"end_line":7,"end_column":9}]}},"filename":"config_expr-03.k","line":4,"column":10,"end_line":8,"end_column":5},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":4,"column":4,"end_line":8,"end_column":5},{"node":{"key":{"node":{"Identifier":{"names":["main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":9,"column":4,"end_line":9,"end_column":8},"value":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["env"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":10,"column":8,"end_line":10,"end_column":11},"value":{"node":{"List":{"elts":[{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["name"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":11,"column":13,"end_line":11,"end_column":17},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"ENV_2\"","value":"ENV_2"}},"filename":"config_expr-03.k","line":11,"column":19,"end_line":11,"end_column":26},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":11,"column":13,"end_line":11,"end_column":26},{"node":{"key":{"node":{"Identifier":{"names":["value"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-03.k","line":11,"column":28,"end_line":11,"end_column":33},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"2\"","value":"2"}},"filename":"config_expr-03.k","line":11,"column":35,"end_line":11,"end_column":38},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":11,"column":28,"end_line":11,"end_column":38}]}},"filename":"config_expr-03.k","line":11,"column":12,"end_line":11,"end_column":39}],"ctx":"Load"}},"filename":"config_expr-03.k","line":10,"column":15,"end_line":12,"end_column":9},"operation":"Insert","insert_index":-1},"filename":"config_expr-03.k","line":10,"column":8,"end_line":12,"end_column":9}]}},"filename":"config_expr-03.k","line":9,"column":10,"end_line":13,"end_column":5},"operation":"Union","insert_index":-1},"filename":"config_expr-03.k","line":9,"column":4,"end_line":13,"end_column":5}]}},"filename":"config_expr-03.k","line":3,"column":9,"end_line":14,"end_column":1},"type_annotation":null,"ty":null}},"filename":"config_expr-03.k","line":3,"column":0,"end_line":14,"end_column":1}],"comments":[{"node":{"text":"# test/grammar/attr_operator/config_inside/insert/dict_0/main.k"},"filename":"config_expr-03.k","line":1,"column":0,"end_line":1,"end_column":63}]} diff --git a/kclvm/parser/testdata/config_expr-04.k.json b/kclvm/parser/testdata/config_expr-04.k.json deleted file mode 100644 index a52a324dc..000000000 --- a/kclvm/parser/testdata/config_expr-04.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"config_expr-04.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Schema":{"doc":"","name":{"node":"Env","filename":"config_expr-04.k","line":3,"column":7,"end_line":3,"end_column":10},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"SchemaAttr":{"doc":"","name":{"node":"name","filename":"config_expr-04.k","line":4,"column":4,"end_line":4,"end_column":8},"type_str":{"node":"str","filename":"config_expr-04.k","line":4,"column":10,"end_line":4,"end_column":13},"op":null,"value":null,"is_optional":false,"decorators":[],"ty":{"node":{"Basic":"Str"},"filename":"config_expr-04.k","line":4,"column":10,"end_line":4,"end_column":13}}},"filename":"config_expr-04.k","line":4,"column":4,"end_line":4,"end_column":13},{"node":{"SchemaAttr":{"doc":"","name":{"node":"value","filename":"config_expr-04.k","line":5,"column":4,"end_line":5,"end_column":9},"type_str":{"node":"str","filename":"config_expr-04.k","line":5,"column":11,"end_line":5,"end_column":14},"op":null,"value":null,"is_optional":false,"decorators":[],"ty":{"node":{"Basic":"Str"},"filename":"config_expr-04.k","line":5,"column":11,"end_line":5,"end_column":14}}},"filename":"config_expr-04.k","line":5,"column":4,"end_line":5,"end_column":14}],"decorators":[],"checks":[],"index_signature":null}},"filename":"config_expr-04.k","line":3,"column":0,"end_line":7,"end_column":0},{"node":{"Schema":{"doc":"","name":{"node":"Main","filename":"config_expr-04.k","line":7,"column":7,"end_line":7,"end_column":11},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"SchemaAttr":{"doc":"","name":{"node":"env","filename":"config_expr-04.k","line":8,"column":4,"end_line":8,"end_column":7},"type_str":{"node":"[Env]","filename":"config_expr-04.k","line":8,"column":9,"end_line":8,"end_column":14},"op":null,"value":null,"is_optional":false,"decorators":[],"ty":{"node":{"List":{"inner_type":{"node":{"Named":{"names":["Env"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":8,"column":10,"end_line":8,"end_column":13}}},"filename":"config_expr-04.k","line":8,"column":9,"end_line":8,"end_column":14}}},"filename":"config_expr-04.k","line":8,"column":4,"end_line":8,"end_column":14}],"decorators":[],"checks":[],"index_signature":null}},"filename":"config_expr-04.k","line":7,"column":0,"end_line":10,"end_column":0},{"node":{"Schema":{"doc":"","name":{"node":"Config","filename":"config_expr-04.k","line":10,"column":7,"end_line":10,"end_column":13},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"SchemaAttr":{"doc":"","name":{"node":"main","filename":"config_expr-04.k","line":11,"column":4,"end_line":11,"end_column":8},"type_str":{"node":"Main","filename":"config_expr-04.k","line":11,"column":10,"end_line":11,"end_column":14},"op":null,"value":null,"is_optional":false,"decorators":[],"ty":{"node":{"Named":{"names":["Main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":11,"column":10,"end_line":11,"end_column":14}}},"filename":"config_expr-04.k","line":11,"column":4,"end_line":11,"end_column":14}],"decorators":[],"checks":[],"index_signature":null}},"filename":"config_expr-04.k","line":10,"column":0,"end_line":13,"end_column":0},{"node":{"Assign":{"targets":[{"node":{"names":["_main"],"pkgpath":"","ctx":"Store"},"filename":"config_expr-04.k","line":13,"column":0,"end_line":13,"end_column":5}],"value":{"node":{"Schema":{"name":{"node":{"names":["Main"],"pkgpath":"","ctx":"Load"},"filename":"config_expr-04.k","line":13,"column":8,"end_line":13,"end_column":12},"args":[],"kwargs":[],"config":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["env"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":14,"column":4,"end_line":14,"end_column":7},"value":{"node":{"List":{"elts":[{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["name"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":15,"column":9,"end_line":15,"end_column":13},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"ENV_1\"","value":"ENV_1"}},"filename":"config_expr-04.k","line":15,"column":15,"end_line":15,"end_column":22},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":15,"column":9,"end_line":15,"end_column":22},{"node":{"key":{"node":{"Identifier":{"names":["value"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":15,"column":24,"end_line":15,"end_column":29},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"1\"","value":"1"}},"filename":"config_expr-04.k","line":15,"column":31,"end_line":15,"end_column":34},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":15,"column":24,"end_line":15,"end_column":34}]}},"filename":"config_expr-04.k","line":15,"column":8,"end_line":15,"end_column":35}],"ctx":"Load"}},"filename":"config_expr-04.k","line":14,"column":9,"end_line":16,"end_column":5},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":14,"column":4,"end_line":16,"end_column":5}]}},"filename":"config_expr-04.k","line":13,"column":13,"end_line":17,"end_column":1}}},"filename":"config_expr-04.k","line":13,"column":8,"end_line":17,"end_column":1},"type_annotation":null,"ty":null}},"filename":"config_expr-04.k","line":13,"column":0,"end_line":17,"end_column":1},{"node":{"Assign":{"targets":[{"node":{"names":["config"],"pkgpath":"","ctx":"Store"},"filename":"config_expr-04.k","line":19,"column":0,"end_line":19,"end_column":6}],"value":{"node":{"Schema":{"name":{"node":{"names":["Config"],"pkgpath":"","ctx":"Load"},"filename":"config_expr-04.k","line":19,"column":9,"end_line":19,"end_column":15},"args":[],"kwargs":[],"config":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":20,"column":4,"end_line":20,"end_column":8},"value":{"node":{"Identifier":{"names":["_main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":20,"column":10,"end_line":20,"end_column":15},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":20,"column":4,"end_line":20,"end_column":15},{"node":{"key":{"node":{"Identifier":{"names":["main"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":21,"column":4,"end_line":21,"end_column":8},"value":{"node":{"Schema":{"name":{"node":{"names":["Main"],"pkgpath":"","ctx":"Load"},"filename":"config_expr-04.k","line":21,"column":10,"end_line":21,"end_column":14},"args":[],"kwargs":[],"config":{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["env"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":22,"column":8,"end_line":22,"end_column":11},"value":{"node":{"List":{"elts":[{"node":{"Config":{"items":[{"node":{"key":{"node":{"Identifier":{"names":["name"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":23,"column":13,"end_line":23,"end_column":17},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"ENV_2\"","value":"ENV_2"}},"filename":"config_expr-04.k","line":23,"column":19,"end_line":23,"end_column":26},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":23,"column":13,"end_line":23,"end_column":26},{"node":{"key":{"node":{"Identifier":{"names":["value"],"pkgpath":"","ctx":"Load"}},"filename":"config_expr-04.k","line":23,"column":28,"end_line":23,"end_column":33},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"2\"","value":"2"}},"filename":"config_expr-04.k","line":23,"column":35,"end_line":23,"end_column":38},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":23,"column":28,"end_line":23,"end_column":38}]}},"filename":"config_expr-04.k","line":23,"column":12,"end_line":23,"end_column":39}],"ctx":"Load"}},"filename":"config_expr-04.k","line":22,"column":15,"end_line":24,"end_column":9},"operation":"Insert","insert_index":-1},"filename":"config_expr-04.k","line":22,"column":8,"end_line":24,"end_column":9}]}},"filename":"config_expr-04.k","line":21,"column":15,"end_line":25,"end_column":5}}},"filename":"config_expr-04.k","line":21,"column":10,"end_line":25,"end_column":5},"operation":"Union","insert_index":-1},"filename":"config_expr-04.k","line":21,"column":4,"end_line":25,"end_column":5}]}},"filename":"config_expr-04.k","line":19,"column":16,"end_line":26,"end_column":1}}},"filename":"config_expr-04.k","line":19,"column":9,"end_line":26,"end_column":1},"type_annotation":null,"ty":null}},"filename":"config_expr-04.k","line":19,"column":0,"end_line":26,"end_column":1}],"comments":[{"node":{"text":"# test/grammar/attr_operator/config_inside/insert/schema_0/main.k"},"filename":"config_expr-04.k","line":1,"column":0,"end_line":1,"end_column":65}]} diff --git a/kclvm/parser/testdata/hello_win.k.json b/kclvm/parser/testdata/hello_win.k.json deleted file mode 100644 index 6693c2dad..000000000 --- a/kclvm/parser/testdata/hello_win.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"hello_win.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Schema":{"doc":"","name":{"node":"Person","filename":"hello_win.k","line":2,"column":7,"end_line":2,"end_column":13},"parent_name":null,"for_host_name":null,"is_mixin":false,"is_protocol":false,"args":null,"mixins":[],"body":[{"node":{"SchemaAttr":{"doc":"","name":{"node":"name","filename":"hello_win.k","line":3,"column":4,"end_line":3,"end_column":8},"type_str":{"node":"str","filename":"hello_win.k","line":3,"column":10,"end_line":3,"end_column":13},"op":{"Aug":"Assign"},"value":{"node":{"StringLit":{"is_long_string":false,"raw_value":"\"kcl\"","value":"kcl"}},"filename":"hello_win.k","line":3,"column":16,"end_line":3,"end_column":21},"is_optional":false,"decorators":[],"ty":{"node":{"Basic":"Str"},"filename":"hello_win.k","line":3,"column":10,"end_line":3,"end_column":13}}},"filename":"hello_win.k","line":3,"column":4,"end_line":3,"end_column":21}],"decorators":[],"checks":[],"index_signature":null}},"filename":"hello_win.k","line":2,"column":0,"end_line":5,"end_column":0},{"node":{"Assign":{"targets":[{"node":{"names":["x0"],"pkgpath":"","ctx":"Store"},"filename":"hello_win.k","line":5,"column":0,"end_line":5,"end_column":2}],"value":{"node":{"Schema":{"name":{"node":{"names":["Person"],"pkgpath":"","ctx":"Load"},"filename":"hello_win.k","line":5,"column":5,"end_line":5,"end_column":11},"args":[],"kwargs":[],"config":{"node":{"Config":{"items":[]}},"filename":"hello_win.k","line":5,"column":12,"end_line":5,"end_column":14}}},"filename":"hello_win.k","line":5,"column":5,"end_line":5,"end_column":14},"type_annotation":null,"ty":null}},"filename":"hello_win.k","line":5,"column":0,"end_line":5,"end_column":14}],"comments":[]} diff --git a/kclvm/parser/testdata/if-01.k.json b/kclvm/parser/testdata/if-01.k.json deleted file mode 100644 index 0c994b60c..000000000 --- a/kclvm/parser/testdata/if-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"if-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"if-01.k","line":1,"column":0,"end_line":1,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"if-01.k","line":1,"column":4,"end_line":1,"end_column":5},"type_annotation":null,"ty":null}},"filename":"if-01.k","line":1,"column":0,"end_line":1,"end_column":5},{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["bbb"],"pkgpath":"","ctx":"Store"},"filename":"if-01.k","line":4,"column":4,"end_line":4,"end_column":7}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"if-01.k","line":4,"column":10,"end_line":4,"end_column":11},"type_annotation":null,"ty":null}},"filename":"if-01.k","line":4,"column":4,"end_line":4,"end_column":11}],"cond":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"if-01.k","line":3,"column":3,"end_line":3,"end_column":4},"orelse":[]}},"filename":"if-01.k","line":3,"column":0,"end_line":4,"end_column":12}],"comments":[]} diff --git a/kclvm/parser/testdata/if-02.k b/kclvm/parser/testdata/if-02.k index 5132d411e..e66aed39a 100644 --- a/kclvm/parser/testdata/if-02.k +++ b/kclvm/parser/testdata/if-02.k @@ -8,3 +8,4 @@ elif a + 100: ddd = 4 else: eee = 5 + fff = 6 diff --git a/kclvm/parser/testdata/if-02.k.json b/kclvm/parser/testdata/if-02.k.json deleted file mode 100644 index 7a811ea94..000000000 --- a/kclvm/parser/testdata/if-02.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"if-02.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"if-02.k","line":1,"column":0,"end_line":1,"end_column":1}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"if-02.k","line":1,"column":4,"end_line":1,"end_column":5},"type_annotation":null,"ty":null}},"filename":"if-02.k","line":1,"column":0,"end_line":1,"end_column":5},{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["bbb"],"pkgpath":"","ctx":"Store"},"filename":"if-02.k","line":4,"column":4,"end_line":4,"end_column":7}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":2}}},"filename":"if-02.k","line":4,"column":10,"end_line":4,"end_column":11},"type_annotation":null,"ty":null}},"filename":"if-02.k","line":4,"column":4,"end_line":4,"end_column":11}],"cond":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"if-02.k","line":3,"column":3,"end_line":3,"end_column":4},"orelse":[{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["ccc"],"pkgpath":"","ctx":"Store"},"filename":"if-02.k","line":6,"column":4,"end_line":6,"end_column":7}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":3}}},"filename":"if-02.k","line":6,"column":10,"end_line":6,"end_column":11},"type_annotation":null,"ty":null}},"filename":"if-02.k","line":6,"column":4,"end_line":6,"end_column":11}],"cond":{"node":{"Binary":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"if-02.k","line":5,"column":5,"end_line":5,"end_column":6},"op":{"Bin":"Add"},"right":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":10}}},"filename":"if-02.k","line":5,"column":9,"end_line":5,"end_column":11}}},"filename":"if-02.k","line":5,"column":5,"end_line":5,"end_column":11},"orelse":[{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["ddd"],"pkgpath":"","ctx":"Store"},"filename":"if-02.k","line":8,"column":4,"end_line":8,"end_column":7}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":4}}},"filename":"if-02.k","line":8,"column":10,"end_line":8,"end_column":11},"type_annotation":null,"ty":null}},"filename":"if-02.k","line":8,"column":4,"end_line":8,"end_column":11}],"cond":{"node":{"Binary":{"left":{"node":{"Identifier":{"names":["a"],"pkgpath":"","ctx":"Load"}},"filename":"if-02.k","line":7,"column":5,"end_line":7,"end_column":6},"op":{"Bin":"Add"},"right":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":100}}},"filename":"if-02.k","line":7,"column":9,"end_line":7,"end_column":12}}},"filename":"if-02.k","line":7,"column":5,"end_line":7,"end_column":12},"orelse":[{"node":{"Assign":{"targets":[{"node":{"names":["eee"],"pkgpath":"","ctx":"Store"},"filename":"if-02.k","line":10,"column":4,"end_line":10,"end_column":7}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":5}}},"filename":"if-02.k","line":10,"column":10,"end_line":10,"end_column":11},"type_annotation":null,"ty":null}},"filename":"if-02.k","line":10,"column":4,"end_line":10,"end_column":11}]}},"filename":"if-02.k","line":7,"column":0,"end_line":9,"end_column":0}]}},"filename":"if-02.k","line":5,"column":0,"end_line":7,"end_column":0}]}},"filename":"if-02.k","line":3,"column":0,"end_line":10,"end_column":12}],"comments":[]} diff --git a/kclvm/parser/testdata/if-03.k.json b/kclvm/parser/testdata/if-03.k.json deleted file mode 100644 index b59063d18..000000000 --- a/kclvm/parser/testdata/if-03.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"if-03.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"If":{"body":[{"node":{"Assign":{"targets":[{"node":{"names":["a"],"pkgpath":"","ctx":"Store"},"filename":"if-03.k","line":1,"column":9,"end_line":1,"end_column":10}],"value":{"node":{"NumberLit":{"binary_suffix":null,"value":{"Int":1}}},"filename":"if-03.k","line":1,"column":13,"end_line":1,"end_column":14},"type_annotation":null,"ty":null}},"filename":"if-03.k","line":1,"column":9,"end_line":1,"end_column":14}],"cond":{"node":{"NameConstantLit":{"value":"True"}},"filename":"if-03.k","line":1,"column":3,"end_line":1,"end_column":7},"orelse":[]}},"filename":"if-03.k","line":1,"column":0,"end_line":1,"end_column":15}],"comments":[]} diff --git a/kclvm/parser/testdata/import-01.k.json b/kclvm/parser/testdata/import-01.k.json deleted file mode 100644 index d78fce55b..000000000 --- a/kclvm/parser/testdata/import-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"import-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"Import":{"path":"a1","rawpath":"a1","name":"a1","asname":null,"pkg_name":""}},"filename":"import-01.k","line":1,"column":0,"end_line":1,"end_column":9},{"node":{"Import":{"path":"a2","rawpath":"a2","name":"a2_pkg","asname":"a2_pkg","pkg_name":""}},"filename":"import-01.k","line":3,"column":0,"end_line":3,"end_column":19},{"node":{"Import":{"path":"subpkg.b1.c1","rawpath":"subpkg.b1.c1","name":"c1","asname":null,"pkg_name":""}},"filename":"import-01.k","line":5,"column":0,"end_line":5,"end_column":19},{"node":{"Import":{"path":".a3","rawpath":".a3","name":"a3","asname":null,"pkg_name":""}},"filename":"import-01.k","line":7,"column":0,"end_line":7,"end_column":10}],"comments":[]} diff --git a/kclvm/parser/testdata/type-01.k.json b/kclvm/parser/testdata/type-01.k.json deleted file mode 100644 index 546806291..000000000 --- a/kclvm/parser/testdata/type-01.k.json +++ /dev/null @@ -1 +0,0 @@ -{"filename":"type-01.k","pkg":"__main__","doc":"","name":"__main__","body":[{"node":{"TypeAlias":{"type_name":{"node":{"names":["a"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":1,"column":5,"end_line":1,"end_column":6},"type_value":{"node":"any","filename":"type-01.k","line":1,"column":9,"end_line":1,"end_column":12},"ty":{"node":"Any","filename":"type-01.k","line":1,"column":9,"end_line":1,"end_column":12}}},"filename":"type-01.k","line":1,"column":5,"end_line":1,"end_column":12},{"node":{"TypeAlias":{"type_name":{"node":{"names":["b"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":3,"column":5,"end_line":3,"end_column":6},"type_value":{"node":"bool","filename":"type-01.k","line":3,"column":9,"end_line":3,"end_column":13},"ty":{"node":{"Basic":"Bool"},"filename":"type-01.k","line":3,"column":9,"end_line":3,"end_column":13}}},"filename":"type-01.k","line":3,"column":5,"end_line":3,"end_column":13},{"node":{"TypeAlias":{"type_name":{"node":{"names":["c"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":4,"column":5,"end_line":4,"end_column":6},"type_value":{"node":"int","filename":"type-01.k","line":4,"column":9,"end_line":4,"end_column":12},"ty":{"node":{"Basic":"Int"},"filename":"type-01.k","line":4,"column":9,"end_line":4,"end_column":12}}},"filename":"type-01.k","line":4,"column":5,"end_line":4,"end_column":12},{"node":{"TypeAlias":{"type_name":{"node":{"names":["d"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":5,"column":5,"end_line":5,"end_column":6},"type_value":{"node":"float","filename":"type-01.k","line":5,"column":9,"end_line":5,"end_column":14},"ty":{"node":{"Basic":"Float"},"filename":"type-01.k","line":5,"column":9,"end_line":5,"end_column":14}}},"filename":"type-01.k","line":5,"column":5,"end_line":5,"end_column":14},{"node":{"TypeAlias":{"type_name":{"node":{"names":["e"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":6,"column":5,"end_line":6,"end_column":6},"type_value":{"node":"str","filename":"type-01.k","line":6,"column":9,"end_line":6,"end_column":12},"ty":{"node":{"Basic":"Str"},"filename":"type-01.k","line":6,"column":9,"end_line":6,"end_column":12}}},"filename":"type-01.k","line":6,"column":5,"end_line":6,"end_column":12},{"node":{"TypeAlias":{"type_name":{"node":{"names":["type_list1"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":8,"column":5,"end_line":8,"end_column":15},"type_value":{"node":"[]","filename":"type-01.k","line":8,"column":18,"end_line":8,"end_column":20},"ty":{"node":{"List":{"inner_type":null}},"filename":"type-01.k","line":8,"column":18,"end_line":8,"end_column":20}}},"filename":"type-01.k","line":8,"column":5,"end_line":8,"end_column":20},{"node":{"TypeAlias":{"type_name":{"node":{"names":["type_list2"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":9,"column":5,"end_line":9,"end_column":15},"type_value":{"node":"[[]]","filename":"type-01.k","line":9,"column":18,"end_line":9,"end_column":22},"ty":{"node":{"List":{"inner_type":{"node":{"List":{"inner_type":null}},"filename":"type-01.k","line":9,"column":19,"end_line":9,"end_column":21}}},"filename":"type-01.k","line":9,"column":18,"end_line":9,"end_column":22}}},"filename":"type-01.k","line":9,"column":5,"end_line":9,"end_column":22},{"node":{"TypeAlias":{"type_name":{"node":{"names":["type_list3"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":10,"column":5,"end_line":10,"end_column":15},"type_value":{"node":"[int]","filename":"type-01.k","line":10,"column":18,"end_line":10,"end_column":23},"ty":{"node":{"List":{"inner_type":{"node":{"Basic":"Int"},"filename":"type-01.k","line":10,"column":19,"end_line":10,"end_column":22}}},"filename":"type-01.k","line":10,"column":18,"end_line":10,"end_column":23}}},"filename":"type-01.k","line":10,"column":5,"end_line":10,"end_column":23},{"node":{"TypeAlias":{"type_name":{"node":{"names":["b"],"pkgpath":"","ctx":"Load"},"filename":"type-01.k","line":12,"column":5,"end_line":12,"end_column":6},"type_value":{"node":"int|str|[]|{:}","filename":"type-01.k","line":12,"column":9,"end_line":12,"end_column":29},"ty":{"node":{"Union":{"type_elements":[{"node":{"Basic":"Int"},"filename":"type-01.k","line":12,"column":9,"end_line":12,"end_column":12},{"node":{"Basic":"Str"},"filename":"type-01.k","line":12,"column":15,"end_line":12,"end_column":18},{"node":{"List":{"inner_type":null}},"filename":"type-01.k","line":12,"column":21,"end_line":12,"end_column":23},{"node":{"Dict":{"key_type":null,"value_type":null}},"filename":"type-01.k","line":12,"column":26,"end_line":12,"end_column":29}]}},"filename":"type-01.k","line":12,"column":9,"end_line":12,"end_column":29}}},"filename":"type-01.k","line":12,"column":5,"end_line":12,"end_column":29}],"comments":[]} diff --git a/kclvm/plugin/.gitignore b/kclvm/plugin/.gitignore deleted file mode 100644 index a4045b0f4..000000000 --- a/kclvm/plugin/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build -*.so -*.dll -target diff --git a/kclvm/plugin/Makefile b/kclvm/plugin/Makefile deleted file mode 100644 index 728058188..000000000 --- a/kclvm/plugin/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2021 The KCL Authors. All rights reserved. - -default: - swig -c++ -python kclvm_plugin.i - python3 -m black . - - cd ../runtime && cargo fmt && cargo build --release - - kclvm setup.py build_ext --inplace - kclvm setup.py install_lib - - @echo ------------------ - cd demo && kclvm hello.py - -swig: - swig -c++ -python kclvm_plugin.i - -clean: - -rm -rf build *.so *.dll diff --git a/kclvm/plugin/kclvm_plugin.cpp b/kclvm/plugin/kclvm_plugin.cpp deleted file mode 100644 index 001d49651..000000000 --- a/kclvm/plugin/kclvm_plugin.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -#include "kclvm_plugin.h" - -#include -#include - -static const int32_t kDefaultBufferSize = 1024*1024*10; - -static _kclvm_plugin_AppContextBase* g_self_ = NULL; -static uint64_t g_rust_invoke_json_ptr_ = 0; - -static const char* _invoke_json_proxy( - const char* method, - const char* args_json, - const char* kwargs_json -) { - if(g_self_ == NULL) { return ""; } - - static std::string jsonResult; - jsonResult = g_self_->_call_py_method(method, args_json, kwargs_json); - return jsonResult.c_str(); -} - -_kclvm_plugin_AppContextBase::_kclvm_plugin_AppContextBase(uint64_t rust_invoke_json_ptr) { - g_rust_invoke_json_ptr_ = rust_invoke_json_ptr; - assert(g_self_ == NULL); - g_self_ = this; -} -_kclvm_plugin_AppContextBase::~_kclvm_plugin_AppContextBase() { - g_rust_invoke_json_ptr_ = 0; - g_self_ = NULL; -} - -void _kclvm_plugin_AppContextBase::_clear_options() { - this->option_keys_.clear(); - this->option_values_.clear(); -} -void _kclvm_plugin_AppContextBase::_add_option(const std::string& key, const std::string& value) { - this->option_keys_.push_back(key); - this->option_values_.push_back(value); -} - -std::string _kclvm_plugin_AppContextBase::_run_app( - uint64_t _start_fn_ptr, - uint64_t _kclvm_main_ptr, // main.k => kclvm_main - int32_t strict_range_check, - int32_t disable_none, - int32_t disable_schema_check, - int32_t list_option_mode, - int32_t debug_mode, - int32_t buffer_size -) { - typedef int32_t (*kcl_run_t)( - uint64_t _kclvm_main_ptr, // main.k => kclvm_main - int32_t option_len, - const char** option_keys, - const char** option_values, - int32_t strict_range_check, - int32_t disable_none, - int32_t disable_schema_check, - int32_t list_option_mode, - int32_t debug_mode, - int32_t result_buffer_len, - char* result_buffer, - int32_t warn_buffer_len, - char* warn_buffer - ); - - int32_t _option_len = this->option_keys_.size(); - std::vector _option_keys(_option_len); - std::vector _option_values(_option_len); - - for(size_t i = 0; i < this->option_keys_.size(); i++) { - _option_keys[i] = (char*)this->option_keys_[i].c_str(); - _option_values[i] = (char*)this->option_values_[i].c_str(); - } - - this->buffer_.clear(); - this->warn_buffer_.clear(); - - if(buffer_size > 0) { - this->buffer_.resize(buffer_size, '\0'); - } else { - this->buffer_.resize(kDefaultBufferSize, '\0'); - } - - this->warn_buffer_.resize(10*1024*1924, '\0'); - - kcl_run_t _kcl_run = (kcl_run_t)(_start_fn_ptr); - int32_t result_len = _kcl_run( - _kclvm_main_ptr, - _option_len, - (const char**)(_option_keys.data()), - (const char**)(_option_values.data()), - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - this->buffer_.size()-1, - &this->buffer_[0], - this->warn_buffer_.size()-1, - &this->warn_buffer_[0] - ); - - if(result_len > 0) { - this->buffer_.resize(result_len); - } else if (result_len == 0) { - this->buffer_ = "{}"; - } else { - this->buffer_ = "{\"error\": \"buffer size limit\"}"; - } - - this->warn_buffer_.resize(strlen(&this->warn_buffer_[0])); - - return this->buffer_; -} - -std::string _kclvm_plugin_AppContextBase::_get_warn() { - return this->warn_buffer_; -} - -uint64_t _kclvm_plugin_AppContextBase::_get_cxx_invoke_proxy_ptr() { - return uint64_t(_invoke_json_proxy); -} - -std::string _kclvm_plugin_AppContextBase::_call_rust_method( - const std::string& name, - const std::string& args_json, - const std::string& kwargs_json -) { - typedef const char* (*invoke_fn_t)( - const char* method, - const char* args_json, - const char* kwargs_json - ); - invoke_fn_t fn = (invoke_fn_t)(g_rust_invoke_json_ptr_); - return fn(name.c_str(), args_json.c_str(), kwargs_json.c_str()); -} - -std::string _kclvm_plugin_AppContextBase::_call_py_method( - const std::string& name, - const std::string& args_json, - const std::string& kwargs_json -) { - return "implemented in Python!!!"; -} diff --git a/kclvm/plugin/kclvm_plugin.h b/kclvm/plugin/kclvm_plugin.h deleted file mode 100644 index bc0e19df5..000000000 --- a/kclvm/plugin/kclvm_plugin.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -#pragma once - -#ifndef __cplusplus -#error "please use C++" -#endif - -#include -#include -#include -#include - -#include -#include - -// ---------------------------------------------------------------------------- - -class _kclvm_plugin_AppContextBase { - std::string buffer_; - std::string warn_buffer_; - std::vector option_keys_; - std::vector option_values_; - -public: - _kclvm_plugin_AppContextBase(uint64_t rust_invoke_json_ptr); - virtual ~_kclvm_plugin_AppContextBase(); - - void _clear_options(); - void _add_option(const std::string& key, const std::string& value); - - std::string _run_app( - uint64_t _start_fn_ptr, - uint64_t _kclvm_main_ptr, // main.k => kclvm_main - int32_t strict_range_check, - int32_t disable_none, - int32_t disable_schema_check, - int32_t list_option_mode, - int32_t debug_mode, - int32_t buffer_size - ); - - std::string _get_warn(); - - uint64_t _get_cxx_invoke_proxy_ptr(); - - std::string _call_rust_method( - const std::string& name, - const std::string& args_json, - const std::string& kwargs_json - ); - - virtual std::string _call_py_method( - const std::string& name, - const std::string& args_json, - const std::string& kwargs_json - ); -}; - -// ---------------------------------------------------------------------------- -// END -// ---------------------------------------------------------------------------- diff --git a/kclvm/plugin/kclvm_plugin.i b/kclvm/plugin/kclvm_plugin.i deleted file mode 100644 index 6fc417d65..000000000 --- a/kclvm/plugin/kclvm_plugin.i +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -// http://www.swig.org/Doc3.0/Python.html#Python_directors - -% module(directors = "1") kclvm_plugin - - % { -#define SWIG_FILE_WITH_INIT -#include "kclvm_plugin.h" - % } - - // ---------------------------------------------------------------------------- - // C/C++ code - // ---------------------------------------------------------------------------- - - % include "stdint.i" % include "std_string.i" - - % feature("director") _kclvm_plugin_AppContextBase; -class _kclvm_plugin_AppContextBase -{ -public: - _kclvm_plugin_AppContextBase(uint64_t rust_invoke_json_ptr); - virtual ~_kclvm_plugin_AppContextBase(); - - void _clear_options(); - void _add_option(const std::string &key, const std::string &value); - - std::string _run_app( - uint64_t _start_fn_ptr, - uint64_t _kclvm_main_ptr, // main.k => kclvm_main - int32_t strict_range_check, - int32_t disable_none, - int32_t disable_schema_check, - int32_t list_option_mode, - int32_t debug_mode, - int32_t buffer_size); - - std::string _get_warn(); - - uint64_t _get_cxx_invoke_proxy_ptr(); - - std::string _call_rust_method( - const std::string &name, - const std::string &args_json, - const std::string &kwargs_json); - - virtual std::string _call_py_method( - const std::string &name, - const std::string &args_json, - const std::string &kwargs_json); -}; - -// ---------------------------------------------------------------------------- -// Python code -// ---------------------------------------------------------------------------- - -% pythonbegin % {import sys import typing import ctypes import os import importlib import json import inspect - - import kclvm.kcl.info as kcl_info import kclvm.compiler.extension.plugin.plugin as kcl_plugin import kclvm.api.object.internal.option as option import kclvm.api.object as objpkg % } - - % pythoncode % -{ -class AppContext(_kclvm_plugin_AppContextBase): - def __init__(self, app_dll_name: str): - self._is_windows: bool = os.name == "nt" - - self._start_func_name: str = "" - self._app_dll_name = app_dll_name - self._plugin_dict: typing.Dict[str, any] = {} - - if self._is_windows: - _executable_root = os.path.dirname(sys.executable) - self._kclvm_runtime = ctypes.CDLL(f"{_executable_root}\\kclvm_cli_cdylib.dll") - self._app_lib = ctypes.CDLL(app_dll_name) - else: - self._kclvm_runtime = ctypes.CDLL(app_dll_name) - self._app_lib = ctypes.CDLL(app_dll_name) - - self._kclvm_runtime.kclvm_plugin_init.restype = None - self._kclvm_runtime.kclvm_plugin_init.argtypes = [ctypes.c_longlong] - - self._kclvm_runtime.kclvm_plugin_invoke_json.restype = ctypes.c_char_p - self._kclvm_runtime.kclvm_plugin_invoke_json.argtypes = [ - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_char_p - ] - - rust_invoke_json_ptr = ctypes.cast(self._kclvm_runtime.kclvm_plugin_invoke_json, ctypes.c_void_p).value - super().__init__(rust_invoke_json_ptr) - - self._kclvm_runtime.kclvm_plugin_init(self._get_cxx_invoke_proxy_ptr()) - - def InitOptions(self, arguments): - self._clear_options() - for kv in arguments or []: - key, value = kv - if isinstance(value, (bool, list, dict)): - value = json.dumps(value) - elif isinstance(value, str): - value = '"{}"'.format(value.replace('"', '\\"')) - else: - value = str(value) - self._add_option(key, value) - - def RunApp(self, *, - start_func_name='_kcl_run', - strict_range_check=None, - disable_none=None, - disable_schema_check=None, - list_option_mode=None, - debug_mode=None, - buffer_size=0 - ) -> str: - self._start_func_name = start_func_name - - _start = getattr(self._kclvm_runtime, start_func_name) - _start_ptr = ctypes.cast(_start, ctypes.c_void_p).value - - if hasattr(self._app_lib, 'kclvm_main'): - _kclvm_main = getattr(self._app_lib, 'kclvm_main') - _kclvm_main_ptr = ctypes.cast(_kclvm_main, ctypes.c_void_p).value - elif hasattr(self._app_lib, 'kclvm_main_win'): - _kclvm_main = getattr(self._app_lib, 'kclvm_main_win') - _kclvm_main_ptr = ctypes.cast(_kclvm_main, ctypes.c_void_p).value - else: - _kclvm_main_ptr = 0 - - if disable_none: - disable_none = 1 - else: - disable_none = 0 - - if strict_range_check: - strict_range_check = 1 - else: - strict_range_check = 0 - - if disable_schema_check: - disable_schema_check = 1 - else: - disable_schema_check = 0 - - if list_option_mode: - list_option_mode = 1 - else: - list_option_mode = 0 - - if debug_mode: - debug_mode = 1 - else: - debug_mode = 0 - - json_result = self._run_app(_start_ptr, _kclvm_main_ptr, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - buffer_size - ) - return json_result - - def GetWarn(self) -> str: - json_warn_result = self._get_warn() - return json_warn_result - - def CallMethod(self, name:str, args_json:str, kwargs_json:str) -> str: - return self._call_rust_method(name, args_json, kwargs_json) - - def _call_py_method(self, name:str, args_json:str, kwargs_json:str) -> str: -try: - return self._call_py_method_unsafe(name, args_json, kwargs_json) - except Exception as e: - return json.dumps({ "__kcl_PanicInfo__": f"{e}" }) - - def _get_plugin(self, plugin_name:str) -> typing.Optional[any]: - if plugin_name in self._plugin_dict: - return self._plugin_dict[plugin_name] - - module = kcl_plugin.get_plugin(plugin_name) - self._plugin_dict[plugin_name] = module - return module - - def _call_py_method_unsafe(self, name:str, args_json:str, kwargs_json:str) -> str: - dotIdx = name.rfind(".") - if dotIdx < 0: - return "" - - modulePath = name[:dotIdx] - mathodName = name[dotIdx+1:] - - plugin_name = modulePath[modulePath.rfind('.')+1:] - - module = self._get_plugin(plugin_name) - mathodFunc = None - - for func_name, func in inspect.getmembers(module): - if func_name == kcl_info.demangle(mathodName): - mathodFunc = func - break - - args = [] - kwargs = {} - - if args_json: - args = json.loads(args_json) - if not isinstance(args, list): - return "" - if kwargs_json: - kwargs = json.loads(kwargs_json) - if not isinstance(kwargs, dict): - return "" - - result = mathodFunc(*args, **kwargs) - return json.dumps(result) - - def __del__(self): - self._free_library() - - def _free_library(self): - if os.name == 'nt': - import ctypes.wintypes - kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) - kernel32.FreeLibrary.argtypes = [ctypes.wintypes.HMODULE] - kernel32.FreeLibrary(self._app_lib._handle) - self._app_lib = None -#kernel32 = ctypes.WinDLL('kernel32', use_last_error = True) -#kernel32.FreeLibrary.argtypes = [ctypes.wintypes.HMODULE] -#kernel32.FreeLibrary(self._app_dll._handle) - pass - else: -#libdl = ctypes.CDLL("libdl.so") -#libdl.dlclose(self._app_dll._handle) - pass - - -def main(args: typing.List[str]): - if len(args) < 2: - print("usage: kclvm_plugin app.[dll|dylib|so]") - sys._exit(1) - - ctx = AppContext(args[1]) - ctx.RunApp(args[2:]) - - -if __name__ == "__main__": - main(sys.argv) -% -} - -// ---------------------------------------------------------------------------- -// END -// ---------------------------------------------------------------------------- diff --git a/kclvm/plugin/kclvm_plugin.py b/kclvm/plugin/kclvm_plugin.py deleted file mode 100644 index fc462ef61..000000000 --- a/kclvm/plugin/kclvm_plugin.py +++ /dev/null @@ -1,423 +0,0 @@ -# This file was automatically generated by SWIG (http://www.swig.org). -# Version 3.0.12 -# -# Do not make changes to this file unless you know what you are doing--modify -# the SWIG interface file instead. - - -import sys -import typing -import ctypes -import os -import importlib -import json -import inspect - -import kclvm.kcl.info as kcl_info -import kclvm.compiler.extension.plugin.plugin as kcl_plugin -import kclvm.api.object.internal.option as option -import kclvm.api.object as objpkg - - -from sys import version_info as _swig_python_version_info - -if _swig_python_version_info >= (2, 7, 0): - - def swig_import_helper(): - import importlib - - pkg = __name__.rpartition(".")[0] - mname = ".".join((pkg, "_kclvm_plugin")).lstrip(".") - try: - return importlib.import_module(mname) - except ImportError: - return importlib.import_module("_kclvm_plugin") - - _kclvm_plugin = swig_import_helper() - del swig_import_helper -elif _swig_python_version_info >= (2, 6, 0): - - def swig_import_helper(): - from os.path import dirname - import imp - - fp = None - try: - fp, pathname, description = imp.find_module( - "_kclvm_plugin", [dirname(__file__)] - ) - except ImportError: - import _kclvm_plugin - - return _kclvm_plugin - try: - _mod = imp.load_module("_kclvm_plugin", fp, pathname, description) - finally: - if fp is not None: - fp.close() - return _mod - - _kclvm_plugin = swig_import_helper() - del swig_import_helper -else: - import _kclvm_plugin -del _swig_python_version_info - -try: - _swig_property = property -except NameError: - pass # Python < 2.2 doesn't have 'property'. - -try: - import builtins as __builtin__ -except ImportError: - import __builtin__ - - -def _swig_setattr_nondynamic(self, class_type, name, value, static=1): - if name == "thisown": - return self.this.own(value) - if name == "this": - if type(value).__name__ == "SwigPyObject": - self.__dict__[name] = value - return - method = class_type.__swig_setmethods__.get(name, None) - if method: - return method(self, value) - if not static: - if _newclass: - object.__setattr__(self, name, value) - else: - self.__dict__[name] = value - else: - raise AttributeError("You cannot add attributes to %s" % self) - - -def _swig_setattr(self, class_type, name, value): - return _swig_setattr_nondynamic(self, class_type, name, value, 0) - - -def _swig_getattr(self, class_type, name): - if name == "thisown": - return self.this.own() - method = class_type.__swig_getmethods__.get(name, None) - if method: - return method(self) - raise AttributeError( - "'%s' object has no attribute '%s'" % (class_type.__name__, name) - ) - - -def _swig_repr(self): - try: - strthis = "proxy of " + self.this.__repr__() - except __builtin__.Exception: - strthis = "" - return "<%s.%s; %s >" % ( - self.__class__.__module__, - self.__class__.__name__, - strthis, - ) - - -try: - _object = object - _newclass = 1 -except __builtin__.Exception: - - class _object: - pass - - _newclass = 0 - -try: - import weakref - - weakref_proxy = weakref.proxy -except __builtin__.Exception: - weakref_proxy = lambda x: x - - -class _kclvm_plugin_AppContextBase(_object): - __swig_setmethods__ = {} - __setattr__ = lambda self, name, value: _swig_setattr( - self, _kclvm_plugin_AppContextBase, name, value - ) - __swig_getmethods__ = {} - __getattr__ = lambda self, name: _swig_getattr( - self, _kclvm_plugin_AppContextBase, name - ) - __repr__ = _swig_repr - - def __init__(self, rust_invoke_json_ptr): - if self.__class__ == _kclvm_plugin_AppContextBase: - _self = None - else: - _self = self - this = _kclvm_plugin.new__kclvm_plugin_AppContextBase( - _self, rust_invoke_json_ptr - ) - try: - self.this.append(this) - except __builtin__.Exception: - self.this = this - - __swig_destroy__ = _kclvm_plugin.delete__kclvm_plugin_AppContextBase - __del__ = lambda self: None - - def _clear_options(self): - return _kclvm_plugin._kclvm_plugin_AppContextBase__clear_options(self) - - def _add_option(self, key, value): - return _kclvm_plugin._kclvm_plugin_AppContextBase__add_option(self, key, value) - - def _run_app( - self, - _start_fn_ptr, - _kclvm_main_ptr, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - buffer_size, - ): - return _kclvm_plugin._kclvm_plugin_AppContextBase__run_app( - self, - _start_fn_ptr, - _kclvm_main_ptr, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - buffer_size, - ) - - def _get_warn(self): - return _kclvm_plugin._kclvm_plugin_AppContextBase__get_warn(self) - - def _get_cxx_invoke_proxy_ptr(self): - return _kclvm_plugin._kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr( - self - ) - - def _call_rust_method(self, name, args_json, kwargs_json): - return _kclvm_plugin._kclvm_plugin_AppContextBase__call_rust_method( - self, name, args_json, kwargs_json - ) - - def _call_py_method(self, name, args_json, kwargs_json): - return _kclvm_plugin._kclvm_plugin_AppContextBase__call_py_method( - self, name, args_json, kwargs_json - ) - - def __disown__(self): - self.this.disown() - _kclvm_plugin.disown__kclvm_plugin_AppContextBase(self) - return weakref_proxy(self) - - -_kclvm_plugin_AppContextBase_swigregister = ( - _kclvm_plugin._kclvm_plugin_AppContextBase_swigregister -) -_kclvm_plugin_AppContextBase_swigregister(_kclvm_plugin_AppContextBase) - - -class AppContext(_kclvm_plugin_AppContextBase): - def __init__(self, app_dll_name: str): - self._is_windows: bool = os.name == "nt" - - self._start_func_name: str = "" - self._app_dll_name = app_dll_name - self._plugin_dict: typing.Dict[str, any] = {} - - if self._is_windows: - _executable_root = os.path.dirname(sys.executable) - self._kclvm_runtime = ctypes.CDLL(f"{_executable_root}\\kclvm_cli_cdylib.dll") - self._app_lib = ctypes.CDLL(app_dll_name) - else: - self._kclvm_runtime = ctypes.CDLL(app_dll_name) - self._app_lib = ctypes.CDLL(app_dll_name) - - self._kclvm_runtime.kclvm_plugin_init.restype = None - self._kclvm_runtime.kclvm_plugin_init.argtypes = [ctypes.c_longlong] - - self._kclvm_runtime.kclvm_plugin_invoke_json.restype = ctypes.c_char_p - self._kclvm_runtime.kclvm_plugin_invoke_json.argtypes = [ - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_char_p, - ] - - rust_invoke_json_ptr = ctypes.cast( - self._kclvm_runtime.kclvm_plugin_invoke_json, ctypes.c_void_p - ).value - super().__init__(rust_invoke_json_ptr) - - self._kclvm_runtime.kclvm_plugin_init(self._get_cxx_invoke_proxy_ptr()) - - def InitOptions(self, arguments): - self._clear_options() - for kv in arguments or []: - key, value = kv - if isinstance(value, (bool, list, dict)): - value = json.dumps(value) - elif isinstance(value, str): - value = '"{}"'.format(value.replace('"', '\\"')) - else: - value = str(value) - self._add_option(key, value) - - def RunApp( - self, - *, - start_func_name="_kcl_run", - strict_range_check=None, - disable_none=None, - disable_schema_check=None, - list_option_mode=None, - debug_mode=None, - buffer_size=0, - ) -> str: - self._start_func_name = start_func_name - - _start = getattr(self._kclvm_runtime, start_func_name) - _start_ptr = ctypes.cast(_start, ctypes.c_void_p).value - - if hasattr(self._app_lib, "kclvm_main"): - _kclvm_main = getattr(self._app_lib, "kclvm_main") - _kclvm_main_ptr = ctypes.cast(_kclvm_main, ctypes.c_void_p).value - elif hasattr(self._app_lib, "kclvm_main_win"): - _kclvm_main = getattr(self._app_lib, "kclvm_main_win") - _kclvm_main_ptr = ctypes.cast(_kclvm_main, ctypes.c_void_p).value - else: - _kclvm_main_ptr = 0 - - if disable_none: - disable_none = 1 - else: - disable_none = 0 - - if strict_range_check: - strict_range_check = 1 - else: - strict_range_check = 0 - - if disable_schema_check: - disable_schema_check = 1 - else: - disable_schema_check = 0 - - if list_option_mode: - list_option_mode = 1 - else: - list_option_mode = 0 - - if debug_mode: - debug_mode = 1 - else: - debug_mode = 0 - - json_result = self._run_app( - _start_ptr, - _kclvm_main_ptr, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - buffer_size, - ) - return json_result - - def GetWarn(self) -> str: - json_warn_result = self._get_warn() - return json_warn_result - - def CallMethod(self, name: str, args_json: str, kwargs_json: str) -> str: - return self._call_rust_method(name, args_json, kwargs_json) - - def _call_py_method(self, name: str, args_json: str, kwargs_json: str) -> str: - try: - return self._call_py_method_unsafe(name, args_json, kwargs_json) - except Exception as e: - return json.dumps({"__kcl_PanicInfo__": f"{e}"}) - - def _get_plugin(self, plugin_name: str) -> typing.Optional[any]: - if plugin_name in self._plugin_dict: - return self._plugin_dict[plugin_name] - - module = kcl_plugin.get_plugin(plugin_name) - self._plugin_dict[plugin_name] = module - return module - - def _call_py_method_unsafe( - self, name: str, args_json: str, kwargs_json: str - ) -> str: - dotIdx = name.rfind(".") - if dotIdx < 0: - return "" - - modulePath = name[:dotIdx] - mathodName = name[dotIdx + 1 :] - - plugin_name = modulePath[modulePath.rfind(".") + 1 :] - - module = self._get_plugin(plugin_name) - mathodFunc = None - - for func_name, func in inspect.getmembers(module): - if func_name == kcl_info.demangle(mathodName): - mathodFunc = func - break - - args = [] - kwargs = {} - - if args_json: - args = json.loads(args_json) - if not isinstance(args, list): - return "" - if kwargs_json: - kwargs = json.loads(kwargs_json) - if not isinstance(kwargs, dict): - return "" - - result = mathodFunc(*args, **kwargs) - return json.dumps(result) - - def __del__(self): - self._free_library() - - def _free_library(self): - if os.name == "nt": - import ctypes.wintypes - - kernel32 = ctypes.WinDLL("kernel32", use_last_error=True) - kernel32.FreeLibrary.argtypes = [ctypes.wintypes.HMODULE] - kernel32.FreeLibrary(self._app_lib._handle) - self._app_lib = None - # kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) - # kernel32.FreeLibrary.argtypes = [ctypes.wintypes.HMODULE] - # kernel32.FreeLibrary(self._app_dll._handle) - pass - else: - # libdl = ctypes.CDLL("libdl.so") - # libdl.dlclose(self._app_dll._handle) - pass - - -def main(args: typing.List[str]): - if len(args) < 2: - print("usage: kclvm_plugin app.[dll|dylib|so]") - sys._exit(1) - - ctx = AppContext(args[1]) - ctx.RunApp(args[2:]) - - -if __name__ == "__main__": - main(sys.argv) - -# This file is compatible with both classic and new-style classes. diff --git a/kclvm/plugin/kclvm_plugin_wrap.cxx b/kclvm/plugin/kclvm_plugin_wrap.cxx deleted file mode 100644 index 1b98fdf40..000000000 --- a/kclvm/plugin/kclvm_plugin_wrap.cxx +++ /dev/null @@ -1,5290 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.12 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - - -#ifndef SWIGPYTHON -#define SWIGPYTHON -#endif - -#define SWIG_DIRECTORS -#define SWIG_PYTHON_DIRECTOR_NO_VTABLE - - -#ifdef __cplusplus -/* SwigValueWrapper is described in swig.swg */ -template class SwigValueWrapper { - struct SwigMovePointer { - T *ptr; - SwigMovePointer(T *p) : ptr(p) { } - ~SwigMovePointer() { delete ptr; } - SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } - } pointer; - SwigValueWrapper& operator=(const SwigValueWrapper& rhs); - SwigValueWrapper(const SwigValueWrapper& rhs); -public: - SwigValueWrapper() : pointer(0) { } - SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } - operator T&() const { return *pointer.ptr; } - T *operator&() { return pointer.ptr; } -}; - -template T SwigValueInit() { - return T(); -} -#endif - -/* ----------------------------------------------------------------------------- - * This section contains generic SWIG labels for method/variable - * declarations/attributes, and other compiler dependent labels. - * ----------------------------------------------------------------------------- */ - -/* template workaround for compilers that cannot correctly implement the C++ standard */ -#ifndef SWIGTEMPLATEDISAMBIGUATOR -# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) -# define SWIGTEMPLATEDISAMBIGUATOR template -# elif defined(__HP_aCC) -/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ -/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ -# define SWIGTEMPLATEDISAMBIGUATOR template -# else -# define SWIGTEMPLATEDISAMBIGUATOR -# endif -#endif - -/* inline attribute */ -#ifndef SWIGINLINE -# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) -# define SWIGINLINE inline -# else -# define SWIGINLINE -# endif -#endif - -/* attribute recognised by some compilers to avoid 'unused' warnings */ -#ifndef SWIGUNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -# elif defined(__ICC) -# define SWIGUNUSED __attribute__ ((__unused__)) -# else -# define SWIGUNUSED -# endif -#endif - -#ifndef SWIG_MSC_UNSUPPRESS_4505 -# if defined(_MSC_VER) -# pragma warning(disable : 4505) /* unreferenced local function has been removed */ -# endif -#endif - -#ifndef SWIGUNUSEDPARM -# ifdef __cplusplus -# define SWIGUNUSEDPARM(p) -# else -# define SWIGUNUSEDPARM(p) p SWIGUNUSED -# endif -#endif - -/* internal SWIG method */ -#ifndef SWIGINTERN -# define SWIGINTERN static SWIGUNUSED -#endif - -/* internal inline SWIG method */ -#ifndef SWIGINTERNINLINE -# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE -#endif - -/* exporting methods */ -#if defined(__GNUC__) -# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# ifndef GCC_HASCLASSVISIBILITY -# define GCC_HASCLASSVISIBILITY -# endif -# endif -#endif - -#ifndef SWIGEXPORT -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# if defined(STATIC_LINKED) -# define SWIGEXPORT -# else -# define SWIGEXPORT __declspec(dllexport) -# endif -# else -# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) -# define SWIGEXPORT __attribute__ ((visibility("default"))) -# else -# define SWIGEXPORT -# endif -# endif -#endif - -/* calling conventions for Windows */ -#ifndef SWIGSTDCALL -# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# define SWIGSTDCALL __stdcall -# else -# define SWIGSTDCALL -# endif -#endif - -/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ -#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -# define _CRT_SECURE_NO_DEPRECATE -#endif - -/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ -#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) -# define _SCL_SECURE_NO_DEPRECATE -#endif - -/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ -#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) -# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 -#endif - -/* Intel's compiler complains if a variable which was never initialised is - * cast to void, which is a common idiom which we use to indicate that we - * are aware a variable isn't used. So we just silence that warning. - * See: https://github.com/swig/swig/issues/192 for more discussion. - */ -#ifdef __INTEL_COMPILER -# pragma warning disable 592 -#endif - - -#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) -/* Use debug wrappers with the Python release dll */ -# undef _DEBUG -# include -# define _DEBUG -#else -# include -#endif - -/* ----------------------------------------------------------------------------- - * swigrun.swg - * - * This file contains generic C API SWIG runtime support for pointer - * type checking. - * ----------------------------------------------------------------------------- */ - -/* This should only be incremented when either the layout of swig_type_info changes, - or for whatever reason, the runtime changes incompatibly */ -#define SWIG_RUNTIME_VERSION "4" - -/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ -#ifdef SWIG_TYPE_TABLE -# define SWIG_QUOTE_STRING(x) #x -# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) -# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) -#else -# define SWIG_TYPE_TABLE_NAME -#endif - -/* - You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for - creating a static or dynamic library from the SWIG runtime code. - In 99.9% of the cases, SWIG just needs to declare them as 'static'. - - But only do this if strictly necessary, ie, if you have problems - with your compiler or suchlike. -*/ - -#ifndef SWIGRUNTIME -# define SWIGRUNTIME SWIGINTERN -#endif - -#ifndef SWIGRUNTIMEINLINE -# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE -#endif - -/* Generic buffer size */ -#ifndef SWIG_BUFFER_SIZE -# define SWIG_BUFFER_SIZE 1024 -#endif - -/* Flags for pointer conversions */ -#define SWIG_POINTER_DISOWN 0x1 -#define SWIG_CAST_NEW_MEMORY 0x2 - -/* Flags for new pointer objects */ -#define SWIG_POINTER_OWN 0x1 - - -/* - Flags/methods for returning states. - - The SWIG conversion methods, as ConvertPtr, return an integer - that tells if the conversion was successful or not. And if not, - an error code can be returned (see swigerrors.swg for the codes). - - Use the following macros/flags to set or process the returning - states. - - In old versions of SWIG, code such as the following was usually written: - - if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { - // success code - } else { - //fail code - } - - Now you can be more explicit: - - int res = SWIG_ConvertPtr(obj,vptr,ty.flags); - if (SWIG_IsOK(res)) { - // success code - } else { - // fail code - } - - which is the same really, but now you can also do - - Type *ptr; - int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); - if (SWIG_IsOK(res)) { - // success code - if (SWIG_IsNewObj(res) { - ... - delete *ptr; - } else { - ... - } - } else { - // fail code - } - - I.e., now SWIG_ConvertPtr can return new objects and you can - identify the case and take care of the deallocation. Of course that - also requires SWIG_ConvertPtr to return new result values, such as - - int SWIG_ConvertPtr(obj, ptr,...) { - if () { - if () { - *ptr = ; - return SWIG_NEWOBJ; - } else { - *ptr = ; - return SWIG_OLDOBJ; - } - } else { - return SWIG_BADOBJ; - } - } - - Of course, returning the plain '0(success)/-1(fail)' still works, but you can be - more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the - SWIG errors code. - - Finally, if the SWIG_CASTRANK_MODE is enabled, the result code - allows to return the 'cast rank', for example, if you have this - - int food(double) - int fooi(int); - - and you call - - food(1) // cast rank '1' (1 -> 1.0) - fooi(1) // cast rank '0' - - just use the SWIG_AddCast()/SWIG_CheckState() -*/ - -#define SWIG_OK (0) -#define SWIG_ERROR (-1) -#define SWIG_IsOK(r) (r >= 0) -#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) - -/* The CastRankLimit says how many bits are used for the cast rank */ -#define SWIG_CASTRANKLIMIT (1 << 8) -/* The NewMask denotes the object was created (using new/malloc) */ -#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) -/* The TmpMask is for in/out typemaps that use temporal objects */ -#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) -/* Simple returning values */ -#define SWIG_BADOBJ (SWIG_ERROR) -#define SWIG_OLDOBJ (SWIG_OK) -#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) -#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) -/* Check, add and del mask methods */ -#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) -#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) -#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) -#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) -#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) -#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) - -/* Cast-Rank Mode */ -#if defined(SWIG_CASTRANK_MODE) -# ifndef SWIG_TypeRank -# define SWIG_TypeRank unsigned long -# endif -# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ -# define SWIG_MAXCASTRANK (2) -# endif -# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) -# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) -SWIGINTERNINLINE int SWIG_AddCast(int r) { - return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; -} -SWIGINTERNINLINE int SWIG_CheckState(int r) { - return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; -} -#else /* no cast-rank mode */ -# define SWIG_AddCast(r) (r) -# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) -#endif - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *(*swig_converter_func)(void *, int *); -typedef struct swig_type_info *(*swig_dycast_func)(void **); - -/* Structure to store information on one type */ -typedef struct swig_type_info { - const char *name; /* mangled name of this type */ - const char *str; /* human readable name of this type */ - swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ - struct swig_cast_info *cast; /* linked list of types that can cast into this type */ - void *clientdata; /* language specific type data */ - int owndata; /* flag if the structure owns the clientdata */ -} swig_type_info; - -/* Structure to store a type and conversion function used for casting */ -typedef struct swig_cast_info { - swig_type_info *type; /* pointer to type that is equivalent to this type */ - swig_converter_func converter; /* function to cast the void pointers */ - struct swig_cast_info *next; /* pointer to next cast in linked list */ - struct swig_cast_info *prev; /* pointer to the previous cast */ -} swig_cast_info; - -/* Structure used to store module information - * Each module generates one structure like this, and the runtime collects - * all of these structures and stores them in a circularly linked list.*/ -typedef struct swig_module_info { - swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ - size_t size; /* Number of types in this module */ - struct swig_module_info *next; /* Pointer to next element in circularly linked list */ - swig_type_info **type_initial; /* Array of initially generated type structures */ - swig_cast_info **cast_initial; /* Array of initially generated casting structures */ - void *clientdata; /* Language specific module data */ -} swig_module_info; - -/* - Compare two type names skipping the space characters, therefore - "char*" == "char *" and "Class" == "Class", etc. - - Return 0 when the two name types are equivalent, as in - strncmp, but skipping ' '. -*/ -SWIGRUNTIME int -SWIG_TypeNameComp(const char *f1, const char *l1, - const char *f2, const char *l2) { - for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { - while ((*f1 == ' ') && (f1 != l1)) ++f1; - while ((*f2 == ' ') && (f2 != l2)) ++f2; - if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; - } - return (int)((l1 - f1) - (l2 - f2)); -} - -/* - Check type equivalence in a name list like ||... - Return 0 if equal, -1 if nb < tb, 1 if nb > tb -*/ -SWIGRUNTIME int -SWIG_TypeCmp(const char *nb, const char *tb) { - int equiv = 1; - const char* te = tb + strlen(tb); - const char* ne = nb; - while (equiv != 0 && *ne) { - for (nb = ne; *ne; ++ne) { - if (*ne == '|') break; - } - equiv = SWIG_TypeNameComp(nb, ne, tb, te); - if (*ne) ++ne; - } - return equiv; -} - -/* - Check type equivalence in a name list like ||... - Return 0 if not equal, 1 if equal -*/ -SWIGRUNTIME int -SWIG_TypeEquiv(const char *nb, const char *tb) { - return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; -} - -/* - Check the typename -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheck(const char *c, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (strcmp(iter->type->name, c) == 0) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison -*/ -SWIGRUNTIME swig_cast_info * -SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { - if (ty) { - swig_cast_info *iter = ty->cast; - while (iter) { - if (iter->type == from) { - if (iter == ty->cast) - return iter; - /* Move iter to the top of the linked list */ - iter->prev->next = iter->next; - if (iter->next) - iter->next->prev = iter->prev; - iter->next = ty->cast; - iter->prev = 0; - if (ty->cast) ty->cast->prev = iter; - ty->cast = iter; - return iter; - } - iter = iter->next; - } - } - return 0; -} - -/* - Cast a pointer up an inheritance hierarchy -*/ -SWIGRUNTIMEINLINE void * -SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { - return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); -} - -/* - Dynamic pointer casting. Down an inheritance hierarchy -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { - swig_type_info *lastty = ty; - if (!ty || !ty->dcast) return ty; - while (ty && (ty->dcast)) { - ty = (*ty->dcast)(ptr); - if (ty) lastty = ty; - } - return lastty; -} - -/* - Return the name associated with this type -*/ -SWIGRUNTIMEINLINE const char * -SWIG_TypeName(const swig_type_info *ty) { - return ty->name; -} - -/* - Return the pretty name associated with this type, - that is an unmangled type name in a form presentable to the user. -*/ -SWIGRUNTIME const char * -SWIG_TypePrettyName(const swig_type_info *type) { - /* The "str" field contains the equivalent pretty names of the - type, separated by vertical-bar characters. We choose - to print the last name, as it is often (?) the most - specific. */ - if (!type) return NULL; - if (type->str != NULL) { - const char *last_name = type->str; - const char *s; - for (s = type->str; *s; s++) - if (*s == '|') last_name = s+1; - return last_name; - } - else - return type->name; -} - -/* - Set the clientdata field for a type -*/ -SWIGRUNTIME void -SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { - swig_cast_info *cast = ti->cast; - /* if (ti->clientdata == clientdata) return; */ - ti->clientdata = clientdata; - - while (cast) { - if (!cast->converter) { - swig_type_info *tc = cast->type; - if (!tc->clientdata) { - SWIG_TypeClientData(tc, clientdata); - } - } - cast = cast->next; - } -} -SWIGRUNTIME void -SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { - SWIG_TypeClientData(ti, clientdata); - ti->owndata = 1; -} - -/* - Search for a swig_type_info structure only by mangled name - Search is a O(log #types) - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_MangledTypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - swig_module_info *iter = start; - do { - if (iter->size) { - size_t l = 0; - size_t r = iter->size - 1; - do { - /* since l+r >= 0, we can (>> 1) instead (/ 2) */ - size_t i = (l + r) >> 1; - const char *iname = iter->types[i]->name; - if (iname) { - int compare = strcmp(name, iname); - if (compare == 0) { - return iter->types[i]; - } else if (compare < 0) { - if (i) { - r = i - 1; - } else { - break; - } - } else if (compare > 0) { - l = i + 1; - } - } else { - break; /* should never happen */ - } - } while (l <= r); - } - iter = iter->next; - } while (iter != end); - return 0; -} - -/* - Search for a swig_type_info structure for either a mangled name or a human readable name. - It first searches the mangled names of the types, which is a O(log #types) - If a type is not found it then searches the human readable names, which is O(#types). - - We start searching at module start, and finish searching when start == end. - Note: if start == end at the beginning of the function, we go all the way around - the circular list. -*/ -SWIGRUNTIME swig_type_info * -SWIG_TypeQueryModule(swig_module_info *start, - swig_module_info *end, - const char *name) { - /* STEP 1: Search the name field using binary search */ - swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); - if (ret) { - return ret; - } else { - /* STEP 2: If the type hasn't been found, do a complete search - of the str field (the human readable name) */ - swig_module_info *iter = start; - do { - size_t i = 0; - for (; i < iter->size; ++i) { - if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) - return iter->types[i]; - } - iter = iter->next; - } while (iter != end); - } - - /* neither found a match */ - return 0; -} - -/* - Pack binary data into a string -*/ -SWIGRUNTIME char * -SWIG_PackData(char *c, void *ptr, size_t sz) { - static const char hex[17] = "0123456789abcdef"; - const unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - unsigned char uu = *u; - *(c++) = hex[(uu & 0xf0) >> 4]; - *(c++) = hex[uu & 0xf]; - } - return c; -} - -/* - Unpack binary data from a string -*/ -SWIGRUNTIME const char * -SWIG_UnpackData(const char *c, void *ptr, size_t sz) { - unsigned char *u = (unsigned char *) ptr; - const unsigned char *eu = u + sz; - for (; u != eu; ++u) { - char d = *(c++); - unsigned char uu; - if ((d >= '0') && (d <= '9')) - uu = (unsigned char)((d - '0') << 4); - else if ((d >= 'a') && (d <= 'f')) - uu = (unsigned char)((d - ('a'-10)) << 4); - else - return (char *) 0; - d = *(c++); - if ((d >= '0') && (d <= '9')) - uu |= (unsigned char)(d - '0'); - else if ((d >= 'a') && (d <= 'f')) - uu |= (unsigned char)(d - ('a'-10)); - else - return (char *) 0; - *u = uu; - } - return c; -} - -/* - Pack 'void *' into a string buffer. -*/ -SWIGRUNTIME char * -SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { - char *r = buff; - if ((2*sizeof(void *) + 2) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,&ptr,sizeof(void *)); - if (strlen(name) + 1 > (bsz - (r - buff))) return 0; - strcpy(r,name); - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - *ptr = (void *) 0; - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sizeof(void *)); -} - -SWIGRUNTIME char * -SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { - char *r = buff; - size_t lname = (name ? strlen(name) : 0); - if ((2*sz + 2 + lname) > bsz) return 0; - *(r++) = '_'; - r = SWIG_PackData(r,ptr,sz); - if (lname) { - strncpy(r,name,lname+1); - } else { - *r = 0; - } - return buff; -} - -SWIGRUNTIME const char * -SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { - if (*c != '_') { - if (strcmp(c,"NULL") == 0) { - memset(ptr,0,sz); - return name; - } else { - return 0; - } - } - return SWIG_UnpackData(++c,ptr,sz); -} - -#ifdef __cplusplus -} -#endif - -/* Errors in SWIG */ -#define SWIG_UnknownError -1 -#define SWIG_IOError -2 -#define SWIG_RuntimeError -3 -#define SWIG_IndexError -4 -#define SWIG_TypeError -5 -#define SWIG_DivisionByZero -6 -#define SWIG_OverflowError -7 -#define SWIG_SyntaxError -8 -#define SWIG_ValueError -9 -#define SWIG_SystemError -10 -#define SWIG_AttributeError -11 -#define SWIG_MemoryError -12 -#define SWIG_NullReferenceError -13 - - - -/* Compatibility macros for Python 3 */ -#if PY_VERSION_HEX >= 0x03000000 - -#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) -#define PyInt_Check(x) PyLong_Check(x) -#define PyInt_AsLong(x) PyLong_AsLong(x) -#define PyInt_FromLong(x) PyLong_FromLong(x) -#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) -#define PyString_Check(name) PyBytes_Check(name) -#define PyString_FromString(x) PyUnicode_FromString(x) -#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) -#define PyString_AsString(str) PyBytes_AsString(str) -#define PyString_Size(str) PyBytes_Size(str) -#define PyString_InternFromString(key) PyUnicode_InternFromString(key) -#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE -#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) -#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) - -#endif - -#ifndef Py_TYPE -# define Py_TYPE(op) ((op)->ob_type) -#endif - -/* SWIG APIs for compatibility of both Python 2 & 3 */ - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_FromFormat PyUnicode_FromFormat -#else -# define SWIG_Python_str_FromFormat PyString_FromFormat -#endif - - -/* Warning: This function will allocate a new string in Python 3, - * so please call SWIG_Python_str_DelForPy3(x) to free the space. - */ -SWIGINTERN char* -SWIG_Python_str_AsChar(PyObject *str) -{ -#if PY_VERSION_HEX >= 0x03000000 - char *cstr; - char *newstr; - Py_ssize_t len; - str = PyUnicode_AsUTF8String(str); - PyBytes_AsStringAndSize(str, &cstr, &len); - newstr = (char *) malloc(len+1); - memcpy(newstr, cstr, len+1); - Py_XDECREF(str); - return newstr; -#else - return PyString_AsString(str); -#endif -} - -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) -#else -# define SWIG_Python_str_DelForPy3(x) -#endif - - -SWIGINTERN PyObject* -SWIG_Python_str_FromChar(const char *c) -{ -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_FromString(c); -#else - return PyString_FromString(c); -#endif -} - -/* Add PyOS_snprintf for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) -# define PyOS_snprintf _snprintf -# else -# define PyOS_snprintf snprintf -# endif -#endif - -/* A crude PyString_FromFormat implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 - -#ifndef SWIG_PYBUFFER_SIZE -# define SWIG_PYBUFFER_SIZE 1024 -#endif - -static PyObject * -PyString_FromFormat(const char *fmt, ...) { - va_list ap; - char buf[SWIG_PYBUFFER_SIZE * 2]; - int res; - va_start(ap, fmt); - res = vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return (res < 0 || res >= (int)sizeof(buf)) ? 0 : PyString_FromString(buf); -} -#endif - -#ifndef PyObject_DEL -# define PyObject_DEL PyObject_Del -#endif - -/* A crude PyExc_StopIteration exception for old Pythons */ -#if PY_VERSION_HEX < 0x02020000 -# ifndef PyExc_StopIteration -# define PyExc_StopIteration PyExc_RuntimeError -# endif -# ifndef PyObject_GenericGetAttr -# define PyObject_GenericGetAttr 0 -# endif -#endif - -/* Py_NotImplemented is defined in 2.1 and up. */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef Py_NotImplemented -# define Py_NotImplemented PyExc_RuntimeError -# endif -#endif - -/* A crude PyString_AsStringAndSize implementation for old Pythons */ -#if PY_VERSION_HEX < 0x02010000 -# ifndef PyString_AsStringAndSize -# define PyString_AsStringAndSize(obj, s, len) {*s = PyString_AsString(obj); *len = *s ? strlen(*s) : 0;} -# endif -#endif - -/* PySequence_Size for old Pythons */ -#if PY_VERSION_HEX < 0x02000000 -# ifndef PySequence_Size -# define PySequence_Size PySequence_Length -# endif -#endif - -/* PyBool_FromLong for old Pythons */ -#if PY_VERSION_HEX < 0x02030000 -static -PyObject *PyBool_FromLong(long ok) -{ - PyObject *result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} -#endif - -/* Py_ssize_t for old Pythons */ -/* This code is as recommended by: */ -/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -# define PY_SSIZE_T_MAX INT_MAX -# define PY_SSIZE_T_MIN INT_MIN -typedef inquiry lenfunc; -typedef intargfunc ssizeargfunc; -typedef intintargfunc ssizessizeargfunc; -typedef intobjargproc ssizeobjargproc; -typedef intintobjargproc ssizessizeobjargproc; -typedef getreadbufferproc readbufferproc; -typedef getwritebufferproc writebufferproc; -typedef getsegcountproc segcountproc; -typedef getcharbufferproc charbufferproc; -static long PyNumber_AsSsize_t (PyObject *x, void *SWIGUNUSEDPARM(exc)) -{ - long result = 0; - PyObject *i = PyNumber_Int(x); - if (i) { - result = PyInt_AsLong(i); - Py_DECREF(i); - } - return result; -} -#endif - -#if PY_VERSION_HEX < 0x02050000 -#define PyInt_FromSize_t(x) PyInt_FromLong((long)x) -#endif - -#if PY_VERSION_HEX < 0x02040000 -#define Py_VISIT(op) \ - do { \ - if (op) { \ - int vret = visit((op), arg); \ - if (vret) \ - return vret; \ - } \ - } while (0) -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef struct { - PyTypeObject type; - PyNumberMethods as_number; - PyMappingMethods as_mapping; - PySequenceMethods as_sequence; - PyBufferProcs as_buffer; - PyObject *name, *slots; -} PyHeapTypeObject; -#endif - -#if PY_VERSION_HEX < 0x02030000 -typedef destructor freefunc; -#endif - -#if ((PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 6) || \ - (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION > 0) || \ - (PY_MAJOR_VERSION > 3)) -# define SWIGPY_USE_CAPSULE -# define SWIGPY_CAPSULE_NAME ((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) -#endif - -#if PY_VERSION_HEX < 0x03020000 -#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) -#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) -#define Py_hash_t long -#endif - -/* ----------------------------------------------------------------------------- - * error manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIME PyObject* -SWIG_Python_ErrorType(int code) { - PyObject* type = 0; - switch(code) { - case SWIG_MemoryError: - type = PyExc_MemoryError; - break; - case SWIG_IOError: - type = PyExc_IOError; - break; - case SWIG_RuntimeError: - type = PyExc_RuntimeError; - break; - case SWIG_IndexError: - type = PyExc_IndexError; - break; - case SWIG_TypeError: - type = PyExc_TypeError; - break; - case SWIG_DivisionByZero: - type = PyExc_ZeroDivisionError; - break; - case SWIG_OverflowError: - type = PyExc_OverflowError; - break; - case SWIG_SyntaxError: - type = PyExc_SyntaxError; - break; - case SWIG_ValueError: - type = PyExc_ValueError; - break; - case SWIG_SystemError: - type = PyExc_SystemError; - break; - case SWIG_AttributeError: - type = PyExc_AttributeError; - break; - default: - type = PyExc_RuntimeError; - } - return type; -} - - -SWIGRUNTIME void -SWIG_Python_AddErrorMsg(const char* mesg) -{ - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - - if (PyErr_Occurred()) PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - PyErr_Clear(); - Py_XINCREF(type); - - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - Py_DECREF(value); - } else { - PyErr_SetString(PyExc_RuntimeError, mesg); - } -} - -#if defined(SWIG_PYTHON_NO_THREADS) -# if defined(SWIG_PYTHON_THREADS) -# undef SWIG_PYTHON_THREADS -# endif -#endif -#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ -# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) -# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */ -# define SWIG_PYTHON_USE_GIL -# endif -# endif -# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ -# ifndef SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() -# endif -# ifdef __cplusplus /* C++ code */ - class SWIG_Python_Thread_Block { - bool status; - PyGILState_STATE state; - public: - void end() { if (status) { PyGILState_Release(state); status = false;} } - SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} - ~SWIG_Python_Thread_Block() { end(); } - }; - class SWIG_Python_Thread_Allow { - bool status; - PyThreadState *save; - public: - void end() { if (status) { PyEval_RestoreThread(save); status = false; }} - SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} - ~SWIG_Python_Thread_Allow() { end(); } - }; -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block -# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow -# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() -# else /* C code */ -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() -# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() -# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) -# endif -# else /* Old thread way, not implemented, user must provide it */ -# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) -# define SWIG_PYTHON_INITIALIZE_THREADS -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) -# define SWIG_PYTHON_THREAD_END_BLOCK -# endif -# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# endif -# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) -# define SWIG_PYTHON_THREAD_END_ALLOW -# endif -# endif -#else /* No thread support */ -# define SWIG_PYTHON_INITIALIZE_THREADS -# define SWIG_PYTHON_THREAD_BEGIN_BLOCK -# define SWIG_PYTHON_THREAD_END_BLOCK -# define SWIG_PYTHON_THREAD_BEGIN_ALLOW -# define SWIG_PYTHON_THREAD_END_ALLOW -#endif - -/* ----------------------------------------------------------------------------- - * Python API portion that goes into the runtime - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ----------------------------------------------------------------------------- - * Constant declarations - * ----------------------------------------------------------------------------- */ - -/* Constant Types */ -#define SWIG_PY_POINTER 4 -#define SWIG_PY_BINARY 5 - -/* Constant information structure */ -typedef struct swig_const_info { - int type; - char *name; - long lvalue; - double dvalue; - void *pvalue; - swig_type_info **ptype; -} swig_const_info; - - -/* ----------------------------------------------------------------------------- - * Wrapper of PyInstanceMethod_New() used in Python 3 - * It is exported to the generated module, used for -fastproxy - * ----------------------------------------------------------------------------- */ -#if PY_VERSION_HEX >= 0x03000000 -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) -{ - return PyInstanceMethod_New(func); -} -#else -SWIGRUNTIME PyObject* SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *SWIGUNUSEDPARM(func)) -{ - return NULL; -} -#endif - -#ifdef __cplusplus -} -#endif - - -/* ----------------------------------------------------------------------------- - * pyrun.swg - * - * This file contains the runtime support for Python modules - * and includes code for managing global variables and pointer - * type checking. - * - * ----------------------------------------------------------------------------- */ - -/* Common SWIG API */ - -/* for raw pointers */ -#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) - -#ifdef SWIGPYTHON_BUILTIN -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) -#else -#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) -#endif - -#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) - -#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) -#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) -#define swig_owntype int - -/* for raw packed data */ -#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - -/* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) - -/* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) - -/* for C++ member pointers, ie, member methods */ -#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) -#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) - - -/* Runtime API */ - -#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) -#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) -#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) - -#define SWIG_SetErrorObj SWIG_Python_SetErrorObj -#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg -#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) -#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) -#define SWIG_fail goto fail - - -/* Runtime API implementation */ - -/* Error manipulation */ - -SWIGINTERN void -SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetObject(errtype, obj); - Py_DECREF(obj); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -SWIGINTERN void -SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyErr_SetString(errtype, msg); - SWIG_PYTHON_THREAD_END_BLOCK; -} - -#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) - -/* Set a constant value */ - -#if defined(SWIGPYTHON_BUILTIN) - -SWIGINTERN void -SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { - PyObject *s = PyString_InternFromString(key); - PyList_Append(seq, s); - Py_DECREF(s); -} - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); - if (public_interface) - SwigPyBuiltin_AddPublicSymbol(public_interface, name); -} - -#else - -SWIGINTERN void -SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { -#if PY_VERSION_HEX < 0x02030000 - PyDict_SetItemString(d, (char *)name, obj); -#else - PyDict_SetItemString(d, name, obj); -#endif - Py_DECREF(obj); -} - -#endif - -/* Append a value to the result obj */ - -SWIGINTERN PyObject* -SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { -#if !defined(SWIG_PYTHON_OUTPUT_TUPLE) - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyList_Check(result)) { - PyObject *o2 = result; - result = PyList_New(1); - PyList_SetItem(result, 0, o2); - } - PyList_Append(result,obj); - Py_DECREF(obj); - } - return result; -#else - PyObject* o2; - PyObject* o3; - if (!result) { - result = obj; - } else if (result == Py_None) { - Py_DECREF(result); - result = obj; - } else { - if (!PyTuple_Check(result)) { - o2 = result; - result = PyTuple_New(1); - PyTuple_SET_ITEM(result, 0, o2); - } - o3 = PyTuple_New(1); - PyTuple_SET_ITEM(o3, 0, obj); - o2 = result; - result = PySequence_Concat(o2, o3); - Py_DECREF(o2); - Py_DECREF(o3); - } - return result; -#endif -} - -/* Unpack the argument tuple */ - -SWIGINTERN Py_ssize_t -SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) -{ - if (!args) { - if (!min && !max) { - return 1; - } else { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", - name, (min == max ? "" : "at least "), (int)min); - return 0; - } - } - if (!PyTuple_Check(args)) { - if (min <= 1 && max >= 1) { - Py_ssize_t i; - objs[0] = args; - for (i = 1; i < max; ++i) { - objs[i] = 0; - } - return 2; - } - PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); - return 0; - } else { - Py_ssize_t l = PyTuple_GET_SIZE(args); - if (l < min) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at least "), (int)min, (int)l); - return 0; - } else if (l > max) { - PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", - name, (min == max ? "" : "at most "), (int)max, (int)l); - return 0; - } else { - Py_ssize_t i; - for (i = 0; i < l; ++i) { - objs[i] = PyTuple_GET_ITEM(args, i); - } - for (; l < max; ++l) { - objs[l] = 0; - } - return i + 1; - } - } -} - -/* A functor is a function object with one single object argument */ -#if PY_VERSION_HEX >= 0x02020000 -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); -#else -#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunction(functor, "O", obj); -#endif - -/* - Helper for static pointer initialization for both C and C++ code, for example - static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); -*/ -#ifdef __cplusplus -#define SWIG_STATIC_POINTER(var) var -#else -#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var -#endif - -/* ----------------------------------------------------------------------------- - * Pointer declarations - * ----------------------------------------------------------------------------- */ - -/* Flags for new pointer objects */ -#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) -#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) - -#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) - -#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) -#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) - -#ifdef __cplusplus -extern "C" { -#endif - -/* How to access Py_None */ -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef SWIG_PYTHON_NO_BUILD_NONE -# ifndef SWIG_PYTHON_BUILD_NONE -# define SWIG_PYTHON_BUILD_NONE -# endif -# endif -#endif - -#ifdef SWIG_PYTHON_BUILD_NONE -# ifdef Py_None -# undef Py_None -# define Py_None SWIG_Py_None() -# endif -SWIGRUNTIMEINLINE PyObject * -_SWIG_Py_None(void) -{ - PyObject *none = Py_BuildValue((char*)""); - Py_DECREF(none); - return none; -} -SWIGRUNTIME PyObject * -SWIG_Py_None(void) -{ - static PyObject *SWIG_STATIC_POINTER(none) = _SWIG_Py_None(); - return none; -} -#endif - -/* The python void return value */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Py_Void(void) -{ - PyObject *none = Py_None; - Py_INCREF(none); - return none; -} - -/* SwigPyClientData */ - -typedef struct { - PyObject *klass; - PyObject *newraw; - PyObject *newargs; - PyObject *destroy; - int delargs; - int implicitconv; - PyTypeObject *pytype; -} SwigPyClientData; - -SWIGRUNTIMEINLINE int -SWIG_Python_CheckImplicit(swig_type_info *ty) -{ - SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; - return data ? data->implicitconv : 0; -} - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_ExceptionType(swig_type_info *desc) { - SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; - PyObject *klass = data ? data->klass : 0; - return (klass ? klass : PyExc_RuntimeError); -} - - -SWIGRUNTIME SwigPyClientData * -SwigPyClientData_New(PyObject* obj) -{ - if (!obj) { - return 0; - } else { - SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); - /* the klass element */ - data->klass = obj; - Py_INCREF(data->klass); - /* the newraw method and newargs arguments used to create a new raw instance */ - if (PyClass_Check(obj)) { - data->newraw = 0; - data->newargs = obj; - Py_INCREF(obj); - } else { -#if (PY_VERSION_HEX < 0x02020000) - data->newraw = 0; -#else - data->newraw = PyObject_GetAttrString(data->klass, (char *)"__new__"); -#endif - if (data->newraw) { - Py_INCREF(data->newraw); - data->newargs = PyTuple_New(1); - PyTuple_SetItem(data->newargs, 0, obj); - } else { - data->newargs = obj; - } - Py_INCREF(data->newargs); - } - /* the destroy method, aka as the C++ delete method */ - data->destroy = PyObject_GetAttrString(data->klass, (char *)"__swig_destroy__"); - if (PyErr_Occurred()) { - PyErr_Clear(); - data->destroy = 0; - } - if (data->destroy) { - int flags; - Py_INCREF(data->destroy); - flags = PyCFunction_GET_FLAGS(data->destroy); -#ifdef METH_O - data->delargs = !(flags & (METH_O)); -#else - data->delargs = 0; -#endif - } else { - data->delargs = 0; - } - data->implicitconv = 0; - data->pytype = 0; - return data; - } -} - -SWIGRUNTIME void -SwigPyClientData_Del(SwigPyClientData *data) { - Py_XDECREF(data->newraw); - Py_XDECREF(data->newargs); - Py_XDECREF(data->destroy); -} - -/* =============== SwigPyObject =====================*/ - -typedef struct { - PyObject_HEAD - void *ptr; - swig_type_info *ty; - int own; - PyObject *next; -#ifdef SWIGPYTHON_BUILTIN - PyObject *dict; -#endif -} SwigPyObject; - - -#ifdef SWIGPYTHON_BUILTIN - -SWIGRUNTIME PyObject * -SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) -{ - SwigPyObject *sobj = (SwigPyObject *)v; - - if (!sobj->dict) - sobj->dict = PyDict_New(); - - Py_INCREF(sobj->dict); - return sobj->dict; -} - -#endif - -SWIGRUNTIME PyObject * -SwigPyObject_long(SwigPyObject *v) -{ - return PyLong_FromVoidPtr(v->ptr); -} - -SWIGRUNTIME PyObject * -SwigPyObject_format(const char* fmt, SwigPyObject *v) -{ - PyObject *res = NULL; - PyObject *args = PyTuple_New(1); - if (args) { - if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { - PyObject *ofmt = SWIG_Python_str_FromChar(fmt); - if (ofmt) { -#if PY_VERSION_HEX >= 0x03000000 - res = PyUnicode_Format(ofmt,args); -#else - res = PyString_Format(ofmt,args); -#endif - Py_DECREF(ofmt); - } - Py_DECREF(args); - } - } - return res; -} - -SWIGRUNTIME PyObject * -SwigPyObject_oct(SwigPyObject *v) -{ - return SwigPyObject_format("%o",v); -} - -SWIGRUNTIME PyObject * -SwigPyObject_hex(SwigPyObject *v) -{ - return SwigPyObject_format("%x",v); -} - -SWIGRUNTIME PyObject * -#ifdef METH_NOARGS -SwigPyObject_repr(SwigPyObject *v) -#else -SwigPyObject_repr(SwigPyObject *v, PyObject *args) -#endif -{ - const char *name = SWIG_TypePrettyName(v->ty); - PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); - if (v->next) { -# ifdef METH_NOARGS - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); -# else - PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next, args); -# endif -# if PY_VERSION_HEX >= 0x03000000 - PyObject *joined = PyUnicode_Concat(repr, nrep); - Py_DecRef(repr); - Py_DecRef(nrep); - repr = joined; -# else - PyString_ConcatAndDel(&repr,nrep); -# endif - } - return repr; -} - -SWIGRUNTIME int -SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) -{ - void *i = v->ptr; - void *j = w->ptr; - return (i < j) ? -1 : ((i > j) ? 1 : 0); -} - -/* Added for Python 3.x, would it also be useful for Python 2.x? */ -SWIGRUNTIME PyObject* -SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) -{ - PyObject* res; - if( op != Py_EQ && op != Py_NE ) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); - return res; -} - - -SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); - -#ifdef SWIGPYTHON_BUILTIN -static swig_type_info *SwigPyObject_stype = 0; -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - SwigPyClientData *cd; - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - assert(cd); - assert(cd->pytype); - return cd->pytype; -} -#else -SWIGRUNTIME PyTypeObject* -SwigPyObject_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); - return type; -} -#endif - -SWIGRUNTIMEINLINE int -SwigPyObject_Check(PyObject *op) { -#ifdef SWIGPYTHON_BUILTIN - PyTypeObject *target_tp = SwigPyObject_type(); - if (PyType_IsSubtype(op->ob_type, target_tp)) - return 1; - return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); -#else - return (Py_TYPE(op) == SwigPyObject_type()) - || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); -#endif -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own); - -SWIGRUNTIME void -SwigPyObject_dealloc(PyObject *v) -{ - SwigPyObject *sobj = (SwigPyObject *) v; - PyObject *next = sobj->next; - if (sobj->own == SWIG_POINTER_OWN) { - swig_type_info *ty = sobj->ty; - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - PyObject *destroy = data ? data->destroy : 0; - if (destroy) { - /* destroy is always a VARARGS method */ - PyObject *res; - - /* PyObject_CallFunction() has the potential to silently drop - the active active exception. In cases of unnamed temporary - variable or where we just finished iterating over a generator - StopIteration will be active right now, and this needs to - remain true upon return from SwigPyObject_dealloc. So save - and restore. */ - - PyObject *val = NULL, *type = NULL, *tb = NULL; - PyErr_Fetch(&val, &type, &tb); - - if (data->delargs) { - /* we need to create a temporary object to carry the destroy operation */ - PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); - res = SWIG_Python_CallFunctor(destroy, tmp); - Py_DECREF(tmp); - } else { - PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); - PyObject *mself = PyCFunction_GET_SELF(destroy); - res = ((*meth)(mself, v)); - } - if (!res) - PyErr_WriteUnraisable(destroy); - - PyErr_Restore(val, type, tb); - - Py_XDECREF(res); - } -#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) - else { - const char *name = SWIG_TypePrettyName(ty); - printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); - } -#endif - } - Py_XDECREF(next); - PyObject_DEL(v); -} - -SWIGRUNTIME PyObject* -SwigPyObject_append(PyObject* v, PyObject* next) -{ - SwigPyObject *sobj = (SwigPyObject *) v; -#ifndef METH_O - PyObject *tmp = 0; - if (!PyArg_ParseTuple(next,(char *)"O:append", &tmp)) return NULL; - next = tmp; -#endif - if (!SwigPyObject_Check(next)) { - PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); - return NULL; - } - sobj->next = next; - Py_INCREF(next); - return SWIG_Py_Void(); -} - -SWIGRUNTIME PyObject* -#ifdef METH_NOARGS -SwigPyObject_next(PyObject* v) -#else -SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *) v; - if (sobj->next) { - Py_INCREF(sobj->next); - return sobj->next; - } else { - return SWIG_Py_Void(); - } -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_disown(PyObject *v) -#else -SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = 0; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -#ifdef METH_NOARGS -SwigPyObject_acquire(PyObject *v) -#else -SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) -#endif -{ - SwigPyObject *sobj = (SwigPyObject *)v; - sobj->own = SWIG_POINTER_OWN; - return SWIG_Py_Void(); -} - -SWIGINTERN PyObject* -SwigPyObject_own(PyObject *v, PyObject *args) -{ - PyObject *val = 0; -#if (PY_VERSION_HEX < 0x02020000) - if (!PyArg_ParseTuple(args,(char *)"|O:own",&val)) -#elif (PY_VERSION_HEX < 0x02050000) - if (!PyArg_UnpackTuple(args, (char *)"own", 0, 1, &val)) -#else - if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) -#endif - { - return NULL; - } - else - { - SwigPyObject *sobj = (SwigPyObject *)v; - PyObject *obj = PyBool_FromLong(sobj->own); - if (val) { -#ifdef METH_NOARGS - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v); - } else { - SwigPyObject_disown(v); - } -#else - if (PyObject_IsTrue(val)) { - SwigPyObject_acquire(v,args); - } else { - SwigPyObject_disown(v,args); - } -#endif - } - return obj; - } -} - -#ifdef METH_O -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_NOARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_NOARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_O, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_NOARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_NOARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#else -static PyMethodDef -swigobject_methods[] = { - {(char *)"disown", (PyCFunction)SwigPyObject_disown, METH_VARARGS, (char *)"releases ownership of the pointer"}, - {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS, (char *)"acquires ownership of the pointer"}, - {(char *)"own", (PyCFunction)SwigPyObject_own, METH_VARARGS, (char *)"returns/sets ownership of the pointer"}, - {(char *)"append", (PyCFunction)SwigPyObject_append, METH_VARARGS, (char *)"appends another 'this' object"}, - {(char *)"next", (PyCFunction)SwigPyObject_next, METH_VARARGS, (char *)"returns the next 'this' object"}, - {(char *)"__repr__",(PyCFunction)SwigPyObject_repr, METH_VARARGS, (char *)"returns object representation"}, - {0, 0, 0, 0} -}; -#endif - -#if PY_VERSION_HEX < 0x02020000 -SWIGINTERN PyObject * -SwigPyObject_getattr(SwigPyObject *sobj,char *name) -{ - return Py_FindMethod(swigobject_methods, (PyObject *)sobj, name); -} -#endif - -SWIGRUNTIME PyTypeObject* -SwigPyObject_TypeOnce(void) { - static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; - - static PyNumberMethods SwigPyObject_as_number = { - (binaryfunc)0, /*nb_add*/ - (binaryfunc)0, /*nb_subtract*/ - (binaryfunc)0, /*nb_multiply*/ - /* nb_divide removed in Python 3 */ -#if PY_VERSION_HEX < 0x03000000 - (binaryfunc)0, /*nb_divide*/ -#endif - (binaryfunc)0, /*nb_remainder*/ - (binaryfunc)0, /*nb_divmod*/ - (ternaryfunc)0,/*nb_power*/ - (unaryfunc)0, /*nb_negative*/ - (unaryfunc)0, /*nb_positive*/ - (unaryfunc)0, /*nb_absolute*/ - (inquiry)0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ -#if PY_VERSION_HEX < 0x03000000 - 0, /*nb_coerce*/ -#endif - (unaryfunc)SwigPyObject_long, /*nb_int*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_long, /*nb_long*/ -#else - 0, /*nb_reserved*/ -#endif - (unaryfunc)0, /*nb_float*/ -#if PY_VERSION_HEX < 0x03000000 - (unaryfunc)SwigPyObject_oct, /*nb_oct*/ - (unaryfunc)SwigPyObject_hex, /*nb_hex*/ -#endif -#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ -#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ -#elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ -#elif PY_VERSION_HEX >= 0x02020000 /* 2.2.0 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_true_divide */ -#elif PY_VERSION_HEX >= 0x02000000 /* 2.0.0 */ - 0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_or */ -#endif - }; - - static PyTypeObject swigpyobject_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyObject", /* tp_name */ - sizeof(SwigPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ -#if PY_VERSION_HEX < 0x02020000 - (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ -#else - (getattrfunc)0, /* tp_getattr */ -#endif - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ -#else - (cmpfunc)SwigPyObject_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyObject_repr, /* tp_repr */ - &SwigPyObject_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigobject_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - swigobject_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpyobject_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpyobject_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpyobject_type) < 0) - return NULL; -#endif - } - return &swigpyobject_type; -} - -SWIGRUNTIME PyObject * -SwigPyObject_New(void *ptr, swig_type_info *ty, int own) -{ - SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); - if (sobj) { - sobj->ptr = ptr; - sobj->ty = ty; - sobj->own = own; - sobj->next = 0; - } - return (PyObject *)sobj; -} - -/* ----------------------------------------------------------------------------- - * Implements a simple Swig Packed type, and use it instead of string - * ----------------------------------------------------------------------------- */ - -typedef struct { - PyObject_HEAD - void *pack; - swig_type_info *ty; - size_t size; -} SwigPyPacked; - -SWIGRUNTIME int -SwigPyPacked_print(SwigPyPacked *v, FILE *fp, int SWIGUNUSEDPARM(flags)) -{ - char result[SWIG_BUFFER_SIZE]; - fputs("pack, v->size, 0, sizeof(result))) { - fputs("at ", fp); - fputs(result, fp); - } - fputs(v->ty->name,fp); - fputs(">", fp); - return 0; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_repr(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { - return SWIG_Python_str_FromFormat("", result, v->ty->name); - } else { - return SWIG_Python_str_FromFormat("", v->ty->name); - } -} - -SWIGRUNTIME PyObject * -SwigPyPacked_str(SwigPyPacked *v) -{ - char result[SWIG_BUFFER_SIZE]; - if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ - return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); - } else { - return SWIG_Python_str_FromChar(v->ty->name); - } -} - -SWIGRUNTIME int -SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) -{ - size_t i = v->size; - size_t j = w->size; - int s = (i < j) ? -1 : ((i > j) ? 1 : 0); - return s ? s : strncmp((char *)v->pack, (char *)w->pack, 2*v->size); -} - -SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_type(void) { - static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); - return type; -} - -SWIGRUNTIMEINLINE int -SwigPyPacked_Check(PyObject *op) { - return ((op)->ob_type == SwigPyPacked_TypeOnce()) - || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); -} - -SWIGRUNTIME void -SwigPyPacked_dealloc(PyObject *v) -{ - if (SwigPyPacked_Check(v)) { - SwigPyPacked *sobj = (SwigPyPacked *) v; - free(sobj->pack); - } - PyObject_DEL(v); -} - -SWIGRUNTIME PyTypeObject* -SwigPyPacked_TypeOnce(void) { - static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; - static PyTypeObject swigpypacked_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX>=0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"SwigPyPacked", /* tp_name */ - sizeof(SwigPyPacked), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ - (printfunc)SwigPyPacked_print, /* tp_print */ - (getattrfunc)0, /* tp_getattr */ - (setattrfunc)0, /* tp_setattr */ -#if PY_VERSION_HEX>=0x03000000 - 0, /* tp_reserved in 3.0.1 */ -#else - (cmpfunc)SwigPyPacked_compare, /* tp_compare */ -#endif - (reprfunc)SwigPyPacked_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)0, /* tp_hash */ - (ternaryfunc)0, /* tp_call */ - (reprfunc)SwigPyPacked_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - swigpacked_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - swigpypacked_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - swigpypacked_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&swigpypacked_type) < 0) - return NULL; -#endif - } - return &swigpypacked_type; -} - -SWIGRUNTIME PyObject * -SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) -{ - SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); - if (sobj) { - void *pack = malloc(size); - if (pack) { - memcpy(pack, ptr, size); - sobj->pack = pack; - sobj->ty = ty; - sobj->size = size; - } else { - PyObject_DEL((PyObject *) sobj); - sobj = 0; - } - } - return (PyObject *) sobj; -} - -SWIGRUNTIME swig_type_info * -SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) -{ - if (SwigPyPacked_Check(obj)) { - SwigPyPacked *sobj = (SwigPyPacked *)obj; - if (sobj->size != size) return 0; - memcpy(ptr, sobj->pack, size); - return sobj->ty; - } else { - return 0; - } -} - -/* ----------------------------------------------------------------------------- - * pointers/data manipulation - * ----------------------------------------------------------------------------- */ - -SWIGRUNTIMEINLINE PyObject * -_SWIG_This(void) -{ - return SWIG_Python_str_FromChar("this"); -} - -static PyObject *swig_this = NULL; - -SWIGRUNTIME PyObject * -SWIG_This(void) -{ - if (swig_this == NULL) - swig_this = _SWIG_This(); - return swig_this; -} - -/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ - -/* TODO: I don't know how to implement the fast getset in Python 3 right now */ -#if PY_VERSION_HEX>=0x03000000 -#define SWIG_PYTHON_SLOW_GETSET_THIS -#endif - -SWIGRUNTIME SwigPyObject * -SWIG_Python_GetSwigThis(PyObject *pyobj) -{ - PyObject *obj; - - if (SwigPyObject_Check(pyobj)) - return (SwigPyObject *) pyobj; - -#ifdef SWIGPYTHON_BUILTIN - (void)obj; -# ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - pyobj = PyWeakref_GET_OBJECT(pyobj); - if (pyobj && SwigPyObject_Check(pyobj)) - return (SwigPyObject*) pyobj; - } -# endif - return NULL; -#else - - obj = 0; - -#if (!defined(SWIG_PYTHON_SLOW_GETSET_THIS) && (PY_VERSION_HEX >= 0x02030000)) - if (PyInstance_Check(pyobj)) { - obj = _PyInstance_Lookup(pyobj, SWIG_This()); - } else { - PyObject **dictptr = _PyObject_GetDictPtr(pyobj); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; - } else { -#ifdef PyWeakref_CheckProxy - if (PyWeakref_CheckProxy(pyobj)) { - PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); - return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; - } -#endif - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } - } - } -#else - obj = PyObject_GetAttr(pyobj,SWIG_This()); - if (obj) { - Py_DECREF(obj); - } else { - if (PyErr_Occurred()) PyErr_Clear(); - return 0; - } -#endif - if (obj && !SwigPyObject_Check(obj)) { - /* a PyObject is called 'this', try to get the 'real this' - SwigPyObject from it */ - return SWIG_Python_GetSwigThis(obj); - } - return (SwigPyObject *)obj; -#endif -} - -/* Acquire a pointer value */ - -SWIGRUNTIME int -SWIG_Python_AcquirePtr(PyObject *obj, int own) { - if (own == SWIG_POINTER_OWN) { - SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); - if (sobj) { - int oldown = sobj->own; - sobj->own = own; - return oldown; - } - } - return 0; -} - -/* Convert a pointer value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { - int res; - SwigPyObject *sobj; - int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; - - if (!obj) - return SWIG_ERROR; - if (obj == Py_None && !implicit_conv) { - if (ptr) - *ptr = 0; - return SWIG_OK; - } - - res = SWIG_ERROR; - - sobj = SWIG_Python_GetSwigThis(obj); - if (own) - *own = 0; - while (sobj) { - void *vptr = sobj->ptr; - if (ty) { - swig_type_info *to = sobj->ty; - if (to == ty) { - /* no type cast needed */ - if (ptr) *ptr = vptr; - break; - } else { - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) { - sobj = (SwigPyObject *)sobj->next; - } else { - if (ptr) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - if (newmemory == SWIG_CAST_NEW_MEMORY) { - assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ - if (own) - *own = *own | SWIG_CAST_NEW_MEMORY; - } - } - break; - } - } - } else { - if (ptr) *ptr = vptr; - break; - } - } - if (sobj) { - if (own) - *own = *own | sobj->own; - if (flags & SWIG_POINTER_DISOWN) { - sobj->own = 0; - } - res = SWIG_OK; - } else { - if (implicit_conv) { - SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; - if (data && !data->implicitconv) { - PyObject *klass = data->klass; - if (klass) { - PyObject *impconv; - data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ - impconv = SWIG_Python_CallFunctor(klass, obj); - data->implicitconv = 0; - if (PyErr_Occurred()) { - PyErr_Clear(); - impconv = 0; - } - if (impconv) { - SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); - if (iobj) { - void *vptr; - res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); - if (SWIG_IsOK(res)) { - if (ptr) { - *ptr = vptr; - /* transfer the ownership to 'ptr' */ - iobj->own = 0; - res = SWIG_AddCast(res); - res = SWIG_AddNewMask(res); - } else { - res = SWIG_AddCast(res); - } - } - } - Py_DECREF(impconv); - } - } - } - } - if (!SWIG_IsOK(res) && obj == Py_None) { - if (ptr) - *ptr = 0; - if (PyErr_Occurred()) - PyErr_Clear(); - res = SWIG_OK; - } - } - return res; -} - -/* Convert a function ptr value */ - -SWIGRUNTIME int -SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { - if (!PyCFunction_Check(obj)) { - return SWIG_ConvertPtr(obj, ptr, ty, 0); - } else { - void *vptr = 0; - - /* here we get the method pointer for callbacks */ - const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); - const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; - if (desc) - desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; - if (!desc) - return SWIG_ERROR; - if (ty) { - swig_cast_info *tc = SWIG_TypeCheck(desc,ty); - if (tc) { - int newmemory = 0; - *ptr = SWIG_TypeCast(tc,vptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - } else { - return SWIG_ERROR; - } - } else { - *ptr = vptr; - } - return SWIG_OK; - } -} - -/* Convert a packed value value */ - -SWIGRUNTIME int -SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { - swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); - if (!to) return SWIG_ERROR; - if (ty) { - if (to != ty) { - /* check type cast? */ - swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); - if (!tc) return SWIG_ERROR; - } - } - return SWIG_OK; -} - -/* ----------------------------------------------------------------------------- - * Create a new pointer object - * ----------------------------------------------------------------------------- */ - -/* - Create a new instance object, without calling __init__, and set the - 'this' attribute. -*/ - -SWIGRUNTIME PyObject* -SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) -{ -#if (PY_VERSION_HEX >= 0x02020000) - PyObject *inst = 0; - PyObject *newraw = data->newraw; - if (newraw) { - inst = PyObject_Call(newraw, data->newargs, NULL); - if (inst) { -#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - PyObject *dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - PyDict_SetItem(dict, SWIG_This(), swig_this); - } - } -#else - PyObject *key = SWIG_This(); - PyObject_SetAttr(inst, key, swig_this); -#endif - } - } else { -#if PY_VERSION_HEX >= 0x03000000 - inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None); - if (inst) { - PyObject_SetAttr(inst, SWIG_This(), swig_this); - Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; - } -#else - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } -#endif - } - return inst; -#else -#if (PY_VERSION_HEX >= 0x02010000) - PyObject *inst = 0; - PyObject *dict = PyDict_New(); - if (dict) { - PyDict_SetItem(dict, SWIG_This(), swig_this); - inst = PyInstance_NewRaw(data->newargs, dict); - Py_DECREF(dict); - } - return (PyObject *) inst; -#else - PyInstanceObject *inst = PyObject_NEW(PyInstanceObject, &PyInstance_Type); - if (inst == NULL) { - return NULL; - } - inst->in_class = (PyClassObject *)data->newargs; - Py_INCREF(inst->in_class); - inst->in_dict = PyDict_New(); - if (inst->in_dict == NULL) { - Py_DECREF(inst); - return NULL; - } -#ifdef Py_TPFLAGS_HAVE_WEAKREFS - inst->in_weakreflist = NULL; -#endif -#ifdef Py_TPFLAGS_GC - PyObject_GC_Init(inst); -#endif - PyDict_SetItem(inst->in_dict, SWIG_This(), swig_this); - return (PyObject *) inst; -#endif -#endif -} - -SWIGRUNTIME void -SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) -{ - PyObject *dict; -#if (PY_VERSION_HEX >= 0x02020000) && !defined(SWIG_PYTHON_SLOW_GETSET_THIS) - PyObject **dictptr = _PyObject_GetDictPtr(inst); - if (dictptr != NULL) { - dict = *dictptr; - if (dict == NULL) { - dict = PyDict_New(); - *dictptr = dict; - } - PyDict_SetItem(dict, SWIG_This(), swig_this); - return; - } -#endif - dict = PyObject_GetAttrString(inst, (char*)"__dict__"); - PyDict_SetItem(dict, SWIG_This(), swig_this); - Py_DECREF(dict); -} - - -SWIGINTERN PyObject * -SWIG_Python_InitShadowInstance(PyObject *args) { - PyObject *obj[2]; - if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { - return NULL; - } else { - SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); - if (sthis) { - SwigPyObject_append((PyObject*) sthis, obj[1]); - } else { - SWIG_Python_SetSwigThis(obj[0], obj[1]); - } - return SWIG_Py_Void(); - } -} - -/* Create a new pointer object */ - -SWIGRUNTIME PyObject * -SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { - SwigPyClientData *clientdata; - PyObject * robj; - int own; - - if (!ptr) - return SWIG_Py_Void(); - - clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; - own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; - if (clientdata && clientdata->pytype) { - SwigPyObject *newobj; - if (flags & SWIG_BUILTIN_TP_INIT) { - newobj = (SwigPyObject*) self; - if (newobj->ptr) { - PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); - while (newobj->next) - newobj = (SwigPyObject *) newobj->next; - newobj->next = next_self; - newobj = (SwigPyObject *)next_self; -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - } else { - newobj = PyObject_New(SwigPyObject, clientdata->pytype); -#ifdef SWIGPYTHON_BUILTIN - newobj->dict = 0; -#endif - } - if (newobj) { - newobj->ptr = ptr; - newobj->ty = type; - newobj->own = own; - newobj->next = 0; - return (PyObject*) newobj; - } - return SWIG_Py_Void(); - } - - assert(!(flags & SWIG_BUILTIN_TP_INIT)); - - robj = SwigPyObject_New(ptr, type, own); - if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { - PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); - Py_DECREF(robj); - robj = inst; - } - return robj; -} - -/* Create a new packed object */ - -SWIGRUNTIMEINLINE PyObject * -SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { - return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); -} - -/* -----------------------------------------------------------------------------* - * Get type list - * -----------------------------------------------------------------------------*/ - -#ifdef SWIG_LINK_RUNTIME -void *SWIG_ReturnGlobalTypeList(void *); -#endif - -SWIGRUNTIME swig_module_info * -SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { - static void *type_pointer = (void *)0; - /* first check if module already created */ - if (!type_pointer) { -#ifdef SWIG_LINK_RUNTIME - type_pointer = SWIG_ReturnGlobalTypeList((void *)0); -#else -# ifdef SWIGPY_USE_CAPSULE - type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); -# else - type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, - (char*)"type_pointer" SWIG_TYPE_TABLE_NAME); -# endif - if (PyErr_Occurred()) { - PyErr_Clear(); - type_pointer = (void *)0; - } -#endif - } - return (swig_module_info *) type_pointer; -} - -#if PY_MAJOR_VERSION < 2 -/* PyModule_AddObject function was introduced in Python 2.0. The following function - is copied out of Python/modsupport.c in python version 2.3.4 */ -SWIGINTERN int -PyModule_AddObject(PyObject *m, char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg"); - return SWIG_ERROR; - } - if (!o) { - PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value"); - return SWIG_ERROR; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return SWIG_ERROR; - } - if (PyDict_SetItemString(dict, name, o)) - return SWIG_ERROR; - Py_DECREF(o); - return SWIG_OK; -} -#endif - -SWIGRUNTIME void -#ifdef SWIGPY_USE_CAPSULE -SWIG_Python_DestroyModule(PyObject *obj) -#else -SWIG_Python_DestroyModule(void *vptr) -#endif -{ -#ifdef SWIGPY_USE_CAPSULE - swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); -#else - swig_module_info *swig_module = (swig_module_info *) vptr; -#endif - swig_type_info **types = swig_module->types; - size_t i; - for (i =0; i < swig_module->size; ++i) { - swig_type_info *ty = types[i]; - if (ty->owndata) { - SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; - if (data) SwigPyClientData_Del(data); - } - } - Py_DECREF(SWIG_This()); - swig_this = NULL; -} - -SWIGRUNTIME void -SWIG_Python_SetModule(swig_module_info *swig_module) { -#if PY_VERSION_HEX >= 0x03000000 - /* Add a dummy module object into sys.modules */ - PyObject *module = PyImport_AddModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION); -#else - static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ - PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); -#endif -#ifdef SWIGPY_USE_CAPSULE - PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#else - PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule); - if (pointer && module) { - PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer); - } else { - Py_XDECREF(pointer); - } -#endif -} - -/* The python cached type query */ -SWIGRUNTIME PyObject * -SWIG_Python_TypeCache(void) { - static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); - return cache; -} - -SWIGRUNTIME swig_type_info * -SWIG_Python_TypeQuery(const char *type) -{ - PyObject *cache = SWIG_Python_TypeCache(); - PyObject *key = SWIG_Python_str_FromChar(type); - PyObject *obj = PyDict_GetItem(cache, key); - swig_type_info *descriptor; - if (obj) { -#ifdef SWIGPY_USE_CAPSULE - descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); -#else - descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj); -#endif - } else { - swig_module_info *swig_module = SWIG_GetModule(0); - descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); - if (descriptor) { -#ifdef SWIGPY_USE_CAPSULE - obj = PyCapsule_New((void*) descriptor, NULL, NULL); -#else - obj = PyCObject_FromVoidPtr(descriptor, NULL); -#endif - PyDict_SetItem(cache, key, obj); - Py_DECREF(obj); - } - } - Py_DECREF(key); - return descriptor; -} - -/* - For backward compatibility only -*/ -#define SWIG_POINTER_EXCEPTION 0 -#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) -#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) - -SWIGRUNTIME int -SWIG_Python_AddErrMesg(const char* mesg, int infront) -{ - if (PyErr_Occurred()) { - PyObject *type = 0; - PyObject *value = 0; - PyObject *traceback = 0; - PyErr_Fetch(&type, &value, &traceback); - if (value) { - char *tmp; - PyObject *old_str = PyObject_Str(value); - Py_XINCREF(type); - PyErr_Clear(); - if (infront) { - PyErr_Format(type, "%s %s", mesg, tmp = SWIG_Python_str_AsChar(old_str)); - } else { - PyErr_Format(type, "%s %s", tmp = SWIG_Python_str_AsChar(old_str), mesg); - } - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(old_str); - } - return 1; - } else { - return 0; - } -} - -SWIGRUNTIME int -SWIG_Python_ArgFail(int argnum) -{ - if (PyErr_Occurred()) { - /* add information about failing argument */ - char mesg[256]; - PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); - return SWIG_Python_AddErrMesg(mesg, 1); - } else { - return 0; - } -} - -SWIGRUNTIMEINLINE const char * -SwigPyObject_GetDesc(PyObject *self) -{ - SwigPyObject *v = (SwigPyObject *)self; - swig_type_info *ty = v ? v->ty : 0; - return ty ? ty->str : ""; -} - -SWIGRUNTIME void -SWIG_Python_TypeError(const char *type, PyObject *obj) -{ - if (type) { -#if defined(SWIG_COBJECT_TYPES) - if (obj && SwigPyObject_Check(obj)) { - const char *otype = (const char *) SwigPyObject_GetDesc(obj); - if (otype) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", - type, otype); - return; - } - } else -#endif - { - const char *otype = (obj ? obj->ob_type->tp_name : 0); - if (otype) { - PyObject *str = PyObject_Str(obj); - const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; - if (cstr) { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", - type, otype, cstr); - SWIG_Python_str_DelForPy3(cstr); - } else { - PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", - type, otype); - } - Py_XDECREF(str); - return; - } - } - PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); - } else { - PyErr_Format(PyExc_TypeError, "unexpected type is received"); - } -} - - -/* Convert a pointer value, signal an exception on a type mismatch */ -SWIGRUNTIME void * -SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { - void *result; - if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { - PyErr_Clear(); -#if SWIG_POINTER_EXCEPTION - if (flags) { - SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); - SWIG_Python_ArgFail(argnum); - } -#endif - } - return result; -} - -#ifdef SWIGPYTHON_BUILTIN -SWIGRUNTIME int -SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { - PyTypeObject *tp = obj->ob_type; - PyObject *descr; - PyObject *encoded_name; - descrsetfunc f; - int res = -1; - -# ifdef Py_USING_UNICODE - if (PyString_Check(name)) { - name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); - if (!name) - return -1; - } else if (!PyUnicode_Check(name)) -# else - if (!PyString_Check(name)) -# endif - { - PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); - return -1; - } else { - Py_INCREF(name); - } - - if (!tp->tp_dict) { - if (PyType_Ready(tp) < 0) - goto done; - } - - descr = _PyType_Lookup(tp, name); - f = NULL; - if (descr != NULL) - f = descr->ob_type->tp_descr_set; - if (!f) { - if (PyString_Check(name)) { - encoded_name = name; - Py_INCREF(name); - } else { - encoded_name = PyUnicode_AsUTF8String(name); - } - PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); - Py_DECREF(encoded_name); - } else { - res = f(descr, obj, value); - } - - done: - Py_DECREF(name); - return res; -} -#endif - - -#ifdef __cplusplus -} -#endif - - - -#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) - -#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else - - -/* ----------------------------------------------------------------------------- - * director_common.swg - * - * This file contains support for director classes which is common between - * languages. - * ----------------------------------------------------------------------------- */ - -/* - Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the - 'Swig' namespace. This could be useful for multi-modules projects. -*/ -#ifdef SWIG_DIRECTOR_STATIC -/* Force anonymous (static) namespace */ -#define Swig -#endif -/* ----------------------------------------------------------------------------- - * director.swg - * - * This file contains support for director classes so that Python proxy - * methods can be called from C++. - * ----------------------------------------------------------------------------- */ - -#ifndef SWIG_DIRECTOR_PYTHON_HEADER_ -#define SWIG_DIRECTOR_PYTHON_HEADER_ - -#include -#include -#include -#include -#include - - -/* - Use -DSWIG_PYTHON_DIRECTOR_NO_VTABLE if you don't want to generate a 'virtual - table', and avoid multiple GetAttr calls to retrieve the python - methods. -*/ - -#ifndef SWIG_PYTHON_DIRECTOR_NO_VTABLE -#ifndef SWIG_PYTHON_DIRECTOR_VTABLE -#define SWIG_PYTHON_DIRECTOR_VTABLE -#endif -#endif - - - -/* - Use -DSWIG_DIRECTOR_NO_UEH if you prefer to avoid the use of the - Undefined Exception Handler provided by swig. -*/ -#ifndef SWIG_DIRECTOR_NO_UEH -#ifndef SWIG_DIRECTOR_UEH -#define SWIG_DIRECTOR_UEH -#endif -#endif - - -/* - Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the - native C++ RTTI and dynamic_cast<>. But be aware that directors - could stop working when using this option. -*/ -#ifdef SWIG_DIRECTOR_NORTTI -/* - When we don't use the native C++ RTTI, we implement a minimal one - only for Directors. -*/ -# ifndef SWIG_DIRECTOR_RTDIR -# define SWIG_DIRECTOR_RTDIR - -namespace Swig { - class Director; - SWIGINTERN std::map& get_rtdir_map() { - static std::map rtdir_map; - return rtdir_map; - } - - SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) { - get_rtdir_map()[vptr] = rtdir; - } - - SWIGINTERNINLINE Director *get_rtdir(void *vptr) { - std::map::const_iterator pos = get_rtdir_map().find(vptr); - Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0; - return rtdir; - } -} -# endif /* SWIG_DIRECTOR_RTDIR */ - -# define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast(ARG)) -# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast(ARG1), ARG2) - -#else - -# define SWIG_DIRECTOR_CAST(ARG) dynamic_cast(ARG) -# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) - -#endif /* SWIG_DIRECTOR_NORTTI */ - -extern "C" { - struct swig_type_info; -} - -namespace Swig { - - /* memory handler */ - struct GCItem { - virtual ~GCItem() {} - - virtual int get_own() const { - return 0; - } - }; - - struct GCItem_var { - GCItem_var(GCItem *item = 0) : _item(item) { - } - - GCItem_var& operator=(GCItem *item) { - GCItem *tmp = _item; - _item = item; - delete tmp; - return *this; - } - - ~GCItem_var() { - delete _item; - } - - GCItem * operator->() const { - return _item; - } - - private: - GCItem *_item; - }; - - struct GCItem_Object : GCItem { - GCItem_Object(int own) : _own(own) { - } - - virtual ~GCItem_Object() { - } - - int get_own() const { - return _own; - } - - private: - int _own; - }; - - template - struct GCItem_T : GCItem { - GCItem_T(Type *ptr) : _ptr(ptr) { - } - - virtual ~GCItem_T() { - delete _ptr; - } - - private: - Type *_ptr; - }; - - template - struct GCArray_T : GCItem { - GCArray_T(Type *ptr) : _ptr(ptr) { - } - - virtual ~GCArray_T() { - delete[] _ptr; - } - - private: - Type *_ptr; - }; - - /* base class for director exceptions */ - class DirectorException : public std::exception { - protected: - std::string swig_msg; - public: - DirectorException(PyObject *error, const char *hdr ="", const char *msg ="") : swig_msg(hdr) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - if (msg[0]) { - swig_msg += " "; - swig_msg += msg; - } - if (!PyErr_Occurred()) { - PyErr_SetString(error, what()); - } - SWIG_PYTHON_THREAD_END_BLOCK; - } - - virtual ~DirectorException() throw() { - } - - /* Deprecated, use what() instead */ - const char *getMessage() const { - return what(); - } - - const char *what() const throw() { - return swig_msg.c_str(); - } - - static void raise(PyObject *error, const char *msg) { - throw DirectorException(error, msg); - } - - static void raise(const char *msg) { - raise(PyExc_RuntimeError, msg); - } - }; - - /* unknown exception handler */ - class UnknownExceptionHandler { -#ifdef SWIG_DIRECTOR_UEH - static void handler() { - try { - throw; - } catch (DirectorException& e) { - std::cerr << "SWIG Director exception caught:" << std::endl - << e.what() << std::endl; - } catch (std::exception& e) { - std::cerr << "std::exception caught: "<< e.what() << std::endl; - } catch (...) { - std::cerr << "Unknown exception caught." << std::endl; - } - - std::cerr << std::endl - << "Python interpreter traceback:" << std::endl; - PyErr_Print(); - std::cerr << std::endl; - - std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl - << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl - << std::endl - << "Exception is being re-thrown, program will likely abort/terminate." << std::endl; - throw; - } - - public: - - std::unexpected_handler old; - UnknownExceptionHandler(std::unexpected_handler nh = handler) { - old = std::set_unexpected(nh); - } - - ~UnknownExceptionHandler() { - std::set_unexpected(old); - } -#endif - }; - - /* type mismatch in the return value from a python method call */ - class DirectorTypeMismatchException : public DirectorException { - public: - DirectorTypeMismatchException(PyObject *error, const char *msg="") - : DirectorException(error, "SWIG director type mismatch", msg) { - } - - DirectorTypeMismatchException(const char *msg="") - : DirectorException(PyExc_TypeError, "SWIG director type mismatch", msg) { - } - - static void raise(PyObject *error, const char *msg) { - throw DirectorTypeMismatchException(error, msg); - } - - static void raise(const char *msg) { - throw DirectorTypeMismatchException(msg); - } - }; - - /* any python exception that occurs during a director method call */ - class DirectorMethodException : public DirectorException { - public: - DirectorMethodException(const char *msg = "") - : DirectorException(PyExc_RuntimeError, "SWIG director method error.", msg) { - } - - static void raise(const char *msg) { - throw DirectorMethodException(msg); - } - }; - - /* attempt to call a pure virtual method via a director method */ - class DirectorPureVirtualException : public DirectorException { - public: - DirectorPureVirtualException(const char *msg = "") - : DirectorException(PyExc_RuntimeError, "SWIG director pure virtual method called", msg) { - } - - static void raise(const char *msg) { - throw DirectorPureVirtualException(msg); - } - }; - - -#if defined(SWIG_PYTHON_THREADS) -/* __THREAD__ is the old macro to activate some thread support */ -# if !defined(__THREAD__) -# define __THREAD__ 1 -# endif -#endif - -#ifdef __THREAD__ -# include "pythread.h" - class Guard { - PyThread_type_lock &mutex_; - - public: - Guard(PyThread_type_lock & mutex) : mutex_(mutex) { - PyThread_acquire_lock(mutex_, WAIT_LOCK); - } - - ~Guard() { - PyThread_release_lock(mutex_); - } - }; -# define SWIG_GUARD(mutex) Guard _guard(mutex) -#else -# define SWIG_GUARD(mutex) -#endif - - /* director base class */ - class Director { - private: - /* pointer to the wrapped python object */ - PyObject *swig_self; - /* flag indicating whether the object is owned by python or c++ */ - mutable bool swig_disown_flag; - - /* decrement the reference count of the wrapped python object */ - void swig_decref() const { - if (swig_disown_flag) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_DECREF(swig_self); - SWIG_PYTHON_THREAD_END_BLOCK; - } - } - - public: - /* wrap a python object. */ - Director(PyObject *self) : swig_self(self), swig_disown_flag(false) { - } - - /* discard our reference at destruction */ - virtual ~Director() { - swig_decref(); - } - - /* return a pointer to the wrapped python object */ - PyObject *swig_get_self() const { - return swig_self; - } - - /* acquire ownership of the wrapped python object (the sense of "disown" is from python) */ - void swig_disown() const { - if (!swig_disown_flag) { - swig_disown_flag=true; - swig_incref(); - } - } - - /* increase the reference count of the wrapped python object */ - void swig_incref() const { - if (swig_disown_flag) { - Py_INCREF(swig_self); - } - } - - /* methods to implement pseudo protected director members */ - virtual bool swig_get_inner(const char * /* swig_protected_method_name */) const { - return true; - } - - virtual void swig_set_inner(const char * /* swig_protected_method_name */, bool /* swig_val */) const { - } - - /* ownership management */ - private: - typedef std::map swig_ownership_map; - mutable swig_ownership_map swig_owner; -#ifdef __THREAD__ - static PyThread_type_lock swig_mutex_own; -#endif - - public: - template - void swig_acquire_ownership_array(Type *vptr) const { - if (vptr) { - SWIG_GUARD(swig_mutex_own); - swig_owner[vptr] = new GCArray_T(vptr); - } - } - - template - void swig_acquire_ownership(Type *vptr) const { - if (vptr) { - SWIG_GUARD(swig_mutex_own); - swig_owner[vptr] = new GCItem_T(vptr); - } - } - - void swig_acquire_ownership_obj(void *vptr, int own) const { - if (vptr && own) { - SWIG_GUARD(swig_mutex_own); - swig_owner[vptr] = new GCItem_Object(own); - } - } - - int swig_release_ownership(void *vptr) const { - int own = 0; - if (vptr) { - SWIG_GUARD(swig_mutex_own); - swig_ownership_map::iterator iter = swig_owner.find(vptr); - if (iter != swig_owner.end()) { - own = iter->second->get_own(); - swig_owner.erase(iter); - } - } - return own; - } - - template - static PyObject *swig_pyobj_disown(PyObject *pyobj, PyObject *SWIGUNUSEDPARM(args)) { - SwigPyObject *sobj = (SwigPyObject *)pyobj; - sobj->own = 0; - Director *d = SWIG_DIRECTOR_CAST(reinterpret_cast(sobj->ptr)); - if (d) - d->swig_disown(); - return PyWeakref_NewProxy(pyobj, NULL); - } - }; - -#ifdef __THREAD__ - PyThread_type_lock Director::swig_mutex_own = PyThread_allocate_lock(); -#endif -} - -#endif - -/* -------- TYPES TABLE (BEGIN) -------- */ - -#define SWIGTYPE_p__kclvm_plugin_AppContextBase swig_types[0] -#define SWIGTYPE_p_char swig_types[1] -#define SWIGTYPE_p_int swig_types[2] -#define SWIGTYPE_p_long_long swig_types[3] -#define SWIGTYPE_p_short swig_types[4] -#define SWIGTYPE_p_signed_char swig_types[5] -#define SWIGTYPE_p_unsigned_char swig_types[6] -#define SWIGTYPE_p_unsigned_int swig_types[7] -#define SWIGTYPE_p_unsigned_long_long swig_types[8] -#define SWIGTYPE_p_unsigned_short swig_types[9] -static swig_type_info *swig_types[11]; -static swig_module_info swig_module = {swig_types, 10, 0, 0, 0, 0}; -#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) -#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) - -/* -------- TYPES TABLE (END) -------- */ - -#if (PY_VERSION_HEX <= 0x02000000) -# if !defined(SWIG_PYTHON_CLASSIC) -# error "This python version requires swig to be run with the '-classic' option" -# endif -#endif - -/*----------------------------------------------- - @(target):= _kclvm_plugin.so - ------------------------------------------------*/ -#if PY_VERSION_HEX >= 0x03000000 -# define SWIG_init PyInit__kclvm_plugin - -#else -# define SWIG_init init_kclvm_plugin - -#endif -#define SWIG_name "_kclvm_plugin" - -#define SWIGVERSION 0x030012 -#define SWIG_VERSION SWIGVERSION - - -#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) -#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),reinterpret_cast< void** >(a)) - - -#include - - -namespace swig { - class SwigPtr_PyObject { - protected: - PyObject *_obj; - - public: - SwigPtr_PyObject() :_obj(0) - { - } - - SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj) - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - - SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj) - { - if (initial_ref) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - } - - SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XINCREF(item._obj); - Py_XDECREF(_obj); - _obj = item._obj; - SWIG_PYTHON_THREAD_END_BLOCK; - return *this; - } - - ~SwigPtr_PyObject() - { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - Py_XDECREF(_obj); - SWIG_PYTHON_THREAD_END_BLOCK; - } - - operator PyObject *() const - { - return _obj; - } - - PyObject *operator->() const - { - return _obj; - } - }; -} - - -namespace swig { - struct SwigVar_PyObject : SwigPtr_PyObject { - SwigVar_PyObject(PyObject* obj = 0) : SwigPtr_PyObject(obj, false) { } - - SwigVar_PyObject & operator = (PyObject* obj) - { - Py_XDECREF(_obj); - _obj = obj; - return *this; - } - }; -} - - -#define SWIG_FILE_WITH_INIT -#include "kclvm_plugin.h" - - -#include // Use the C99 official header - - -#include - - -SWIGINTERN swig_type_info* -SWIG_pchar_descriptor(void) -{ - static int init = 0; - static swig_type_info* info = 0; - if (!init) { - info = SWIG_TypeQuery("_p_char"); - init = 1; - } - return info; -} - - -SWIGINTERN int -SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) -{ -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (PyBytes_Check(obj)) -#else - if (PyUnicode_Check(obj)) -#endif -#else - if (PyString_Check(obj)) -#endif - { - char *cstr; Py_ssize_t len; -#if PY_VERSION_HEX>=0x03000000 -#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - if (!alloc && cptr) { - /* We can't allow converting without allocation, since the internal - representation of string in Python 3 is UCS-2/UCS-4 but we require - a UTF-8 representation. - TODO(bhy) More detailed explanation */ - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if(alloc) *alloc = SWIG_NEWOBJ; -#endif - PyBytes_AsStringAndSize(obj, &cstr, &len); -#else - PyString_AsStringAndSize(obj, &cstr, &len); -#endif - if (cptr) { - if (alloc) { - /* - In python the user should not be able to modify the inner - string representation. To warranty that, if you define - SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string - buffer is always returned. - - The default behavior is just to return the pointer value, - so, be careful. - */ -#if defined(SWIG_PYTHON_SAFE_CSTRINGS) - if (*alloc != SWIG_OLDOBJ) -#else - if (*alloc == SWIG_NEWOBJ) -#endif - { - *cptr = reinterpret_cast< char* >(memcpy(new char[len + 1], cstr, sizeof(char)*(len + 1))); - *alloc = SWIG_NEWOBJ; - } else { - *cptr = cstr; - *alloc = SWIG_OLDOBJ; - } - } else { -#if PY_VERSION_HEX>=0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - *cptr = PyBytes_AsString(obj); -#else - assert(0); /* Should never reach here with Unicode strings in Python 3 */ -#endif -#else - *cptr = SWIG_Python_str_AsChar(obj); -#endif - } - } - if (psize) *psize = len + 1; -#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - Py_XDECREF(obj); -#endif - return SWIG_OK; - } else { -#if defined(SWIG_PYTHON_2_UNICODE) -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) -#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once" -#endif -#if PY_VERSION_HEX<0x03000000 - if (PyUnicode_Check(obj)) { - char *cstr; Py_ssize_t len; - if (!alloc && cptr) { - return SWIG_RuntimeError; - } - obj = PyUnicode_AsUTF8String(obj); - if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { - if (cptr) { - if (alloc) *alloc = SWIG_NEWOBJ; - *cptr = reinterpret_cast< char* >(memcpy(new char[len + 1], cstr, sizeof(char)*(len + 1))); - } - if (psize) *psize = len + 1; - - Py_XDECREF(obj); - return SWIG_OK; - } else { - Py_XDECREF(obj); - } - } -#endif -#endif - - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - if (pchar_descriptor) { - void* vptr = 0; - if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { - if (cptr) *cptr = (char *) vptr; - if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; - if (alloc) *alloc = SWIG_OLDOBJ; - return SWIG_OK; - } - } - } - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsPtr_std_string (PyObject * obj, std::string **val) -{ - char* buf = 0 ; size_t size = 0; int alloc = SWIG_OLDOBJ; - if (SWIG_IsOK((SWIG_AsCharPtrAndSize(obj, &buf, &size, &alloc)))) { - if (buf) { - if (val) *val = new std::string(buf, size - 1); - if (alloc == SWIG_NEWOBJ) delete[] buf; - return SWIG_NEWOBJ; - } else { - if (val) *val = 0; - return SWIG_OLDOBJ; - } - } else { - static int init = 0; - static swig_type_info* descriptor = 0; - if (!init) { - descriptor = SWIG_TypeQuery("std::string" " *"); - init = 1; - } - if (descriptor) { - std::string *vptr; - int res = SWIG_ConvertPtr(obj, (void**)&vptr, descriptor, 0); - if (SWIG_IsOK(res) && val) *val = vptr; - return res; - } - } - return SWIG_ERROR; -} - - -SWIGINTERNINLINE PyObject * -SWIG_FromCharPtrAndSize(const char* carray, size_t size) -{ - if (carray) { - if (size > INT_MAX) { - swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); - return pchar_descriptor ? - SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void(); - } else { -#if PY_VERSION_HEX >= 0x03000000 -#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) - return PyBytes_FromStringAndSize(carray, static_cast< Py_ssize_t >(size)); -#else -#if PY_VERSION_HEX >= 0x03010000 - return PyUnicode_DecodeUTF8(carray, static_cast< Py_ssize_t >(size), "surrogateescape"); -#else - return PyUnicode_FromStringAndSize(carray, static_cast< Py_ssize_t >(size)); -#endif -#endif -#else - return PyString_FromStringAndSize(carray, static_cast< Py_ssize_t >(size)); -#endif - } - } else { - return SWIG_Py_Void(); - } -} - - -SWIGINTERNINLINE PyObject * -SWIG_From_std_string (const std::string& s) -{ - return SWIG_FromCharPtrAndSize(s.data(), s.size()); -} - - -SWIGINTERN int -SWIG_AsVal_double (PyObject *obj, double *val) -{ - int res = SWIG_TypeError; - if (PyFloat_Check(obj)) { - if (val) *val = PyFloat_AsDouble(obj); - return SWIG_OK; -#if PY_VERSION_HEX < 0x03000000 - } else if (PyInt_Check(obj)) { - if (val) *val = (double) PyInt_AsLong(obj); - return SWIG_OK; -#endif - } else if (PyLong_Check(obj)) { - double v = PyLong_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - double d = PyFloat_AsDouble(obj); - if (!PyErr_Occurred()) { - if (val) *val = d; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_AddCast(SWIG_OK)); - } else { - PyErr_Clear(); - } - } - } -#endif - return res; -} - - -#include - - -#include - - -SWIGINTERNINLINE int -SWIG_CanCastAsInteger(double *d, double min, double max) { - double x = *d; - if ((min <= x && x <= max)) { - double fx = floor(x); - double cx = ceil(x); - double rd = ((x - fx) < 0.5) ? fx : cx; /* simple rint */ - if ((errno == EDOM) || (errno == ERANGE)) { - errno = 0; - } else { - double summ, reps, diff; - if (rd < x) { - diff = x - rd; - } else if (rd > x) { - diff = rd - x; - } else { - return 1; - } - summ = rd + x; - reps = diff/summ; - if (reps < 8*DBL_EPSILON) { - *d = rd; - return 1; - } - } - } - return 0; -} - - -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - long v = PyInt_AsLong(obj); - if (v >= 0) { - if (val) *val = v; - return SWIG_OK; - } else { - return SWIG_OverflowError; - } - } else -#endif - if (PyLong_Check(obj)) { - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - unsigned long v = PyLong_AsUnsignedLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { - if (val) *val = (unsigned long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -#include -#if !defined(SWIG_NO_LLONG_MAX) -# if !defined(LLONG_MAX) && defined(__GNUC__) && defined (__LONG_LONG_MAX__) -# define LLONG_MAX __LONG_LONG_MAX__ -# define LLONG_MIN (-LLONG_MAX - 1LL) -# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) -# endif -#endif - - -#if defined(LLONG_MAX) && !defined(SWIG_LONG_LONG_AVAILABLE) -# define SWIG_LONG_LONG_AVAILABLE -#endif - - -#ifdef SWIG_LONG_LONG_AVAILABLE -SWIGINTERN int -SWIG_AsVal_unsigned_SS_long_SS_long (PyObject *obj, unsigned long long *val) -{ - int res = SWIG_TypeError; - if (PyLong_Check(obj)) { - unsigned long long v = PyLong_AsUnsignedLongLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - res = SWIG_OverflowError; - } - } else { - unsigned long v; - res = SWIG_AsVal_unsigned_SS_long (obj,&v); - if (SWIG_IsOK(res)) { - if (val) *val = v; - return res; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - const double mant_max = 1LL << DBL_MANT_DIG; - double d; - res = SWIG_AsVal_double (obj,&d); - if (SWIG_IsOK(res) && !SWIG_CanCastAsInteger(&d, 0, mant_max)) - return SWIG_OverflowError; - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, mant_max)) { - if (val) *val = (unsigned long long)(d); - return SWIG_AddCast(res); - } - res = SWIG_TypeError; - } -#endif - return res; -} -#endif - - -SWIGINTERN int -SWIG_AsVal_long (PyObject *obj, long* val) -{ -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(obj)) { - if (val) *val = PyInt_AsLong(obj); - return SWIG_OK; - } else -#endif - if (PyLong_Check(obj)) { - long v = PyLong_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_OK; - } else { - PyErr_Clear(); - return SWIG_OverflowError; - } - } -#ifdef SWIG_PYTHON_CAST_MODE - { - int dispatch = 0; - long v = PyInt_AsLong(obj); - if (!PyErr_Occurred()) { - if (val) *val = v; - return SWIG_AddCast(SWIG_OK); - } else { - PyErr_Clear(); - } - if (!dispatch) { - double d; - int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d)); - if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { - if (val) *val = (long)(d); - return res; - } - } - } -#endif - return SWIG_TypeError; -} - - -SWIGINTERN int -SWIG_AsVal_int (PyObject * obj, int *val) -{ - long v; - int res = SWIG_AsVal_long (obj, &v); - if (SWIG_IsOK(res)) { - if ((v < INT_MIN || v > INT_MAX)) { - return SWIG_OverflowError; - } else { - if (val) *val = static_cast< int >(v); - } - } - return res; -} - - -#ifdef SWIG_LONG_LONG_AVAILABLE -SWIGINTERNINLINE PyObject* -SWIG_From_unsigned_SS_long_SS_long (unsigned long long value) -{ - return (value > LONG_MAX) ? - PyLong_FromUnsignedLongLong(value) : PyInt_FromLong(static_cast< long >(value)); -} -#endif - - - -/* --------------------------------------------------- - * C++ director class methods - * --------------------------------------------------- */ - -#include "kclvm_plugin_wrap.h" - -SwigDirector__kclvm_plugin_AppContextBase::SwigDirector__kclvm_plugin_AppContextBase(PyObject *self, uint64_t rust_invoke_json_ptr): _kclvm_plugin_AppContextBase(rust_invoke_json_ptr), Swig::Director(self) { - SWIG_DIRECTOR_RGTR((_kclvm_plugin_AppContextBase *)this, this); -} - - - - -SwigDirector__kclvm_plugin_AppContextBase::~SwigDirector__kclvm_plugin_AppContextBase() { -} - -std::string SwigDirector__kclvm_plugin_AppContextBase::_call_py_method(std::string const &name, std::string const &args_json, std::string const &kwargs_json) { - std::string c_result; - swig::SwigVar_PyObject obj0; - obj0 = SWIG_From_std_string(static_cast< std::string >(name)); - swig::SwigVar_PyObject obj1; - obj1 = SWIG_From_std_string(static_cast< std::string >(args_json)); - swig::SwigVar_PyObject obj2; - obj2 = SWIG_From_std_string(static_cast< std::string >(kwargs_json)); - if (!swig_get_self()) { - Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call _kclvm_plugin_AppContextBase.__init__."); - } -#if defined(SWIG_PYTHON_DIRECTOR_VTABLE) - const size_t swig_method_index = 0; - const char *const swig_method_name = "_call_py_method"; - PyObject *method = swig_get_method(swig_method_index, swig_method_name); - swig::SwigVar_PyObject result = PyObject_CallFunction(method, (char *)"(OOO)" ,(PyObject *)obj0,(PyObject *)obj1,(PyObject *)obj2); -#else - swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *)"_call_py_method", (char *)"(OOO)" ,(PyObject *)obj0,(PyObject *)obj1,(PyObject *)obj2); -#endif - if (!result) { - PyObject *error = PyErr_Occurred(); - if (error) { - Swig::DirectorMethodException::raise("Error detected when calling '_kclvm_plugin_AppContextBase._call_py_method'"); - } - } - std::string *swig_optr = 0; - int swig_ores = SWIG_AsPtr_std_string(result, &swig_optr); - if (!SWIG_IsOK(swig_ores) || !swig_optr) { - Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(SWIG_ArgError((swig_optr ? swig_ores : SWIG_TypeError))), "in output value of type '""std::string""'"); - } - c_result = *swig_optr; - if (SWIG_IsNewObj(swig_ores)) delete swig_optr; - return (std::string) c_result; -} - - -#ifdef __cplusplus -extern "C" { -#endif -SWIGINTERN PyObject *_wrap_new__kclvm_plugin_AppContextBase(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - PyObject *arg1 = (PyObject *) 0 ; - uint64_t arg2 ; - unsigned long long val2 ; - int ecode2 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - _kclvm_plugin_AppContextBase *result = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OO:new__kclvm_plugin_AppContextBase",&obj0,&obj1)) SWIG_fail; - arg1 = obj0; - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new__kclvm_plugin_AppContextBase" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - if ( arg1 != Py_None ) { - /* subclassed */ - result = (_kclvm_plugin_AppContextBase *)new SwigDirector__kclvm_plugin_AppContextBase(arg1,arg2); - } else { - result = (_kclvm_plugin_AppContextBase *)new _kclvm_plugin_AppContextBase(arg2); - } - - resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p__kclvm_plugin_AppContextBase, SWIG_POINTER_NEW | 0 ); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap_delete__kclvm_plugin_AppContextBase(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"O:delete__kclvm_plugin_AppContextBase",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, SWIG_POINTER_DISOWN | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete__kclvm_plugin_AppContextBase" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - delete arg1; - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__clear_options(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"O:_kclvm_plugin_AppContextBase__clear_options",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__clear_options" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - (arg1)->_clear_options(); - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__add_option(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - std::string *arg2 = 0 ; - std::string *arg3 = 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 = SWIG_OLDOBJ ; - int res3 = SWIG_OLDOBJ ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"OOO:_kclvm_plugin_AppContextBase__add_option",&obj0,&obj1,&obj2)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__add_option" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - { - std::string *ptr = (std::string *)0; - res2 = SWIG_AsPtr_std_string(obj1, &ptr); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_kclvm_plugin_AppContextBase__add_option" "', argument " "2"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__add_option" "', argument " "2"" of type '" "std::string const &""'"); - } - arg2 = ptr; - } - { - std::string *ptr = (std::string *)0; - res3 = SWIG_AsPtr_std_string(obj2, &ptr); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_kclvm_plugin_AppContextBase__add_option" "', argument " "3"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__add_option" "', argument " "3"" of type '" "std::string const &""'"); - } - arg3 = ptr; - } - (arg1)->_add_option((std::string const &)*arg2,(std::string const &)*arg3); - resultobj = SWIG_Py_Void(); - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - return resultobj; -fail: - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__run_app(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - uint64_t arg2 ; - uint64_t arg3 ; - int32_t arg4 ; - int32_t arg5 ; - int32_t arg6 ; - int32_t arg7 ; - int32_t arg8 ; - int32_t arg9 ; - void *argp1 = 0 ; - int res1 = 0 ; - unsigned long long val2 ; - int ecode2 = 0 ; - unsigned long long val3 ; - int ecode3 = 0 ; - int val4 ; - int ecode4 = 0 ; - int val5 ; - int ecode5 = 0 ; - int val6 ; - int ecode6 = 0 ; - int val7 ; - int ecode7 = 0 ; - int val8 ; - int ecode8 = 0 ; - int val9 ; - int ecode9 = 0 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - PyObject * obj4 = 0 ; - PyObject * obj5 = 0 ; - PyObject * obj6 = 0 ; - PyObject * obj7 = 0 ; - PyObject * obj8 = 0 ; - std::string result; - - if (!PyArg_ParseTuple(args,(char *)"OOOOOOOOO:_kclvm_plugin_AppContextBase__run_app",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5,&obj6,&obj7,&obj8)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - ecode2 = SWIG_AsVal_unsigned_SS_long_SS_long(obj1, &val2); - if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "2"" of type '" "uint64_t""'"); - } - arg2 = static_cast< uint64_t >(val2); - ecode3 = SWIG_AsVal_unsigned_SS_long_SS_long(obj2, &val3); - if (!SWIG_IsOK(ecode3)) { - SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "3"" of type '" "uint64_t""'"); - } - arg3 = static_cast< uint64_t >(val3); - ecode4 = SWIG_AsVal_int(obj3, &val4); - if (!SWIG_IsOK(ecode4)) { - SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "4"" of type '" "int32_t""'"); - } - arg4 = static_cast< int32_t >(val4); - ecode5 = SWIG_AsVal_int(obj4, &val5); - if (!SWIG_IsOK(ecode5)) { - SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "5"" of type '" "int32_t""'"); - } - arg5 = static_cast< int32_t >(val5); - ecode6 = SWIG_AsVal_int(obj5, &val6); - if (!SWIG_IsOK(ecode6)) { - SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "6"" of type '" "int32_t""'"); - } - arg6 = static_cast< int32_t >(val6); - ecode7 = SWIG_AsVal_int(obj6, &val7); - if (!SWIG_IsOK(ecode7)) { - SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "7"" of type '" "int32_t""'"); - } - arg7 = static_cast< int32_t >(val7); - ecode8 = SWIG_AsVal_int(obj7, &val8); - if (!SWIG_IsOK(ecode8)) { - SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "8"" of type '" "int32_t""'"); - } - arg8 = static_cast< int32_t >(val8); - ecode9 = SWIG_AsVal_int(obj8, &val9); - if (!SWIG_IsOK(ecode9)) { - SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "_kclvm_plugin_AppContextBase__run_app" "', argument " "9"" of type '" "int32_t""'"); - } - arg9 = static_cast< int32_t >(val9); - result = (arg1)->_run_app(arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); - resultobj = SWIG_From_std_string(static_cast< std::string >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__get_warn(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - std::string result; - - if (!PyArg_ParseTuple(args,(char *)"O:_kclvm_plugin_AppContextBase__get_warn",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__get_warn" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - result = (arg1)->_get_warn(); - resultobj = SWIG_From_std_string(static_cast< std::string >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - uint64_t result; - - if (!PyArg_ParseTuple(args,(char *)"O:_kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - result = (uint64_t)(arg1)->_get_cxx_invoke_proxy_ptr(); - resultobj = SWIG_From_unsigned_SS_long_SS_long(static_cast< unsigned long long >(result)); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__call_rust_method(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - std::string *arg2 = 0 ; - std::string *arg3 = 0 ; - std::string *arg4 = 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 = SWIG_OLDOBJ ; - int res3 = SWIG_OLDOBJ ; - int res4 = SWIG_OLDOBJ ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - std::string result; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:_kclvm_plugin_AppContextBase__call_rust_method",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - { - std::string *ptr = (std::string *)0; - res2 = SWIG_AsPtr_std_string(obj1, &ptr); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "2"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "2"" of type '" "std::string const &""'"); - } - arg2 = ptr; - } - { - std::string *ptr = (std::string *)0; - res3 = SWIG_AsPtr_std_string(obj2, &ptr); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "3"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "3"" of type '" "std::string const &""'"); - } - arg3 = ptr; - } - { - std::string *ptr = (std::string *)0; - res4 = SWIG_AsPtr_std_string(obj3, &ptr); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "4"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_rust_method" "', argument " "4"" of type '" "std::string const &""'"); - } - arg4 = ptr; - } - result = (arg1)->_call_rust_method((std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4); - resultobj = SWIG_From_std_string(static_cast< std::string >(result)); - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - if (SWIG_IsNewObj(res4)) delete arg4; - return resultobj; -fail: - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - if (SWIG_IsNewObj(res4)) delete arg4; - return NULL; -} - - -SWIGINTERN PyObject *_wrap__kclvm_plugin_AppContextBase__call_py_method(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - std::string *arg2 = 0 ; - std::string *arg3 = 0 ; - std::string *arg4 = 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - int res2 = SWIG_OLDOBJ ; - int res3 = SWIG_OLDOBJ ; - int res4 = SWIG_OLDOBJ ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - PyObject * obj3 = 0 ; - Swig::Director *director = 0; - bool upcall = false; - std::string result; - - if (!PyArg_ParseTuple(args,(char *)"OOOO:_kclvm_plugin_AppContextBase__call_py_method",&obj0,&obj1,&obj2,&obj3)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - { - std::string *ptr = (std::string *)0; - res2 = SWIG_AsPtr_std_string(obj1, &ptr); - if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "2"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "2"" of type '" "std::string const &""'"); - } - arg2 = ptr; - } - { - std::string *ptr = (std::string *)0; - res3 = SWIG_AsPtr_std_string(obj2, &ptr); - if (!SWIG_IsOK(res3)) { - SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "3"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "3"" of type '" "std::string const &""'"); - } - arg3 = ptr; - } - { - std::string *ptr = (std::string *)0; - res4 = SWIG_AsPtr_std_string(obj3, &ptr); - if (!SWIG_IsOK(res4)) { - SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "4"" of type '" "std::string const &""'"); - } - if (!ptr) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "_kclvm_plugin_AppContextBase__call_py_method" "', argument " "4"" of type '" "std::string const &""'"); - } - arg4 = ptr; - } - director = SWIG_DIRECTOR_CAST(arg1); - upcall = (director && (director->swig_get_self()==obj0)); - try { - if (upcall) { - result = (arg1)->_kclvm_plugin_AppContextBase::_call_py_method((std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4); - } else { - result = (arg1)->_call_py_method((std::string const &)*arg2,(std::string const &)*arg3,(std::string const &)*arg4); - } - } catch (Swig::DirectorException&) { - SWIG_fail; - } - resultobj = SWIG_From_std_string(static_cast< std::string >(result)); - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - if (SWIG_IsNewObj(res4)) delete arg4; - return resultobj; -fail: - if (SWIG_IsNewObj(res2)) delete arg2; - if (SWIG_IsNewObj(res3)) delete arg3; - if (SWIG_IsNewObj(res4)) delete arg4; - return NULL; -} - - -SWIGINTERN PyObject *_wrap_disown__kclvm_plugin_AppContextBase(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *resultobj = 0; - _kclvm_plugin_AppContextBase *arg1 = (_kclvm_plugin_AppContextBase *) 0 ; - void *argp1 = 0 ; - int res1 = 0 ; - PyObject * obj0 = 0 ; - - if (!PyArg_ParseTuple(args,(char *)"O:disown__kclvm_plugin_AppContextBase",&obj0)) SWIG_fail; - res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p__kclvm_plugin_AppContextBase, 0 | 0 ); - if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "disown__kclvm_plugin_AppContextBase" "', argument " "1"" of type '" "_kclvm_plugin_AppContextBase *""'"); - } - arg1 = reinterpret_cast< _kclvm_plugin_AppContextBase * >(argp1); - { - Swig::Director *director = SWIG_DIRECTOR_CAST(arg1); - if (director) director->swig_disown(); - } - - resultobj = SWIG_Py_Void(); - return resultobj; -fail: - return NULL; -} - - -SWIGINTERN PyObject *_kclvm_plugin_AppContextBase_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { - PyObject *obj; - if (!PyArg_ParseTuple(args,(char *)"O:swigregister", &obj)) return NULL; - SWIG_TypeNewClientData(SWIGTYPE_p__kclvm_plugin_AppContextBase, SWIG_NewClientData(obj)); - return SWIG_Py_Void(); -} - -static PyMethodDef SwigMethods[] = { - { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL}, - { (char *)"new__kclvm_plugin_AppContextBase", _wrap_new__kclvm_plugin_AppContextBase, METH_VARARGS, NULL}, - { (char *)"delete__kclvm_plugin_AppContextBase", _wrap_delete__kclvm_plugin_AppContextBase, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__clear_options", _wrap__kclvm_plugin_AppContextBase__clear_options, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__add_option", _wrap__kclvm_plugin_AppContextBase__add_option, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__run_app", _wrap__kclvm_plugin_AppContextBase__run_app, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__get_warn", _wrap__kclvm_plugin_AppContextBase__get_warn, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr", _wrap__kclvm_plugin_AppContextBase__get_cxx_invoke_proxy_ptr, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__call_rust_method", _wrap__kclvm_plugin_AppContextBase__call_rust_method, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase__call_py_method", _wrap__kclvm_plugin_AppContextBase__call_py_method, METH_VARARGS, NULL}, - { (char *)"disown__kclvm_plugin_AppContextBase", _wrap_disown__kclvm_plugin_AppContextBase, METH_VARARGS, NULL}, - { (char *)"_kclvm_plugin_AppContextBase_swigregister", _kclvm_plugin_AppContextBase_swigregister, METH_VARARGS, NULL}, - { NULL, NULL, 0, NULL } -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ - -static swig_type_info _swigt__p__kclvm_plugin_AppContextBase = {"_p__kclvm_plugin_AppContextBase", "_kclvm_plugin_AppContextBase *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_short = {"_p_short", "short *|int_least16_t *|int16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_signed_char = {"_p_signed_char", "signed char *|int_least8_t *|int_fast8_t *|int8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_char = {"_p_unsigned_char", "unsigned char *|uint_least8_t *|uint_fast8_t *|uint8_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_int = {"_p_unsigned_int", "uintptr_t *|uint_least32_t *|uint_fast32_t *|uint32_t *|unsigned int *|uint_fast16_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_long_long = {"_p_unsigned_long_long", "uint_least64_t *|uint_fast64_t *|uint64_t *|unsigned long long *|uintmax_t *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned short *|uint_least16_t *|uint16_t *", 0, 0, (void*)0, 0}; - -static swig_type_info *swig_type_initial[] = { - &_swigt__p__kclvm_plugin_AppContextBase, - &_swigt__p_char, - &_swigt__p_int, - &_swigt__p_long_long, - &_swigt__p_short, - &_swigt__p_signed_char, - &_swigt__p_unsigned_char, - &_swigt__p_unsigned_int, - &_swigt__p_unsigned_long_long, - &_swigt__p_unsigned_short, -}; - -static swig_cast_info _swigc__p__kclvm_plugin_AppContextBase[] = { {&_swigt__p__kclvm_plugin_AppContextBase, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_short[] = { {&_swigt__p_short, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_signed_char[] = { {&_swigt__p_signed_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_char[] = { {&_swigt__p_unsigned_char, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_int[] = { {&_swigt__p_unsigned_int, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_long_long[] = { {&_swigt__p_unsigned_long_long, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short, 0, 0, 0},{0, 0, 0, 0}}; - -static swig_cast_info *swig_cast_initial[] = { - _swigc__p__kclvm_plugin_AppContextBase, - _swigc__p_char, - _swigc__p_int, - _swigc__p_long_long, - _swigc__p_short, - _swigc__p_signed_char, - _swigc__p_unsigned_char, - _swigc__p_unsigned_int, - _swigc__p_unsigned_long_long, - _swigc__p_unsigned_short, -}; - - -/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ - -static swig_const_info swig_const_table[] = { -{0, 0, 0, 0.0, 0, 0}}; - -#ifdef __cplusplus -} -#endif -/* ----------------------------------------------------------------------------- - * Type initialization: - * This problem is tough by the requirement that no dynamic - * memory is used. Also, since swig_type_info structures store pointers to - * swig_cast_info structures and swig_cast_info structures store pointers back - * to swig_type_info structures, we need some lookup code at initialization. - * The idea is that swig generates all the structures that are needed. - * The runtime then collects these partially filled structures. - * The SWIG_InitializeModule function takes these initial arrays out of - * swig_module, and does all the lookup, filling in the swig_module.types - * array with the correct data and linking the correct swig_cast_info - * structures together. - * - * The generated swig_type_info structures are assigned statically to an initial - * array. We just loop through that array, and handle each type individually. - * First we lookup if this type has been already loaded, and if so, use the - * loaded structure instead of the generated one. Then we have to fill in the - * cast linked list. The cast data is initially stored in something like a - * two-dimensional array. Each row corresponds to a type (there are the same - * number of rows as there are in the swig_type_initial array). Each entry in - * a column is one of the swig_cast_info structures for that type. - * The cast_initial array is actually an array of arrays, because each row has - * a variable number of columns. So to actually build the cast linked list, - * we find the array of casts associated with the type, and loop through it - * adding the casts to the list. The one last trick we need to do is making - * sure the type pointer in the swig_cast_info struct is correct. - * - * First off, we lookup the cast->type name to see if it is already loaded. - * There are three cases to handle: - * 1) If the cast->type has already been loaded AND the type we are adding - * casting info to has not been loaded (it is in this module), THEN we - * replace the cast->type pointer with the type pointer that has already - * been loaded. - * 2) If BOTH types (the one we are adding casting info to, and the - * cast->type) are loaded, THEN the cast info has already been loaded by - * the previous module so we just ignore it. - * 3) Finally, if cast->type has not already been loaded, then we add that - * swig_cast_info to the linked list (because the cast->type) pointer will - * be correct. - * ----------------------------------------------------------------------------- */ - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* c-mode */ -#endif -#endif - -#if 0 -#define SWIGRUNTIME_DEBUG -#endif - - -SWIGRUNTIME void -SWIG_InitializeModule(void *clientdata) { - size_t i; - swig_module_info *module_head, *iter; - int init; - - /* check to see if the circular list has been setup, if not, set it up */ - if (swig_module.next==0) { - /* Initialize the swig_module */ - swig_module.type_initial = swig_type_initial; - swig_module.cast_initial = swig_cast_initial; - swig_module.next = &swig_module; - init = 1; - } else { - init = 0; - } - - /* Try and load any already created modules */ - module_head = SWIG_GetModule(clientdata); - if (!module_head) { - /* This is the first module loaded for this interpreter */ - /* so set the swig module into the interpreter */ - SWIG_SetModule(clientdata, &swig_module); - } else { - /* the interpreter has loaded a SWIG module, but has it loaded this one? */ - iter=module_head; - do { - if (iter==&swig_module) { - /* Our module is already in the list, so there's nothing more to do. */ - return; - } - iter=iter->next; - } while (iter!= module_head); - - /* otherwise we must add our module into the list */ - swig_module.next = module_head->next; - module_head->next = &swig_module; - } - - /* When multiple interpreters are used, a module could have already been initialized in - a different interpreter, but not yet have a pointer in this interpreter. - In this case, we do not want to continue adding types... everything should be - set up already */ - if (init == 0) return; - - /* Now work on filling in swig_module.types */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: size %d\n", swig_module.size); -#endif - for (i = 0; i < swig_module.size; ++i) { - swig_type_info *type = 0; - swig_type_info *ret; - swig_cast_info *cast; - -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); -#endif - - /* if there is another module already loaded */ - if (swig_module.next != &swig_module) { - type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); - } - if (type) { - /* Overwrite clientdata field */ -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found type %s\n", type->name); -#endif - if (swig_module.type_initial[i]->clientdata) { - type->clientdata = swig_module.type_initial[i]->clientdata; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); -#endif - } - } else { - type = swig_module.type_initial[i]; - } - - /* Insert casting types */ - cast = swig_module.cast_initial[i]; - while (cast->type) { - /* Don't need to add information already in the list */ - ret = 0; -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); -#endif - if (swig_module.next != &swig_module) { - ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); -#ifdef SWIGRUNTIME_DEBUG - if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); -#endif - } - if (ret) { - if (type == swig_module.type_initial[i]) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: skip old type %s\n", ret->name); -#endif - cast->type = ret; - ret = 0; - } else { - /* Check for casting already in the list */ - swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); -#ifdef SWIGRUNTIME_DEBUG - if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); -#endif - if (!ocast) ret = 0; - } - } - - if (!ret) { -#ifdef SWIGRUNTIME_DEBUG - printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); -#endif - if (type->cast) { - type->cast->prev = cast; - cast->next = type->cast; - } - type->cast = cast; - } - cast++; - } - /* Set entry in modules->types array equal to the type */ - swig_module.types[i] = type; - } - swig_module.types[i] = 0; - -#ifdef SWIGRUNTIME_DEBUG - printf("**** SWIG_InitializeModule: Cast List ******\n"); - for (i = 0; i < swig_module.size; ++i) { - int j = 0; - swig_cast_info *cast = swig_module.cast_initial[i]; - printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name); - while (cast->type) { - printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); - cast++; - ++j; - } - printf("---- Total casts: %d\n",j); - } - printf("**** SWIG_InitializeModule: Cast List ******\n"); -#endif -} - -/* This function will propagate the clientdata field of type to -* any new swig_type_info structures that have been added into the list -* of equivalent types. It is like calling -* SWIG_TypeClientData(type, clientdata) a second time. -*/ -SWIGRUNTIME void -SWIG_PropagateClientData(void) { - size_t i; - swig_cast_info *equiv; - static int init_run = 0; - - if (init_run) return; - init_run = 1; - - for (i = 0; i < swig_module.size; i++) { - if (swig_module.types[i]->clientdata) { - equiv = swig_module.types[i]->cast; - while (equiv) { - if (!equiv->converter) { - if (equiv->type && !equiv->type->clientdata) - SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); - } - equiv = equiv->next; - } - } - } -} - -#ifdef __cplusplus -#if 0 -{ - /* c-mode */ -#endif -} -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - /* Python-specific SWIG API */ -#define SWIG_newvarlink() SWIG_Python_newvarlink() -#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) -#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) - - /* ----------------------------------------------------------------------------- - * global variable support code. - * ----------------------------------------------------------------------------- */ - - typedef struct swig_globalvar { - char *name; /* Name of global variable */ - PyObject *(*get_attr)(void); /* Return the current value */ - int (*set_attr)(PyObject *); /* Set the value */ - struct swig_globalvar *next; - } swig_globalvar; - - typedef struct swig_varlinkobject { - PyObject_HEAD - swig_globalvar *vars; - } swig_varlinkobject; - - SWIGINTERN PyObject * - swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { -#if PY_VERSION_HEX >= 0x03000000 - return PyUnicode_InternFromString(""); -#else - return PyString_FromString(""); -#endif - } - - SWIGINTERN PyObject * - swig_varlink_str(swig_varlinkobject *v) { -#if PY_VERSION_HEX >= 0x03000000 - PyObject *str = PyUnicode_InternFromString("("); - PyObject *tail; - PyObject *joined; - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - tail = PyUnicode_FromString(var->name); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - if (var->next) { - tail = PyUnicode_InternFromString(", "); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; - } - } - tail = PyUnicode_InternFromString(")"); - joined = PyUnicode_Concat(str, tail); - Py_DecRef(str); - Py_DecRef(tail); - str = joined; -#else - PyObject *str = PyString_FromString("("); - swig_globalvar *var; - for (var = v->vars; var; var=var->next) { - PyString_ConcatAndDel(&str,PyString_FromString(var->name)); - if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); - } - PyString_ConcatAndDel(&str,PyString_FromString(")")); -#endif - return str; - } - - SWIGINTERN int - swig_varlink_print(swig_varlinkobject *v, FILE *fp, int SWIGUNUSEDPARM(flags)) { - char *tmp; - PyObject *str = swig_varlink_str(v); - fprintf(fp,"Swig global variables "); - fprintf(fp,"%s\n", tmp = SWIG_Python_str_AsChar(str)); - SWIG_Python_str_DelForPy3(tmp); - Py_DECREF(str); - return 0; - } - - SWIGINTERN void - swig_varlink_dealloc(swig_varlinkobject *v) { - swig_globalvar *var = v->vars; - while (var) { - swig_globalvar *n = var->next; - free(var->name); - free(var); - var = n; - } - } - - SWIGINTERN PyObject * - swig_varlink_getattr(swig_varlinkobject *v, char *n) { - PyObject *res = NULL; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->get_attr)(); - break; - } - var = var->next; - } - if (res == NULL && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN int - swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { - int res = 1; - swig_globalvar *var = v->vars; - while (var) { - if (strcmp(var->name,n) == 0) { - res = (*var->set_attr)(p); - break; - } - var = var->next; - } - if (res == 1 && !PyErr_Occurred()) { - PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); - } - return res; - } - - SWIGINTERN PyTypeObject* - swig_varlink_type(void) { - static char varlink__doc__[] = "Swig var link object"; - static PyTypeObject varlink_type; - static int type_init = 0; - if (!type_init) { - const PyTypeObject tmp = { -#if PY_VERSION_HEX >= 0x03000000 - PyVarObject_HEAD_INIT(NULL, 0) -#else - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ -#endif - (char *)"swigvarlink", /* tp_name */ - sizeof(swig_varlinkobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) swig_varlink_dealloc, /* tp_dealloc */ - (printfunc) swig_varlink_print, /* tp_print */ - (getattrfunc) swig_varlink_getattr, /* tp_getattr */ - (setattrfunc) swig_varlink_setattr, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) swig_varlink_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - (reprfunc) swig_varlink_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - varlink__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ -#if PY_VERSION_HEX >= 0x02020000 - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ -#endif -#if PY_VERSION_HEX >= 0x02030000 - 0, /* tp_del */ -#endif -#if PY_VERSION_HEX >= 0x02060000 - 0, /* tp_version_tag */ -#endif -#if PY_VERSION_HEX >= 0x03040000 - 0, /* tp_finalize */ -#endif -#ifdef COUNT_ALLOCS - 0, /* tp_allocs */ - 0, /* tp_frees */ - 0, /* tp_maxalloc */ -#if PY_VERSION_HEX >= 0x02050000 - 0, /* tp_prev */ -#endif - 0 /* tp_next */ -#endif - }; - varlink_type = tmp; - type_init = 1; -#if PY_VERSION_HEX < 0x02020000 - varlink_type.ob_type = &PyType_Type; -#else - if (PyType_Ready(&varlink_type) < 0) - return NULL; -#endif - } - return &varlink_type; - } - - /* Create a variable linking object for use later */ - SWIGINTERN PyObject * - SWIG_Python_newvarlink(void) { - swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); - if (result) { - result->vars = 0; - } - return ((PyObject*) result); - } - - SWIGINTERN void - SWIG_Python_addvarlink(PyObject *p, char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { - swig_varlinkobject *v = (swig_varlinkobject *) p; - swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); - if (gv) { - size_t size = strlen(name)+1; - gv->name = (char *)malloc(size); - if (gv->name) { - strncpy(gv->name,name,size); - gv->get_attr = get_attr; - gv->set_attr = set_attr; - gv->next = v->vars; - } - } - v->vars = gv; - } - - SWIGINTERN PyObject * - SWIG_globals(void) { - static PyObject *_SWIG_globals = 0; - if (!_SWIG_globals) _SWIG_globals = SWIG_newvarlink(); - return _SWIG_globals; - } - - /* ----------------------------------------------------------------------------- - * constants/methods manipulation - * ----------------------------------------------------------------------------- */ - - /* Install Constants */ - SWIGINTERN void - SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { - PyObject *obj = 0; - size_t i; - for (i = 0; constants[i].type; ++i) { - switch(constants[i].type) { - case SWIG_PY_POINTER: - obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); - break; - case SWIG_PY_BINARY: - obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); - break; - default: - obj = 0; - break; - } - if (obj) { - PyDict_SetItemString(d, constants[i].name, obj); - Py_DECREF(obj); - } - } - } - - /* -----------------------------------------------------------------------------*/ - /* Fix SwigMethods to carry the callback ptrs when needed */ - /* -----------------------------------------------------------------------------*/ - - SWIGINTERN void - SWIG_Python_FixMethods(PyMethodDef *methods, - swig_const_info *const_table, - swig_type_info **types, - swig_type_info **types_initial) { - size_t i; - for (i = 0; methods[i].ml_name; ++i) { - const char *c = methods[i].ml_doc; - if (!c) continue; - c = strstr(c, "swig_ptr: "); - if (c) { - int j; - swig_const_info *ci = 0; - const char *name = c + 10; - for (j = 0; const_table[j].type; ++j) { - if (strncmp(const_table[j].name, name, - strlen(const_table[j].name)) == 0) { - ci = &(const_table[j]); - break; - } - } - if (ci) { - void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; - if (ptr) { - size_t shift = (ci->ptype) - types; - swig_type_info *ty = types_initial[shift]; - size_t ldoc = (c - methods[i].ml_doc); - size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; - char *ndoc = (char*)malloc(ldoc + lptr + 10); - if (ndoc) { - char *buff = ndoc; - strncpy(buff, methods[i].ml_doc, ldoc); - buff += ldoc; - strncpy(buff, "swig_ptr: ", 10); - buff += 10; - SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); - methods[i].ml_doc = ndoc; - } - } - } - } - } - } - -#ifdef __cplusplus -} -#endif - -/* -----------------------------------------------------------------------------* - * Partial Init method - * -----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" -#endif - -SWIGEXPORT -#if PY_VERSION_HEX >= 0x03000000 -PyObject* -#else -void -#endif -SWIG_init(void) { - PyObject *m, *d, *md; -#if PY_VERSION_HEX >= 0x03000000 - static struct PyModuleDef SWIG_module = { -# if PY_VERSION_HEX >= 0x03020000 - PyModuleDef_HEAD_INIT, -# else - { - PyObject_HEAD_INIT(NULL) - NULL, /* m_init */ - 0, /* m_index */ - NULL, /* m_copy */ - }, -# endif - (char *) SWIG_name, - NULL, - -1, - SwigMethods, - NULL, - NULL, - NULL, - NULL - }; -#endif - -#if defined(SWIGPYTHON_BUILTIN) - static SwigPyClientData SwigPyObject_clientdata = { - 0, 0, 0, 0, 0, 0, 0 - }; - static PyGetSetDef this_getset_def = { - (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL - }; - static SwigPyGetSet thisown_getset_closure = { - (PyCFunction) SwigPyObject_own, - (PyCFunction) SwigPyObject_own - }; - static PyGetSetDef thisown_getset_def = { - (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure - }; - PyTypeObject *builtin_pytype; - int builtin_base_count; - swig_type_info *builtin_basetype; - PyObject *tuple; - PyGetSetDescrObject *static_getset; - PyTypeObject *metatype; - PyTypeObject *swigpyobject; - SwigPyClientData *cd; - PyObject *public_interface, *public_symbol; - PyObject *this_descr; - PyObject *thisown_descr; - PyObject *self = 0; - int i; - - (void)builtin_pytype; - (void)builtin_base_count; - (void)builtin_basetype; - (void)tuple; - (void)static_getset; - (void)self; - - /* Metaclass is used to implement static member variables */ - metatype = SwigPyObjectType(); - assert(metatype); -#endif - - /* Fix SwigMethods to carry the callback ptrs when needed */ - SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); - -#if PY_VERSION_HEX >= 0x03000000 - m = PyModule_Create(&SWIG_module); -#else - m = Py_InitModule((char *) SWIG_name, SwigMethods); -#endif - - md = d = PyModule_GetDict(m); - (void)md; - - SWIG_InitializeModule(0); - -#ifdef SWIGPYTHON_BUILTIN - swigpyobject = SwigPyObject_TypeOnce(); - - SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); - assert(SwigPyObject_stype); - cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; - if (!cd) { - SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; - SwigPyObject_clientdata.pytype = swigpyobject; - } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { - PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); -# if PY_VERSION_HEX >= 0x03000000 - return NULL; -# else - return; -# endif - } - - /* All objects have a 'this' attribute */ - this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); - (void)this_descr; - - /* All objects have a 'thisown' attribute */ - thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); - (void)thisown_descr; - - public_interface = PyList_New(0); - public_symbol = 0; - (void)public_symbol; - - PyDict_SetItemString(md, "__all__", public_interface); - Py_DECREF(public_interface); - for (i = 0; SwigMethods[i].ml_name != NULL; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); - for (i = 0; swig_const_table[i].name != 0; ++i) - SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); -#endif - - SWIG_InstallConstants(d,swig_const_table); - -#if PY_VERSION_HEX >= 0x03000000 - return m; -#else - return; -#endif -} - diff --git a/kclvm/plugin/kclvm_plugin_wrap.h b/kclvm/plugin/kclvm_plugin_wrap.h deleted file mode 100644 index 0548c7e4c..000000000 --- a/kclvm/plugin/kclvm_plugin_wrap.h +++ /dev/null @@ -1,60 +0,0 @@ -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 3.0.12 - * - * This file is not intended to be easily readable and contains a number of - * coding conventions designed to improve portability and efficiency. Do not make - * changes to this file unless you know what you are doing--modify the SWIG - * interface file instead. - * ----------------------------------------------------------------------------- */ - -#ifndef SWIG_kclvm_plugin_WRAP_H_ -#define SWIG_kclvm_plugin_WRAP_H_ - -#include -#include - - -class SwigDirector__kclvm_plugin_AppContextBase : public _kclvm_plugin_AppContextBase, public Swig::Director { - -public: - SwigDirector__kclvm_plugin_AppContextBase(PyObject *self, uint64_t rust_invoke_json_ptr); - virtual ~SwigDirector__kclvm_plugin_AppContextBase(); - virtual std::string _call_py_method(std::string const &name, std::string const &args_json, std::string const &kwargs_json); - -/* Internal director utilities */ -public: - bool swig_get_inner(const char *swig_protected_method_name) const { - std::map::const_iterator iv = swig_inner.find(swig_protected_method_name); - return (iv != swig_inner.end() ? iv->second : false); - } - void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const { - swig_inner[swig_protected_method_name] = swig_val; - } -private: - mutable std::map swig_inner; - -#if defined(SWIG_PYTHON_DIRECTOR_VTABLE) -/* VTable implementation */ - PyObject *swig_get_method(size_t method_index, const char *method_name) const { - PyObject *method = vtable[method_index]; - if (!method) { - swig::SwigVar_PyObject name = SWIG_Python_str_FromChar(method_name); - method = PyObject_GetAttr(swig_get_self(), name); - if (!method) { - std::string msg = "Method in class _kclvm_plugin_AppContextBase doesn't exist, undefined "; - msg += method_name; - Swig::DirectorMethodException::raise(msg.c_str()); - } - vtable[method_index] = method; - } - return method; - } -private: - mutable swig::SwigVar_PyObject vtable[1]; -#endif - -}; - - -#endif diff --git a/kclvm/plugin/readme.md b/kclvm/plugin/readme.md deleted file mode 100644 index 3132958d4..000000000 --- a/kclvm/plugin/readme.md +++ /dev/null @@ -1 +0,0 @@ -# KCLVM Plugin diff --git a/kclvm/plugin/setup.py b/kclvm/plugin/setup.py deleted file mode 100644 index 93daf026c..000000000 --- a/kclvm/plugin/setup.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2021 The KCL Authors. All rights reserved. - -import os -import distutils.core - -PWD = os.path.abspath(os.path.dirname(__file__)) -kclvm_ROOT = os.path.abspath(f"{PWD}/..") - -distutils.core.setup( - name="kclvm-plugin", - version="1.0", - py_modules=["kclvm_plugin", "kclvm_runtime"], - ext_modules=[ - distutils.core.Extension( - "_kclvm_plugin", - [f"{PWD}/kclvm_plugin.cpp", f"{PWD}/kclvm_plugin_wrap.cxx"], - include_dirs=[f"{kclvm_ROOT}/runtime/src"], - ) - ], -) diff --git a/kclvm/query/Cargo.toml b/kclvm/query/Cargo.toml index 51ae2af30..750139b95 100644 --- a/kclvm/query/Cargo.toml +++ b/kclvm/query/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-query" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -16,6 +16,7 @@ kclvm-ast-pretty = {path = "../ast_pretty"} kclvm-parser = {path = "../parser"} kclvm-sema = {path = "../sema"} kclvm-error = {path = "../error"} +maplit = "1.0.2" [dev-dependencies] pretty_assertions = "1.2.1" diff --git a/kclvm/query/src/lib.rs b/kclvm/query/src/lib.rs index 5d40a8657..d0384f3d1 100644 --- a/kclvm/query/src/lib.rs +++ b/kclvm/query/src/lib.rs @@ -4,7 +4,9 @@ //! input file name, and according to the ast::OverrideSpec transforms the nodes in the //! AST, recursively modifying or deleting the values of the nodes in the AST. pub mod r#override; +pub mod path; pub mod query; +pub mod selector; #[cfg(test)] mod tests; @@ -83,7 +85,7 @@ pub fn override_file(file: &str, specs: &[String], import_paths: &[String]) -> R .collect::>(); // Parse file to AST module. let mut module = match parse_file(file, None) { - Ok(module) => module, + Ok(module) => module.module, Err(msg) => return Err(anyhow!("{}", msg)), }; let mut result = false; diff --git a/kclvm/query/src/override.rs b/kclvm/query/src/override.rs index 8eed0b60d..35ce97213 100644 --- a/kclvm/query/src/override.rs +++ b/kclvm/query/src/override.rs @@ -6,11 +6,14 @@ use compiler_base_macros::bug; use kclvm_ast::config::try_get_config_expr_mut; use kclvm_ast::path::get_key_path; use kclvm_ast::walker::MutSelfMutWalker; +use kclvm_ast::MAIN_PKG; use kclvm_ast::{ast, walk_if_mut}; use kclvm_ast_pretty::print_ast_module; use kclvm_parser::parse_expr; use kclvm_sema::pre_process::{fix_config_expr_nest_attr, transform_multi_assign}; +use crate::path::parse_attribute_path; + use super::util::{invalid_spec_error, split_field_path}; /// Import statement column offset always start with 1. @@ -29,7 +32,7 @@ const IMPORT_STMT_COLUMN_OFFSET: u64 = 1; /// use kclvm_parser::load_program; /// use kclvm_tools::query::r#override::apply_overrides; /// -/// let mut prog = load_program(&["config.k"], None).unwrap(); +/// let mut prog = load_program(&["config.k"], None, None).unwrap(); /// let overrides = vec![parse_override_spec("config.id=1").unwrap()]; /// let import_paths = vec!["path.to.pkg".to_string()]; /// let result = apply_overrides(&mut prog, &overrides, &import_paths, true).unwrap(); @@ -42,7 +45,7 @@ pub fn apply_overrides( ) -> Result<()> { for o in overrides { let pkgpath = if o.pkgpath.is_empty() { - &prog.main + MAIN_PKG } else { &o.pkgpath }; @@ -89,10 +92,10 @@ fn build_expr_from_string(value: &str) -> Option> { /// # Examples /// /// ```no_check -/// use kclvm_parser::parse_file; +/// use kclvm_parser::parse_file_force_errors; /// use kclvm_tools::query::apply_override_on_module; /// -/// let mut module = parse_file("", None).unwrap(); +/// let mut module = parse_file_force_errors("", None).unwrap(); /// let override_spec = parse_override_spec("config.id=1").unwrap(); /// let import_paths = vec!["path.to.pkg".to_string()]; /// let result = apply_override_on_module(&mut module, override_spec, &import_paths).unwrap(); @@ -104,15 +107,17 @@ pub fn apply_override_on_module( ) -> Result { // Apply import paths on AST module. apply_import_paths_on_module(m, import_paths)?; - let ss = o.field_path.split('.').collect::>(); + let ss = parse_attribute_path(&o.field_path)?; if ss.len() <= 1 { return Ok(false); } - let target_id = ss[0]; - let field = ss[1..].join("."); + let target_id = &ss[0]; let value = &o.field_value; let key = ast::Identifier { - names: field.split('.').map(|s| s.to_string()).collect(), + names: ss[1..] + .iter() + .map(|s| ast::Node::dummy_node(s.to_string())) + .collect(), ctx: ast::ExprContext::Store, pkgpath: "".to_string(), }; @@ -128,7 +133,7 @@ pub fn apply_override_on_module( transform_multi_assign(m); let mut transformer = OverrideTransformer { target_id: target_id.to_string(), - field_path: field, + field_paths: ss[1..].to_vec(), override_key: key, override_value: build_expr_from_string(value), override_target_count: 0, @@ -187,9 +192,9 @@ fn apply_import_paths_on_module(m: &mut ast::Module, import_paths: &[String]) -> for stmt in &m.body { if let ast::Stmt::Import(import_stmt) = &stmt.node { if let Some(asname) = &import_stmt.asname { - exist_import_set.insert(format!("{} as {}", import_stmt.path, asname)); + exist_import_set.insert(format!("{} as {}", import_stmt.path.node, asname.node)); } else { - exist_import_set.insert(import_stmt.path.to_string()); + exist_import_set.insert(import_stmt.path.node.to_string()); } } } @@ -203,7 +208,7 @@ fn apply_import_paths_on_module(m: &mut ast::Module, import_paths: &[String]) -> .last() .ok_or_else(|| anyhow!("Invalid import path {}", path))?; let import_node = ast::ImportStmt { - path: path.to_string(), + path: ast::Node::dummy_node(path.to_string()), rawpath: "".to_string(), name: name.to_string(), asname: None, @@ -226,7 +231,7 @@ fn apply_import_paths_on_module(m: &mut ast::Module, import_paths: &[String]) -> /// OverrideTransformer is used to walk AST and transform it with the override values. struct OverrideTransformer { pub target_id: String, - pub field_path: String, + pub field_paths: Vec, pub override_key: ast::Identifier, pub override_value: Option>, pub override_target_count: usize, @@ -243,7 +248,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for OverrideTransformer { unification_stmt.target.node.names ), }; - if name != &self.target_id { + if name.node != self.target_id { return; } self.override_target_count = 1; @@ -258,7 +263,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for OverrideTransformer { if target.node.names.len() != 1 { continue; } - if target.node.names[0] != self.target_id { + if target.node.names[0].node != self.target_id { continue; } self.override_target_count += 1; @@ -320,7 +325,11 @@ impl OverrideTransformer { /// return whether is found a replaced one. fn lookup_config_and_replace(&self, config_expr: &mut ast::ConfigExpr) -> bool { // Split a path into multiple parts. `a.b.c` -> ["a", "b", "c"] - let parts = self.field_path.split('.').collect::>(); + let parts = self + .field_paths + .iter() + .map(|s| s.as_str()) + .collect::>(); self.replace_config_with_path_parts(config_expr, &parts) } @@ -397,7 +406,10 @@ impl OverrideTransformer { } else if let ast::OverrideAction::CreateOrUpdate = self.action { if !changed { let key = ast::Identifier { - names: parts.iter().map(|s| s.to_string()).collect(), + names: parts + .iter() + .map(|s| ast::Node::dummy_node(s.to_string())) + .collect(), ctx: ast::ExprContext::Store, pkgpath: "".to_string(), }; diff --git a/kclvm/query/src/path.rs b/kclvm/query/src/path.rs new file mode 100644 index 000000000..c75cf427e --- /dev/null +++ b/kclvm/query/src/path.rs @@ -0,0 +1,60 @@ +use anyhow::Result; + +/// Parse attribute path which returns either a vector of strings or an error. e.g. +/// `a.b.c`, `a['b'].c`, `a["b"].c`, `a.['b'].c` and `a.["b"].c` both return `["a", "b", "c"]` +pub fn parse_attribute_path(path: &str) -> Result> { + let mut parts: Vec = Vec::new(); + let mut current = String::new(); + let mut chars = path.chars().peekable(); + let mut in_brackets = false; + + while let Some(ch) = chars.next() { + if in_brackets { + if ch == '"' || ch == '\'' { + // Expecting the closing quote, skip if found + if chars.peek() == Some(&']') { + chars.next(); // Consume the closing bracket + in_brackets = false; + continue; + } + return Err(anyhow::anyhow!("Expected closing bracket")); + } else { + current.push(ch); + } + } else { + match ch { + '.' => { + if !current.is_empty() { + parts.push(current.clone()); + current.clear(); + } + } + '[' => { + if !current.is_empty() { + parts.push(current.clone()); + current.clear(); + } + in_brackets = true; + // Skip the opening quote + if let Some(next_char) = chars.next() { + if next_char != '"' && next_char != '\'' { + return Err(anyhow::anyhow!("Expected opening quote after '['")); + } + } + } + ']' => { + return Err(anyhow::anyhow!("Unmatched closing bracket")); + } + _ => { + current.push(ch); + } + } + } + } + + if !current.is_empty() { + parts.push(current); + } + + Ok(parts) +} diff --git a/kclvm/query/src/query.rs b/kclvm/query/src/query.rs index a931c4074..c23983431 100644 --- a/kclvm/query/src/query.rs +++ b/kclvm/query/src/query.rs @@ -4,7 +4,7 @@ use anyhow::Result; use indexmap::IndexMap; use kclvm_parser::{load_program, LoadProgramOptions, ParseSession}; use kclvm_sema::{ - resolver::{resolve_program, scope::Scope}, + resolver::{resolve_program_with_opts, scope::Scope, Options}, ty::SchemaType, }; @@ -81,7 +81,18 @@ pub fn get_schema_type( opt: GetSchemaOption, ) -> Result> { let mut result = IndexMap::new(); - let scope = resolve_file(file, code)?; + let scope = resolve_file(&CompilationOptions { + k_files: vec![file.to_string()], + loader_opts: code.map(|c| LoadProgramOptions { + k_code_list: vec![c.to_string()], + ..Default::default() + }), + resolve_opts: Options { + resolve_val: true, + ..Default::default() + }, + get_schema_opts: opt.clone(), + })?; for (name, o) in &scope.borrow().elems { if o.borrow().ty.is_schema() { let schema_ty = o.borrow().ty.into_schema_type(); @@ -106,22 +117,89 @@ pub fn get_schema_type( Ok(result) } -fn resolve_file(file: &str, code: Option<&str>) -> Result>> { +#[derive(Debug, Clone, Default)] +pub struct CompilationOptions { + pub k_files: Vec, + pub loader_opts: Option, + pub resolve_opts: Options, + pub get_schema_opts: GetSchemaOption, +} + +/// Service for getting the full schema type list. +/// +/// # Examples +/// +/// ``` +/// use kclvm_parser::LoadProgramOptions; +/// use kclvm_query::query::CompilationOptions; +/// use kclvm_query::query::get_full_schema_type; +/// use std::path::Path; +/// use maplit::hashmap; +/// +/// let work_dir_parent = Path::new(".").join("src").join("test_data").join("get_schema_ty"); +/// +/// let result = get_full_schema_type( +/// Some("a"), +/// CompilationOptions { +/// k_files: vec![ +/// work_dir_parent.join("aaa").join("main.k").canonicalize().unwrap().display().to_string() +/// ], +/// loader_opts: Some(LoadProgramOptions { +/// work_dir: work_dir_parent.join("aaa").canonicalize().unwrap().display().to_string(), +/// package_maps: hashmap!{ +/// "bbb".to_string() => work_dir_parent.join("bbb").canonicalize().unwrap().display().to_string(), +/// }, +/// ..Default::default() +/// }), +/// ..Default::default() +/// } +/// ).unwrap(); +/// assert_eq!(result.len(), 1); +/// ``` +pub fn get_full_schema_type( + schema_name: Option<&str>, + opts: CompilationOptions, +) -> Result> { + let mut result = IndexMap::new(); + let scope = resolve_file(&opts)?; + for (name, o) in &scope.borrow().elems { + if o.borrow().ty.is_schema() { + let schema_ty = o.borrow().ty.into_schema_type(); + if opts.get_schema_opts == GetSchemaOption::All + || (opts.get_schema_opts == GetSchemaOption::Definitions && !schema_ty.is_instance) + || (opts.get_schema_opts == GetSchemaOption::Instances && schema_ty.is_instance) + { + // Schema name filter + match schema_name { + Some(schema_name) => { + if schema_name.is_empty() || schema_name == name { + result.insert(name.to_string(), schema_ty); + } + } + None => { + result.insert(name.to_string(), schema_ty); + } + } + } + } + } + Ok(result) +} + +fn resolve_file(opts: &CompilationOptions) -> Result>> { let sess = Arc::new(ParseSession::default()); let mut program = match load_program( sess, - &[file], - code.map(|c| LoadProgramOptions { - k_code_list: vec![c.to_string()], - ..Default::default() - }), + &opts.k_files.iter().map(AsRef::as_ref).collect::>(), + opts.loader_opts.clone(), + None, ) { - Ok(p) => p, + Ok(p) => p.program, Err(err) => { return Err(anyhow::anyhow!("{err}")); } }; - let scope = resolve_program(&mut program); + let scope = resolve_program_with_opts(&mut program, opts.resolve_opts.clone(), None); match scope.main_scope() { Some(scope) => Ok(scope.clone()), None => Err(anyhow::anyhow!("main scope is not found")), diff --git a/kclvm/query/src/selector.rs b/kclvm/query/src/selector.rs new file mode 100644 index 000000000..1d8d21497 --- /dev/null +++ b/kclvm/query/src/selector.rs @@ -0,0 +1,37 @@ +use super::util::{invalid_symbol_selector_spec_error, split_field_path}; +use anyhow::Result; +use kclvm_ast::ast; + +/// Parse symbol selector string to symbol selector spec +/// +/// # Examples +/// +/// ``` +/// use kclvm_query::selector::parse_symbol_selector_spec; +/// +/// if let Ok(spec) = parse_symbol_selector_spec("", "alice.age") { +/// assert_eq!(spec.pkgpath, "".to_string()); +/// assert_eq!(spec.field_path, "alice.age".to_string()); +/// } +/// ``` +pub fn parse_symbol_selector_spec( + pkg_root: &str, + symbol_path: &str, +) -> Result { + if let Ok((pkgpath, field_path)) = split_field_path(symbol_path) { + Ok(ast::SymbolSelectorSpec { + pkg_root: pkg_root.to_string(), + pkgpath, + field_path, + }) + } else { + Err(invalid_symbol_selector_spec_error(symbol_path)) + } +} + +#[test] +fn test_symbol_path_selector() { + let spec = parse_symbol_selector_spec("", "pkg_name:alice.age").unwrap(); + assert_eq!(spec.pkgpath, "pkg_name".to_string()); + assert_eq!(spec.field_path, "alice.age".to_string()); +} diff --git a/kclvm/query/src/test_data/get_schema_ty/aaa/kcl.mod b/kclvm/query/src/test_data/get_schema_ty/aaa/kcl.mod new file mode 100644 index 000000000..1e29d9eb2 --- /dev/null +++ b/kclvm/query/src/test_data/get_schema_ty/aaa/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "aaa" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/query/src/test_data/get_schema_ty/aaa/main.k b/kclvm/query/src/test_data/get_schema_ty/aaa/main.k new file mode 100644 index 000000000..e2c858985 --- /dev/null +++ b/kclvm/query/src/test_data/get_schema_ty/aaa/main.k @@ -0,0 +1,5 @@ +import bbb as b + +a = b.B { + name: "b instance in a" +} \ No newline at end of file diff --git a/kclvm/query/src/test_data/get_schema_ty/bbb/kcl.mod b/kclvm/query/src/test_data/get_schema_ty/bbb/kcl.mod new file mode 100644 index 000000000..e9ea10a52 --- /dev/null +++ b/kclvm/query/src/test_data/get_schema_ty/bbb/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "bbb" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/query/src/test_data/get_schema_ty/bbb/main.k b/kclvm/query/src/test_data/get_schema_ty/bbb/main.k new file mode 100644 index 000000000..21dad4f9e --- /dev/null +++ b/kclvm/query/src/test_data/get_schema_ty/bbb/main.k @@ -0,0 +1,2 @@ +schema B: + name: str \ No newline at end of file diff --git a/kclvm/query/src/test_data/import_paths.k b/kclvm/query/src/test_data/import_paths.k index 7cbd51526..44d5c3a58 100644 --- a/kclvm/query/src/test_data/import_paths.k +++ b/kclvm/query/src/test_data/import_paths.k @@ -2,7 +2,8 @@ import pkg import pkg.pkg import pkg.pkg as alias_pkg1 import pkg.pkg as alias_pkg2 -import .relative_pkg +import relative_pkg + schema Data: id?: int = 0 value?: str = "value" diff --git a/kclvm/query/src/test_data/kcl.mod b/kclvm/query/src/test_data/kcl.mod index e69de29bb..c51d42cae 100644 --- a/kclvm/query/src/test_data/kcl.mod +++ b/kclvm/query/src/test_data/kcl.mod @@ -0,0 +1,2 @@ +[package] + diff --git a/kclvm/query/src/tests.rs b/kclvm/query/src/tests.rs index 6758a23df..72041a36c 100644 --- a/kclvm/query/src/tests.rs +++ b/kclvm/query/src/tests.rs @@ -1,8 +1,9 @@ use std::path::PathBuf; use super::{r#override::apply_override_on_module, *}; +use crate::path::parse_attribute_path; use kclvm_ast::ast; -use kclvm_parser::parse_file; +use kclvm_parser::parse_file_force_errors; use pretty_assertions::assert_eq; const CARGO_FILE_PATH: &str = env!("CARGO_MANIFEST_DIR"); @@ -55,6 +56,7 @@ fn test_override_file_config() { "appConfiguration.mainContainer.name=override_name".to_string(), "appConfiguration.labels.key.key=\"override_value\"".to_string(), "appConfiguration.labels.key.str-key=\"override_value\"".to_string(), + "appConfiguration.labels.key['dot.key']=\"override_value\"".to_string(), "appConfiguration.overQuota=False".to_string(), "appConfiguration.probe={periodSeconds=20}".to_string(), "appConfiguration.resource-".to_string(), @@ -75,7 +77,7 @@ fn test_override_file_config() { cargo_file_path.push("src/test_data/config.k"); let abs_path = cargo_file_path.to_str().unwrap(); - let mut module = parse_file(abs_path, None).unwrap(); + let mut module = parse_file_force_errors(abs_path, None).unwrap(); for o in &overrides { apply_override_on_module(&mut module, o, &import_paths).unwrap(); } @@ -109,6 +111,7 @@ appConfiguration = AppConfiguration { key: { key: "override_value" "str-key" = "override_value" + "dot.key" = "override_value" } } mainContainer: Main {name: "override_name"} @@ -142,3 +145,42 @@ fn test_parse_override_spec_invalid() { assert!(parse_override_spec(spec).is_err(), "{spec} test failed"); } } + +#[test] +fn test_parse_property_path() { + assert_eq!(parse_attribute_path("a.b.c").unwrap(), vec!["a", "b", "c"]); + assert_eq!( + parse_attribute_path(r#"a["b"].c"#).unwrap(), + vec!["a", "b", "c"] + ); + assert_eq!( + parse_attribute_path(r#"a.["b"].c"#).unwrap(), + vec!["a", "b", "c"] + ); + assert_eq!( + parse_attribute_path(r#"a['b'].c"#).unwrap(), + vec!["a", "b", "c"] + ); + assert_eq!( + parse_attribute_path(r#"a.b['c.d']"#).unwrap(), + vec!["a", "b", "c.d"] + ); + assert_eq!( + parse_attribute_path(r#"a.b.['c.d']"#).unwrap(), + vec!["a", "b", "c.d"] + ); + assert_eq!( + parse_attribute_path(r#"a.b['c.d'].e"#).unwrap(), + vec!["a", "b", "c.d", "e"] + ); + assert_eq!( + parse_attribute_path(r#"a.b.['c.d'].e"#).unwrap(), + vec!["a", "b", "c.d", "e"] + ); + assert_eq!( + parse_attribute_path(r#"a.b.c-d.e"#).unwrap(), + vec!["a", "b", "c-d", "e"] + ); + assert!(parse_attribute_path(r#"a.[b.c-d.e"#).is_err(),); + assert!(parse_attribute_path(r#"a.[b.c]-d.e"#).is_err(),); +} diff --git a/kclvm/query/src/util.rs b/kclvm/query/src/util.rs index 3d7bf3b90..f4d811fd9 100644 --- a/kclvm/query/src/util.rs +++ b/kclvm/query/src/util.rs @@ -27,3 +27,12 @@ pub(crate) fn split_field_path(path: &str) -> Result<(String, String)> { pub(crate) fn invalid_spec_error(spec: &str) -> anyhow::Error { anyhow!("Invalid spec format '{}', expected := or :-", spec) } + +/// Get the invalid symbol selector spec error message. +#[inline] +pub(crate) fn invalid_symbol_selector_spec_error(spec: &str) -> anyhow::Error { + anyhow!( + "Invalid spec format '{}', expected :", + spec + ) +} diff --git a/kclvm/runner/Cargo.toml b/kclvm/runner/Cargo.toml index f7e05eed1..b46b87edb 100644 --- a/kclvm/runner/Cargo.toml +++ b/kclvm/runner/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-runner" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -37,6 +37,7 @@ kclvm-error = {path = "../error"} kclvm-query = {path = "../query"} kclvm-utils = {path = "../utils"} kclvm-driver = {path = "../driver"} +uuid = "1.7.0" [dev-dependencies] kclvm-parser = {path = "../parser"} @@ -44,4 +45,4 @@ criterion = "0.3" [[bench]] name = "bench_runner" -harness = false \ No newline at end of file +harness = false diff --git a/kclvm/runner/benches/bench_runner.rs b/kclvm/runner/benches/bench_runner.rs index c75311fdb..5863d35f6 100644 --- a/kclvm/runner/benches/bench_runner.rs +++ b/kclvm/runner/benches/bench_runner.rs @@ -35,7 +35,7 @@ fn exec(file: &str) -> Result { let opts = args.get_load_program_options(); let sess = Arc::new(ParseSession::default()); // Load AST program - let program = load_program(sess.clone(), &[file], Some(opts)).unwrap(); + let program = load_program(sess.clone(), &[file], Some(opts), None).unwrap(); // Resolve ATS, generate libs, link libs and execute. execute(sess, program, &args) } diff --git a/kclvm/runner/src/assembler.rs b/kclvm/runner/src/assembler.rs index 92c926179..340fabc85 100644 --- a/kclvm/runner/src/assembler.rs +++ b/kclvm/runner/src/assembler.rs @@ -6,7 +6,7 @@ use kclvm_compiler::codegen::{ llvm::{emit_code, OBJECT_FILE_SUFFIX}, EmitOptions, }; -use kclvm_config::cache::{load_pkg_cache, save_pkg_cache, CacheOption}; +use kclvm_config::cache::{load_pkg_cache, save_pkg_cache, CacheOption, KCL_CACHE_PATH_ENV_VAR}; use kclvm_sema::resolver::scope::ProgramScope; use std::{ collections::HashMap, @@ -14,6 +14,8 @@ use std::{ path::{Path, PathBuf}, }; +use crate::ExecProgramArgs; + /// IR code file suffix. const DEFAULT_IR_FILE: &str = "_a.out"; @@ -54,12 +56,15 @@ pub(crate) trait LibAssembler { /// /// "object_file_path" is the full filename of the generated intermediate code file with suffix. /// e.g. code_file_path : "/test_dir/test_code_file.o" + /// + /// "arg" is the arguments of the kclvm runtime. fn assemble( &self, compile_prog: &Program, import_names: IndexMap>, code_file: &str, code_file_path: &str, + arg: &ExecProgramArgs, ) -> Result; /// Clean cache lock files. @@ -90,6 +95,7 @@ impl LibAssembler for KclvmLibAssembler { import_names: IndexMap>, code_file: &str, object_file_path: &str, + args: &ExecProgramArgs, ) -> Result { match &self { KclvmLibAssembler::LLVM => LlvmLibAssembler::default().assemble( @@ -97,6 +103,7 @@ impl LibAssembler for KclvmLibAssembler { import_names, code_file, object_file_path, + args, ), } } @@ -145,6 +152,7 @@ impl LibAssembler for LlvmLibAssembler { import_names: IndexMap>, code_file: &str, object_file_path: &str, + arg: &ExecProgramArgs, ) -> Result { // Clean the existed "*.o" object file. clean_path(object_file_path)?; @@ -152,6 +160,7 @@ impl LibAssembler for LlvmLibAssembler { // Compile KCL code into ".o" object file. emit_code( compile_prog, + arg.work_dir.clone().unwrap_or("".to_string()), import_names, &EmitOptions { from_path: None, @@ -243,8 +252,8 @@ impl KclvmAssembler { /// Generate cache dir from the program root path. /// Create cache dir if it doesn't exist. #[inline] - pub(crate) fn load_cache_dir(&self, prog_root_name: &str) -> Result { - let cache_dir = self.construct_cache_dir(prog_root_name); + pub(crate) fn load_cache_dir(&self, root: &str) -> Result { + let cache_dir = self.construct_cache_dir(root); if !cache_dir.exists() { std::fs::create_dir_all(&cache_dir)?; } @@ -252,8 +261,9 @@ impl KclvmAssembler { } #[inline] - pub(crate) fn construct_cache_dir(&self, prog_root_name: &str) -> PathBuf { - Path::new(prog_root_name) + pub(crate) fn construct_cache_dir(&self, root: &str) -> PathBuf { + let root = std::env::var(KCL_CACHE_PATH_ENV_VAR).unwrap_or(root.to_string()); + Path::new(&root) .join(".kclvm") .join("cache") .join(kclvm_version::get_version_string()) @@ -270,7 +280,7 @@ impl KclvmAssembler { /// /// `gen_libs` will create multiple threads and call the method provided by [KclvmLibAssembler] in each thread /// to generate the dynamic link library in parallel. - pub(crate) fn gen_libs(self) -> Result> { + pub(crate) fn gen_libs(self, args: &ExecProgramArgs) -> Result> { self.clean_path_for_genlibs( DEFAULT_IR_FILE, &self.single_file_assembler.get_code_file_suffix(), @@ -289,7 +299,6 @@ impl KclvmAssembler { pkgs.insert(pkgpath.clone(), modules); let compile_prog = ast::Program { root: self.program.root.clone(), - main: self.program.main.clone(), pkgs, }; compile_progs.insert( @@ -336,7 +345,13 @@ impl KclvmAssembler { // written. let file_path = if is_main_pkg { // generate dynamic link library for single file kcl program - assembler.assemble(&compile_prog, import_names, &code_file, &code_file_path)? + assembler.assemble( + &compile_prog, + import_names, + &code_file, + &code_file_path, + args, + )? } else { // Read the lib path cache let file_relative_path: Option = load_pkg_cache( @@ -370,14 +385,16 @@ impl KclvmAssembler { import_names, &code_file, &code_file_path, + args, )?; let lib_relative_path = file_path.replacen(root, ".", 1); - save_pkg_cache( + let _ = save_pkg_cache( root, &target, &pkgpath, lib_relative_path, CacheOption::default(), + &self.external_pkgs, ); file_path } diff --git a/kclvm/runner/src/custom_manifests_data/list.stdout.golden b/kclvm/runner/src/custom_manifests_data/list.stdout.golden index 1b3810d70..cf081cf3d 100644 --- a/kclvm/runner/src/custom_manifests_data/list.stdout.golden +++ b/kclvm/runner/src/custom_manifests_data/list.stdout.golden @@ -1,17 +1,17 @@ k1: - - 1 - - 2 +- 1 +- 2 k2: - - 3 - - 4 +- 3 +- 4 --- k3: - - 5 - - 6 +- 5 +- 6 k4: - - 7 - - 8 +- 7 +- 8 --- k5: - - 9 - - 10 +- 9 +- 10 diff --git a/kclvm/runner/src/lib.rs b/kclvm/runner/src/lib.rs index 51a82eab1..a297e91ac 100644 --- a/kclvm/runner/src/lib.rs +++ b/kclvm/runner/src/lib.rs @@ -1,20 +1,20 @@ -use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime}; +use std::{collections::HashMap, ffi::OsStr, path::Path}; -use anyhow::Result; +use anyhow::{anyhow, bail, Result}; use assembler::KclvmLibAssembler; use kclvm_ast::{ ast::{Module, Program}, MAIN_PKG, }; -use kclvm_driver::canonicalize_input_files; -use kclvm_error::{Diagnostic, Handler}; -use kclvm_parser::{load_program, ParseSession}; +use kclvm_driver::{canonicalize_input_files, expand_input_files}; +use kclvm_parser::{load_program, KCLModuleCache, ParseSessionRef}; use kclvm_query::apply_overrides; -use kclvm_runtime::{PanicInfo, ValueRef}; -use kclvm_sema::resolver::resolve_program; +use kclvm_sema::resolver::{ + resolve_program, resolve_program_with_opts, scope::ProgramScope, Options, +}; use linker::Command; -pub use runner::ExecProgramArgs; -use runner::{ExecProgramResult, KclvmRunner, KclvmRunnerOptions}; +pub use runner::{Artifact, ExecProgramArgs, ExecProgramResult, MapErrorResult}; +use runner::{KclLibRunner, KclLibRunnerOptions, ProgramRunner}; use tempfile::tempdir; pub mod assembler; @@ -25,7 +25,7 @@ pub mod runner; pub mod tests; /// After the kcl program passed through kclvm-parser in the compiler frontend, -/// KCLVM needs to resolve ast, generate corresponding LLVM IR, dynamic link library or +/// KCL needs to resolve ast, generate corresponding LLVM IR, dynamic link library or /// executable file for kcl program in the compiler backend. /// /// Method “execute” is the entry point for the compiler backend. @@ -33,7 +33,7 @@ pub mod tests; /// It returns the KCL program executing result as Result, /// and mainly takes "program" (ast.Program returned by kclvm-parser) as input. /// -/// "args" is the items selected by the user in the KCLVM CLI. +/// "args" is the items selected by the user in the KCL CLI. /// /// This method will first resolve “program” (ast.Program) and save the result to the "scope" (ProgramScope). /// @@ -48,7 +48,7 @@ pub mod tests; /// After linking all dynamic link libraries by KclvmLinker, method "KclvmLinker::link_all_libs" will return a path /// for dynamic link library after linking. /// -/// At last, KclvmRunner will be constructed and call method "run" to execute the kcl program. +/// At last, KclLibRunner will be constructed and call method "run" to execute the kcl program. /// /// **Note that it is not thread safe.** /// @@ -69,73 +69,38 @@ pub mod tests; /// // Result is the kcl in json format. /// let result = exec_program(sess, &args).unwrap(); /// ``` -pub fn exec_program( - sess: Arc, - args: &ExecProgramArgs, -) -> Result { +pub fn exec_program(sess: ParseSessionRef, args: &ExecProgramArgs) -> Result { // parse args from json string let opts = args.get_load_program_options(); - let k_files = &args.k_filename_list; - let work_dir = args.work_dir.clone().unwrap_or_default(); - let kcl_paths = canonicalize_input_files(k_files, work_dir, false)?; - + let kcl_paths = expand_files(args)?; let kcl_paths_str = kcl_paths.iter().map(|s| s.as_str()).collect::>(); - - let mut program = load_program(sess.clone(), kcl_paths_str.as_slice(), Some(opts))?; - - if let Err(err) = apply_overrides( + let module_cache = KCLModuleCache::default(); + let mut program = load_program( + sess.clone(), + kcl_paths_str.as_slice(), + Some(opts), + Some(module_cache), + )? + .program; + apply_overrides( &mut program, &args.overrides, &[], args.print_override_ast || args.debug > 0, - ) { - return Err(err.to_string()); - } + )?; + execute(sess, program, args) +} - let start_time = SystemTime::now(); - let exec_result = execute(sess, program, args); - let escape_time = match SystemTime::now().duration_since(start_time) { - Ok(dur) => dur.as_secs_f32(), - Err(err) => return Err(err.to_string()), - }; - let mut result = ExecProgramResult { - escaped_time: escape_time.to_string(), - ..Default::default() - }; - // Exec result is a JSON or YAML string. - let exec_result = match exec_result { - Ok(res) => { - if res.is_empty() { - return Ok(result); - } else { - res - } - } - Err(res) => { - if res.is_empty() { - return Ok(result); - } else { - return Err(res); - } - } - }; - let kcl_val = match ValueRef::from_yaml_stream(&exec_result) { - Ok(v) => v, - Err(err) => return Err(err.to_string()), - }; - // Filter values with the path selector. - let kcl_val = kcl_val.filter_by_path(&args.path_selector)?; - // Plan values. - let (json_result, yaml_result) = kcl_val.plan(args.sort_keys); - result.json_result = json_result; - if !args.disable_yaml_result { - result.yaml_result = yaml_result; - } - Ok(result) +/// Execute the KCL artifact with args. +pub fn exec_artifact>( + path: P, + args: &ExecProgramArgs, +) -> Result { + Artifact::from_path(path)?.run(args) } /// After the kcl program passed through kclvm-parser in the compiler frontend, -/// KCLVM needs to resolve ast, generate corresponding LLVM IR, dynamic link library or +/// KCL needs to resolve ast, generate corresponding LLVM IR, dynamic link library or /// executable file for kcl program in the compiler backend. /// /// Method “execute” is the entry point for the compiler backend. @@ -143,7 +108,7 @@ pub fn exec_program( /// It returns the KCL program executing result as Result, /// and mainly takes "program" (ast.Program returned by kclvm-parser) as input. /// -/// "args" is the items selected by the user in the KCLVM CLI. +/// "args" is the items selected by the user in the KCL CLI. /// /// This method will first resolve “program” (ast.Program) and save the result to the "scope" (ProgramScope). /// @@ -158,7 +123,7 @@ pub fn exec_program( /// After linking all dynamic link libraries by KclvmLinker, method "KclvmLinker::link_all_libs" will return a path /// for dynamic link library after linking. /// -/// At last, KclvmRunner will be constructed and call method "run" to execute the kcl program. +/// At last, KclLibRunner will be constructed and call method "run" to execute the kcl program. /// /// **Note that it is not thread safe.** /// @@ -178,28 +143,37 @@ pub fn exec_program( /// /// // Parse kcl file /// let kcl_path = "./src/test_datas/init_check_order_0/main.k"; -/// let prog = load_program(sess.clone(), &[kcl_path], Some(opts)).unwrap(); +/// let prog = load_program(sess.clone(), &[kcl_path], Some(opts), None).unwrap().program; /// /// // Resolve ast, generate libs, link libs and execute. /// // Result is the kcl in json format. /// let result = execute(sess, prog, &args).unwrap(); /// ``` pub fn execute( - sess: Arc, + sess: ParseSessionRef, mut program: Program, args: &ExecProgramArgs, -) -> Result { +) -> Result { + // If the user only wants to compile the kcl program, the following code will only resolve ast. + if args.compile_only { + let mut resolve_opts = Options::default(); + resolve_opts.merge_program = false; + // Resolve ast + let scope = resolve_program_with_opts(&mut program, resolve_opts, None); + emit_compile_diag_to_string(sess, &scope, args.compile_only)?; + return Ok(ExecProgramResult::default()); + } // Resolve ast let scope = resolve_program(&mut program); - scope.emit_diagnostics_to_string(sess.0.clone())?; - + // Emit parse and resolve errors if exists. + emit_compile_diag_to_string(sess, &scope, false)?; // Create a temp entry file and the temp dir will be delete automatically - let temp_dir = tempdir().map_err(|e| e.to_string())?; - let temp_dir_path = temp_dir.path().to_str().ok_or(format!( + let temp_dir = tempdir()?; + let temp_dir_path = temp_dir.path().to_str().ok_or(anyhow!( "Internal error: {}: No such file or directory", temp_dir.path().display() ))?; - let temp_entry_file = temp_file(temp_dir_path).map_err(|e| e.to_string())?; + let temp_entry_file = temp_file(temp_dir_path)?; // Generate libs let lib_paths = assembler::KclvmAssembler::new( @@ -209,38 +183,22 @@ pub fn execute( KclvmLibAssembler::LLVM, args.get_package_maps_from_external_pkg(), ) - .gen_libs() - .map_err(|e| e.to_string())?; + .gen_libs(args)?; - // Link libs + // Link libs into one library let lib_suffix = Command::get_lib_suffix(); let temp_out_lib_file = format!("{}{}", temp_entry_file, lib_suffix); - let lib_path = linker::KclvmLinker::link_all_libs(lib_paths, temp_out_lib_file) - .map_err(|e| e.to_string())?; + let lib_path = linker::KclvmLinker::link_all_libs(lib_paths, temp_out_lib_file)?; - // Run - let runner = KclvmRunner::new(Some(KclvmRunnerOptions { + // Run the library + let runner = KclLibRunner::new(Some(KclLibRunnerOptions { plugin_agent_ptr: args.plugin_agent, })); - let result = runner.run(&lib_path, args); + let result = runner.run(&lib_path, args)?; - // Clean temp files. - // FIXME(issue #346): On windows, sometimes there will be an error that the file cannot be accessed. - // Therefore, the function of automatically deleting dll files on windows is temporarily turned off. - #[cfg(not(target_os = "windows"))] - remove_file(&lib_path).map_err(|e| e.to_string())?; - #[cfg(not(target_os = "windows"))] - clean_tmp_files(&temp_entry_file, &lib_suffix).map_err(|e| e.to_string())?; - // Wrap runtime error into diagnostic style string. - result.map_err(|err| { - match Handler::default() - .add_diagnostic(>::into(PanicInfo::from(err))) - .emit_to_string() - { - Ok(msg) => msg, - Err(err) => err.to_string(), - } - }) + remove_file(&lib_path)?; + clean_tmp_files(&temp_entry_file, &lib_suffix)?; + Ok(result) } /// `execute_module` can directly execute the ast `Module`. @@ -249,7 +207,7 @@ pub fn execute( /// For more information, see doc above method `execute`. /// /// **Note that it is not thread safe.** -pub fn execute_module(mut m: Module) -> Result { +pub fn execute_module(mut m: Module) -> Result { m.pkg = MAIN_PKG.to_string(); let mut pkgs = HashMap::new(); @@ -257,17 +215,77 @@ pub fn execute_module(mut m: Module) -> Result { let prog = Program { root: MAIN_PKG.to_string(), - main: MAIN_PKG.to_string(), pkgs, }; execute( - Arc::new(ParseSession::default()), + ParseSessionRef::default(), prog, &ExecProgramArgs::default(), ) } +/// Build a KCL program and generate a library artifact. +pub fn build_program>( + sess: ParseSessionRef, + args: &ExecProgramArgs, + output: Option

, +) -> Result { + // Parse program. + let opts = args.get_load_program_options(); + let kcl_paths = expand_files(args)?; + let kcl_paths_str = kcl_paths.iter().map(|s| s.as_str()).collect::>(); + let mut program = + load_program(sess.clone(), kcl_paths_str.as_slice(), Some(opts), None)?.program; + // Resolve program. + let scope = resolve_program(&mut program); + // Emit parse and resolve errors if exists. + emit_compile_diag_to_string(sess, &scope, false)?; + // Create a temp entry file and the temp dir will be delete automatically. + let temp_dir = tempdir()?; + let temp_dir_path = temp_dir.path().to_str().ok_or(anyhow!( + "Internal error: {}: No such file or directory", + temp_dir.path().display() + ))?; + let temp_entry_file = temp_file(temp_dir_path)?; + // Generate native libs. + let lib_paths = assembler::KclvmAssembler::new( + program, + scope, + temp_entry_file.clone(), + KclvmLibAssembler::LLVM, + args.get_package_maps_from_external_pkg(), + ) + .gen_libs(args)?; + + // Link libs into one library. + let lib_suffix = Command::get_lib_suffix(); + let temp_out_lib_file = if let Some(output) = output { + let path = output + .as_ref() + .to_str() + .ok_or(anyhow!("build output path is not found"))? + .to_string(); + path + } else { + format!("{}{}", temp_entry_file, lib_suffix) + }; + let lib_path = linker::KclvmLinker::link_all_libs(lib_paths, temp_out_lib_file)?; + + // Return the library artifact. + Artifact::from_path(lib_path) +} + +/// Expand and return the normalized file paths for the input file list. +pub fn expand_files(args: &ExecProgramArgs) -> Result> { + let k_files = &args.k_filename_list; + let work_dir = args.work_dir.clone().unwrap_or_default(); + let k_files = expand_input_files(k_files); + let kcl_paths = + canonicalize_input_files(&k_files, work_dir, false).map_err(|err| anyhow!(err))?; + Ok(kcl_paths) +} + /// Clean all the tmp files generated during lib generating and linking. #[inline] fn clean_tmp_files(temp_entry_file: &String, lib_suffix: &String) -> Result<()> { @@ -295,3 +313,25 @@ fn temp_file(dir: &str) -> Result { .ok_or(anyhow::anyhow!("{dir} not found"))? .to_string()) } + +// [`emit_compile_diag_to_string`] will emit compile diagnostics to string, including parsing and resolving diagnostics. +fn emit_compile_diag_to_string( + sess: ParseSessionRef, + scope: &ProgramScope, + include_warnings: bool, +) -> Result<()> { + let mut res_str = sess.1.borrow_mut().emit_to_string()?; + let sema_err = scope.emit_diagnostics_to_string(sess.0.clone(), include_warnings); + if sema_err.is_err() { + #[cfg(not(target_os = "windows"))] + res_str.push_str("\n"); + #[cfg(target_os = "windows")] + res_str.push_str("\r\n"); + res_str.push_str(&sema_err.unwrap_err()); + } + + res_str + .is_empty() + .then(|| Ok(())) + .unwrap_or_else(|| bail!(res_str)) +} diff --git a/kclvm/runner/src/linker.rs b/kclvm/runner/src/linker.rs index 9388a4ca1..036ddfd8d 100644 --- a/kclvm/runner/src/linker.rs +++ b/kclvm/runner/src/linker.rs @@ -6,7 +6,6 @@ use std::path::PathBuf; const KCLVM_CLI_BIN_PATH_ENV_VAR: &str = "KCLVM_CLI_BIN_PATH"; const KCLVM_LIB_LINK_PATH_ENV_VAR: &str = "KCLVM_LIB_LINK_PATH"; const KCLVM_LIB_SHORT_NAME: &str = "kclvm_cli_cdylib"; - const EXEC_ROOT_NOT_FOUND_MSG: &str = "Internal error: the executable root is not found"; /// KclvmLinker is mainly responsible for linking the libs generated by KclvmAssembler. @@ -100,41 +99,18 @@ impl Command { pub(crate) fn unix_args( &self, libs: &[String], - lib_path: String, + _lib_path: String, cmd: &mut std::process::Command, ) -> Result<()> { - let path = self.runtime_lib_path(&lib_path)?; + let path = self.get_lib_link_path()?; cmd.args(libs) .arg(&format!("-Wl,-rpath,{}", &path)) .arg(&format!("-L{}", &path)) .arg(&format!("-I{}/include", self.executable_root)) - .arg("-lkclvm_cli_cdylib"); + .arg(&format!("-l{KCLVM_LIB_SHORT_NAME}")); Ok(()) } - /// Get the runtime library path. - pub(crate) fn runtime_lib_path(&self, lib_path: &str) -> Result { - let path = self.get_lib_link_path()?; - let lib_name = Self::get_lib_name(); - let lib_file_path = std::path::Path::new(&path).join(&lib_name); - // Copy runtime library to target path for parallel execute. - Ok( - if let Some(target_path) = std::path::Path::new(&lib_path).parent() { - let target_lib_file_path = std::path::Path::new(target_path).join(&lib_name); - - // Locking file for parallel file copy. - let mut file_lock = - fslock::LockFile::open(&format!("{}.lock", target_lib_file_path.display()))?; - file_lock.lock()?; - - std::fs::copy(lib_file_path, target_lib_file_path)?; - target_path.to_string_lossy().to_string() - } else { - path - }, - ) - } - // Add args for cc on windows os. #[cfg(target_os = "windows")] pub(crate) fn msvc_win_args( @@ -144,7 +120,7 @@ impl Command { cmd: &mut std::process::Command, ) -> Result<()> { cmd.args(libs) - .arg("kclvm_cli_cdylib.lib") + .arg(&format!("{KCLVM_LIB_SHORT_NAME}.lib")) .arg("/link") .arg("/NOENTRY") .arg("/NOLOGO") @@ -164,12 +140,12 @@ impl Command { if let Ok(path) = std::env::var(KCLVM_CLI_BIN_PATH_ENV_VAR) { return Ok(path); } - let kclvm_exe = if Self::is_windows() { - "kclvm.exe" + let bin_name = if Self::is_windows() { + "kclvm_cli.exe" } else { - "kclvm" + "kclvm_cli" }; - let p = if let Some(x) = Self::find_it(kclvm_exe) { + let p = if let Some(x) = Self::find_it(bin_name) { x } else { std::env::current_exe()? diff --git a/kclvm/runner/src/runner.rs b/kclvm/runner/src/runner.rs index 0c320cff5..6d3ca2ec7 100644 --- a/kclvm/runner/src/runner.rs +++ b/kclvm/runner/src/runner.rs @@ -1,3 +1,4 @@ +use anyhow::{anyhow, Result}; use std::collections::HashMap; use kclvm_ast::ast; @@ -5,14 +6,18 @@ use kclvm_config::{ modfile::get_vendor_home, settings::{SettingsFile, SettingsPathBuf}, }; +use kclvm_error::{Diagnostic, Handler}; use kclvm_query::r#override::parse_override_spec; -use kclvm_runtime::ValueRef; +use kclvm_runtime::{FFIRunOptions, PanicInfo}; use serde::{Deserialize, Serialize}; +use std::ffi::OsStr; +use std::os::raw::c_char; const RESULT_SIZE: usize = 2048 * 2048; +const KCL_DEBUG_ERROR_ENV_VAR: &str = "KCL_DEBUG_ERROR"; #[allow(non_camel_case_types)] -pub type kclvm_char_t = i8; +pub type kclvm_char_t = c_char; #[allow(non_camel_case_types)] pub type kclvm_size_t = i32; #[allow(non_camel_case_types)] @@ -25,32 +30,35 @@ pub type kclvm_value_ref_t = std::ffi::c_void; pub struct ExecProgramArgs { pub work_dir: Option, pub k_filename_list: Vec, - // -E key=value + /// -E key=value pub external_pkgs: Vec, pub k_code_list: Vec, - // -D key=value + /// -D key=value pub args: Vec, - // -O override_spec + /// -O override_spec pub overrides: Vec, - // -S path_selector - #[serde(skip)] + /// -S path_selector pub path_selector: Vec, pub disable_yaml_result: bool, - // Whether to apply overrides on the source code. + /// Whether to apply overrides on the source code. pub print_override_ast: bool, - // -r --strict-range-check + /// -r --strict-range-check pub strict_range_check: bool, - // -n --disable-none + /// -n --disable-none pub disable_none: bool, - // -v --verbose + /// -v --verbose pub verbose: i32, - // -d --debug + /// -d --debug pub debug: i32, - // yaml/json: sort keys + /// yaml/json: sort keys pub sort_keys: bool, - // include schema type path in JSON/YAML result + /// Show hidden attributes + pub show_hidden: bool, + /// Whether including schema type in JSON/YAML result pub include_schema_type_path: bool, - // plugin_agent is the address of plugin. + /// Whether to compile only. + pub compile_only: bool, + /// plugin_agent is the address of plugin. #[serde(skip)] pub plugin_agent: u64, } @@ -82,8 +90,42 @@ impl ExecProgramArgs { pub struct ExecProgramResult { pub json_result: String, pub yaml_result: String, + pub log_message: String, + pub err_message: String, +} + +pub trait MapErrorResult { + /// Map execute error message into the [`Result::Err`] + fn map_err_to_result(self) -> Result + where + Self: Sized; +} + +impl MapErrorResult for ExecProgramResult { + /// Map execute error message into the [`Result::Err`] + fn map_err_to_result(self) -> Result + where + Self: Sized, + { + if self.err_message.is_empty() { + Ok(self) + } else { + Err(anyhow!(self.err_message)) + } + } +} - pub escaped_time: String, +impl MapErrorResult for Result { + /// Map execute error message into the [`Result::Err`] + fn map_err_to_result(self) -> Result + where + Self: Sized, + { + match self { + Ok(result) => result.map_err_to_result(), + Err(err) => Err(err), + } + } } impl ExecProgramArgs { @@ -112,8 +154,6 @@ impl ExecProgramArgs { vendor_dirs: vec![get_vendor_home()], package_maps: self.get_package_maps_from_external_pkg(), k_code_list: self.k_code_list.clone(), - cmd_args: self.args.clone(), - cmd_overrides: self.overrides.clone(), load_plugins: self.plugin_agent > 0, ..Default::default() } @@ -134,6 +174,9 @@ impl TryFrom for ExecProgramArgs { args.verbose = cli_configs.verbose.unwrap_or_default() as i32; args.debug = cli_configs.debug.unwrap_or_default() as i32; args.sort_keys = cli_configs.sort_keys.unwrap_or_default(); + args.show_hidden = cli_configs.show_hidden.unwrap_or_default(); + args.include_schema_type_path = + cli_configs.include_schema_type_path.unwrap_or_default(); for override_str in &cli_configs.overrides.unwrap_or_default() { args.overrides.push(parse_override_spec(override_str)?); } @@ -164,43 +207,70 @@ impl TryFrom for ExecProgramArgs { } } +/// A public struct named [Artifact] which wraps around the native library [libloading::Library]. +pub struct Artifact(libloading::Library, String); + +pub trait ProgramRunner { + /// Run with the arguments [ExecProgramArgs] and return the program execute result that + /// contains the planning result and the evaluation errors if any. + fn run(&self, args: &ExecProgramArgs) -> Result; +} + +impl ProgramRunner for Artifact { + fn run(&self, args: &ExecProgramArgs) -> Result { + unsafe { + KclLibRunner::lib_kclvm_plugin_init(&self.0, args.plugin_agent)?; + KclLibRunner::lib_kcl_run(&self.0, args) + } + } +} + +impl Artifact { + #[inline] + pub fn from_path>(path: P) -> Result { + let path = path.as_ref().to_str().unwrap().to_string(); + let lib = unsafe { libloading::Library::new(&path)? }; + Ok(Self(lib, path)) + } + + #[inline] + pub fn get_path(&self) -> &String { + &self.1 + } +} + #[derive(Debug, Default)] -pub struct KclvmRunnerOptions { +pub struct KclLibRunnerOptions { pub plugin_agent_ptr: u64, } -pub struct KclvmRunner { - opts: KclvmRunnerOptions, +pub struct KclLibRunner { + opts: KclLibRunnerOptions, } -impl KclvmRunner { +impl KclLibRunner { /// New a runner using the lib path and options. - pub fn new(opts: Option) -> Self { + pub fn new(opts: Option) -> Self { Self { opts: opts.unwrap_or_default(), } } /// Run kcl library with exec arguments. - pub fn run(&self, lib_path: &str, args: &ExecProgramArgs) -> Result { + pub fn run(&self, lib_path: &str, args: &ExecProgramArgs) -> Result { unsafe { - let lib = libloading::Library::new( - std::path::PathBuf::from(lib_path) - .canonicalize() - .map_err(|e| e.to_string())?, - ) - .map_err(|e| e.to_string())?; + let lib = libloading::Library::new(std::path::PathBuf::from(lib_path).canonicalize()?)?; Self::lib_kclvm_plugin_init(&lib, self.opts.plugin_agent_ptr)?; Self::lib_kcl_run(&lib, args) } } } -impl KclvmRunner { +impl KclLibRunner { unsafe fn lib_kclvm_plugin_init( lib: &libloading::Library, plugin_method_ptr: u64, - ) -> Result<(), String> { + ) -> Result<()> { // get kclvm_plugin_init let kclvm_plugin_init: libloading::Symbol< unsafe extern "C" fn( @@ -210,7 +280,7 @@ impl KclvmRunner { kwargs_json: *const i8, ) -> *const i8, ), - > = lib.get(b"kclvm_plugin_init").map_err(|e| e.to_string())?; + > = lib.get(b"kclvm_plugin_init")?; // get plugin_method let plugin_method_ptr = plugin_method_ptr; @@ -234,119 +304,147 @@ impl KclvmRunner { unsafe fn lib_kcl_run( lib: &libloading::Library, args: &ExecProgramArgs, - ) -> Result { + ) -> Result { let kcl_run: libloading::Symbol< unsafe extern "C" fn( kclvm_main_ptr: u64, // main.k => kclvm_main option_len: kclvm_size_t, option_keys: *const *const kclvm_char_t, option_values: *const *const kclvm_char_t, - strict_range_check: i32, - disable_none: i32, - disable_schema_check: i32, - list_option_mode: i32, - debug_mode: i32, - result_buffer_len: kclvm_size_t, - result_buffer: *mut kclvm_char_t, - warn_buffer_len: kclvm_size_t, - warn_buffer: *mut kclvm_char_t, + opts: FFIRunOptions, + path_selector: *const *const kclvm_char_t, + json_result_buffer_len: *mut kclvm_size_t, + json_result_buffer: *mut kclvm_char_t, + yaml_result_buffer_len: *mut kclvm_size_t, + yaml_result_buffer: *mut kclvm_char_t, + err_buffer_len: *mut kclvm_size_t, + err_buffer: *mut kclvm_char_t, + log_buffer_len: *mut kclvm_size_t, + log_buffer: *mut kclvm_char_t, ) -> kclvm_size_t, - > = lib.get(b"_kcl_run").map_err(|e| e.to_string())?; + > = lib.get(b"_kcl_run")?; - let kclvm_main: libloading::Symbol = - lib.get(b"kclvm_main").map_err(|e| e.to_string())?; + // The lib main function + let kclvm_main: libloading::Symbol = lib.get(b"kclvm_main")?; let kclvm_main_ptr = kclvm_main.into_raw().into_raw() as u64; + // CLI configs option len let option_len = args.args.len() as kclvm_size_t; - + // CLI configs option keys let cstr_argv: Vec<_> = args .args .iter() .map(|arg| std::ffi::CString::new(arg.name.as_str()).unwrap()) .collect(); - let mut p_argv: Vec<_> = cstr_argv .iter() // do NOT into_iter() .map(|arg| arg.as_ptr()) .collect(); p_argv.push(std::ptr::null()); - - let p: *const *const kclvm_char_t = p_argv.as_ptr(); - let option_keys = p; - + let option_keys = p_argv.as_ptr(); + // CLI configs option values let cstr_argv: Vec<_> = args .args .iter() .map(|arg| std::ffi::CString::new(arg.value.as_str()).unwrap()) .collect(); - let mut p_argv: Vec<_> = cstr_argv .iter() // do NOT into_iter() .map(|arg| arg.as_ptr()) .collect(); p_argv.push(std::ptr::null()); - - let p: *const *const kclvm_char_t = p_argv.as_ptr(); - let option_values = p; - - let strict_range_check = args.strict_range_check as i32; - let disable_none = args.disable_none as i32; - let disable_schema_check = 0; // todo - let list_option_mode = 0; // todo - let debug_mode = args.debug; - - let mut result = vec![0u8; RESULT_SIZE]; - let result_buffer_len = result.len() as i32 - 1; - let result_buffer = result.as_mut_ptr() as *mut i8; - - let mut warn_data = vec![0u8; RESULT_SIZE]; - let warn_buffer_len = warn_data.len() as i32 - 1; - let warn_buffer = warn_data.as_mut_ptr() as *mut i8; - - let n = kcl_run( + let option_values = p_argv.as_ptr(); + // path selectors + let cstr_argv: Vec<_> = args + .path_selector + .iter() + .map(|arg| std::ffi::CString::new(arg.as_str()).unwrap()) + .collect(); + let mut p_argv: Vec<_> = cstr_argv + .iter() // do NOT into_iter() + .map(|arg| arg.as_ptr()) + .collect(); + p_argv.push(std::ptr::null()); + let path_selector = p_argv.as_ptr(); + + let opts = FFIRunOptions { + strict_range_check: args.strict_range_check as i32, + disable_none: args.disable_none as i32, + disable_schema_check: 0, // todo + list_option_mode: 0, // todo + disable_empty_list: 0, + sort_keys: args.sort_keys as i32, + show_hidden: args.show_hidden as i32, + debug_mode: args.debug, + include_schema_type_path: args.include_schema_type_path as i32, + }; + let mut json_buffer = Buffer::make(); + let mut yaml_buffer = Buffer::make(); + let mut log_buffer = Buffer::make(); + let mut err_buffer = Buffer::make(); + // Input the main function, options and return the exec result + // including JSON and YAML result, log message and error message. + kcl_run( kclvm_main_ptr, option_len, option_keys, option_values, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - result_buffer_len, - result_buffer, - warn_buffer_len, - warn_buffer, + opts, + path_selector, + json_buffer.mut_len(), + json_buffer.mut_ptr(), + yaml_buffer.mut_len(), + yaml_buffer.mut_ptr(), + err_buffer.mut_len(), + err_buffer.mut_ptr(), + log_buffer.mut_len(), + log_buffer.mut_ptr(), ); - - if n == 0 { - Ok("".to_string()) - } else if n > 0 { - let return_len = n; - let s = - std::str::from_utf8(&result[0..return_len as usize]).map_err(|e| e.to_string())?; - wrap_msg_in_result(s) - } else { - let return_len = 0 - n; - let s = std::str::from_utf8(&warn_data[0..return_len as usize]) - .map_err(|e| e.to_string())?; - Err(s.to_string()) + // Convert runtime result to ExecProgramResult + let mut result = ExecProgramResult { + yaml_result: yaml_buffer.to_string()?, + json_result: json_buffer.to_string()?, + log_message: log_buffer.to_string()?, + err_message: err_buffer.to_string()?, + }; + // Wrap runtime JSON Panic error string into diagnostic style string. + if !result.err_message.is_empty() && std::env::var(KCL_DEBUG_ERROR_ENV_VAR).is_err() { + result.err_message = match Handler::default() + .add_diagnostic(>::into(PanicInfo::from( + result.err_message.as_str(), + ))) + .emit_to_string() + { + Ok(msg) => msg, + Err(err) => err.to_string(), + }; } + Ok(result) } } -fn wrap_msg_in_result(msg: &str) -> Result { - // YAML is compatible with JSON. We can use YAML library for result parsing. - let kcl_val = match ValueRef::from_yaml_stream(msg) { - Ok(msg) => msg, - Err(err) => { - return Err(err.to_string()); - } - }; - if let Some(val) = kcl_val.get_by_key("__kcl_PanicInfo__") { - if val.is_truthy() { - return Err(msg.to_string()); - } +#[repr(C)] +struct Buffer(Vec, i32); + +impl Buffer { + #[inline] + fn make() -> Self { + let buffer = vec![0u8; RESULT_SIZE]; + Self(buffer, RESULT_SIZE as i32 - 1) + } + + #[inline] + fn to_string(&self) -> anyhow::Result { + Ok(String::from_utf8(self.0[0..self.1 as usize].to_vec())?) + } + + #[inline] + fn mut_ptr(&mut self) -> *mut c_char { + self.0.as_mut_ptr() as *mut c_char + } + + #[inline] + fn mut_len(&mut self) -> &mut i32 { + &mut self.1 } - Ok(msg.to_string()) } diff --git a/kclvm/runner/src/test_datas/compile_recursive/kcl1/main.k b/kclvm/runner/src/test_datas/compile_recursive/kcl1/main.k new file mode 100644 index 000000000..23d3c668c --- /dev/null +++ b/kclvm/runner/src/test_datas/compile_recursive/kcl1/main.k @@ -0,0 +1 @@ +k1 = 'Hello k1!' \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/compile_recursive/kcl2/main.k b/kclvm/runner/src/test_datas/compile_recursive/kcl2/main.k new file mode 100644 index 000000000..0cc5f31c5 --- /dev/null +++ b/kclvm/runner/src/test_datas/compile_recursive/kcl2/main.k @@ -0,0 +1 @@ +k2 = 'Hello k2!' \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/compile_recursive/main.k b/kclvm/runner/src/test_datas/compile_recursive/main.k new file mode 100644 index 000000000..fa7048e63 --- /dev/null +++ b/kclvm/runner/src/test_datas/compile_recursive/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World!' \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/exec_prog_args/default.json b/kclvm/runner/src/test_datas/exec_prog_args/default.json index ac565a968..0ccfdb556 100644 --- a/kclvm/runner/src/test_datas/exec_prog_args/default.json +++ b/kclvm/runner/src/test_datas/exec_prog_args/default.json @@ -1 +1 @@ -{"work_dir":null,"k_filename_list":[],"external_pkgs":[],"k_code_list":[],"args":[],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false} \ No newline at end of file +{"work_dir":null,"k_filename_list":[],"external_pkgs":[],"k_code_list":[],"args":[],"overrides":[],"path_selector":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"show_hidden":false,"include_schema_type_path":false,"compile_only":false} \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/init_check_order_0/stdout.golden.json b/kclvm/runner/src/test_datas/init_check_order_0/stdout.golden.json index c962e7309..a80a0c009 100644 --- a/kclvm/runner/src/test_datas/init_check_order_0/stdout.golden.json +++ b/kclvm/runner/src/test_datas/init_check_order_0/stdout.golden.json @@ -1 +1 @@ -{"alice": {"name": "alice", "age": 10, "gender": "female", "info": "alice, female, 10 years old", "__settings__": {"output_type": "INLINE", "__schema_type__": "__main__.Person"}}} \ No newline at end of file +{"alice": {"name": "alice", "age": 10, "gender": "female", "info": "alice, female, 10 years old"}} \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/init_check_order_1/stdout.golden.json b/kclvm/runner/src/test_datas/init_check_order_1/stdout.golden.json index 1aad8c19b..c56067a6c 100644 --- a/kclvm/runner/src/test_datas/init_check_order_1/stdout.golden.json +++ b/kclvm/runner/src/test_datas/init_check_order_1/stdout.golden.json @@ -1 +1 @@ -{"alice": {"firstName": "Alice", "lastName": "Smith", "upper": "SMITH", "__settings__": {"output_type": "INLINE", "__schema_type__": "__main__.InfoMixin"}, "gender": "female", "title": "Ms.Smith", "info": "Ms.Smith, female", "added": "some girl attr"}, "bob": {"firstName": "Bob", "lastName": "Green", "upper": "GREEN", "__settings__": {"output_type": "INLINE", "__schema_type__": "__main__.InfoMixin"}, "gender": "male", "title": "Mr.Green", "info": "Mr.Green, male", "added": "some boy attr"}} \ No newline at end of file +{"alice": {"firstName": "Alice", "lastName": "Smith", "upper": "SMITH", "gender": "female", "title": "Ms.Smith", "info": "Ms.Smith, female", "added": "some girl attr"}, "bob": {"firstName": "Bob", "lastName": "Green", "upper": "GREEN", "gender": "male", "title": "Mr.Green", "info": "Mr.Green, male", "added": "some boy attr"}} \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/normal_2/stdout.golden.json b/kclvm/runner/src/test_datas/normal_2/stdout.golden.json index 9958766ac..c9f63ad19 100644 --- a/kclvm/runner/src/test_datas/normal_2/stdout.golden.json +++ b/kclvm/runner/src/test_datas/normal_2/stdout.golden.json @@ -1 +1 @@ -{"numMap":{"0":0,"2":2,"__settings__":{"__schema_type__":"__main__.NumberMap","output_type":"INLINE"}}} \ No newline at end of file +{"numMap":{"0":0,"2":2}} \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/settings_file/settings.json b/kclvm/runner/src/test_datas/settings_file/settings.json index 1edf02279..b3567f2ea 100644 --- a/kclvm/runner/src/test_datas/settings_file/settings.json +++ b/kclvm/runner/src/test_datas/settings_file/settings.json @@ -1 +1 @@ -{"work_dir":null,"k_filename_list":["../main.k","./before/base.k","./main.k","./sub/sub.k"],"external_pkgs":[],"k_code_list":[],"args":[{"name":"app-name","value":"\"kclvm\""},{"name":"image","value":"\"kclvm:v0.0.1\""}],"overrides":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"include_schema_type_path":false} \ No newline at end of file +{"work_dir":null,"k_filename_list":["../main.k","./before/base.k","./main.k","./sub/sub.k"],"external_pkgs":[],"k_code_list":[],"args":[{"name":"app-name","value":"\"kclvm\""},{"name":"image","value":"\"kclvm:v0.0.1\""}],"overrides":[],"path_selector":[],"disable_yaml_result":false,"print_override_ast":false,"strict_range_check":false,"disable_none":false,"verbose":0,"debug":0,"sort_keys":false,"show_hidden":false,"include_schema_type_path":false,"compile_only":false} \ No newline at end of file diff --git a/kclvm/runner/src/test_datas/type_annotation_not_full_2/stdout.golden.json b/kclvm/runner/src/test_datas/type_annotation_not_full_2/stdout.golden.json index 310d018aa..c200367c8 100644 --- a/kclvm/runner/src/test_datas/type_annotation_not_full_2/stdout.golden.json +++ b/kclvm/runner/src/test_datas/type_annotation_not_full_2/stdout.golden.json @@ -1 +1 @@ -{"a1":{"__settings__":{"__schema_type__":"__main__.A","output_type":"INLINE"},"a":1},"a2":{"__settings__":{"__schema_type__":"__main__.A","output_type":"INLINE"},"a":2},"a3":{"__settings__":{"__schema_type__":"__main__.A","output_type":"INLINE"},"a":3}} \ No newline at end of file +{"a1":{"a":1},"a2":{"a":2},"a3":{"a":3}} \ No newline at end of file diff --git a/kclvm/runner/src/test_file_pattern/kcl1/kcl.mod b/kclvm/runner/src/test_file_pattern/kcl1/kcl.mod new file mode 100644 index 000000000..ab572545d --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl1/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl1" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/runner/src/test_file_pattern/kcl1/kcl3/kcl.mod b/kclvm/runner/src/test_file_pattern/kcl1/kcl3/kcl.mod new file mode 100644 index 000000000..b99124970 --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl1/kcl3/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl3" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/runner/src/test_file_pattern/kcl1/kcl3/main.k b/kclvm/runner/src/test_file_pattern/kcl1/kcl3/main.k new file mode 100644 index 000000000..0acce2f52 --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl1/kcl3/main.k @@ -0,0 +1 @@ +k3 = 'Hello World!' \ No newline at end of file diff --git a/kclvm/runner/src/test_file_pattern/kcl1/main.k b/kclvm/runner/src/test_file_pattern/kcl1/main.k new file mode 100644 index 000000000..ac6689514 --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl1/main.k @@ -0,0 +1 @@ +k1 = 'Hello World!' \ No newline at end of file diff --git a/kclvm/runner/src/test_file_pattern/kcl2/kcl.mod b/kclvm/runner/src/test_file_pattern/kcl2/kcl.mod new file mode 100644 index 000000000..5fb058acd --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl2/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "kcl2" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/runner/src/test_file_pattern/kcl2/main.k b/kclvm/runner/src/test_file_pattern/kcl2/main.k new file mode 100644 index 000000000..fe6900bb4 --- /dev/null +++ b/kclvm/runner/src/test_file_pattern/kcl2/main.k @@ -0,0 +1 @@ +k2 = 'Hello World!' \ No newline at end of file diff --git a/kclvm/runner/src/test_indent_error/if_indent_err.k b/kclvm/runner/src/test_indent_error/if_indent_err.k new file mode 100644 index 000000000..04c753795 --- /dev/null +++ b/kclvm/runner/src/test_indent_error/if_indent_err.k @@ -0,0 +1,4 @@ +_a = True +if _a : + a = 1 + b = 1 \ No newline at end of file diff --git a/kclvm/runner/src/test_indent_error/if_indent_err.stderr b/kclvm/runner/src/test_indent_error/if_indent_err.stderr new file mode 100644 index 000000000..9e60cd8c5 --- /dev/null +++ b/kclvm/runner/src/test_indent_error/if_indent_err.stderr @@ -0,0 +1 @@ +invalid indentation with 1 space, try to align indents by adding or removing spaces \ No newline at end of file diff --git a/kclvm/runner/src/test_indent_error/schema_indent_err.k b/kclvm/runner/src/test_indent_error/schema_indent_err.k new file mode 100644 index 000000000..2bd207d0d --- /dev/null +++ b/kclvm/runner/src/test_indent_error/schema_indent_err.k @@ -0,0 +1,11 @@ +schema MySchema: + metadata: {str:} = {} + metadata1: {str:} = {} + +metadata.environment = "dev" + + +output = MySchema { + metadata.environment = "qa" + metadata.name = "config" +} diff --git a/kclvm/runner/src/test_indent_error/schema_indent_err.stderr b/kclvm/runner/src/test_indent_error/schema_indent_err.stderr new file mode 100644 index 000000000..9e60cd8c5 --- /dev/null +++ b/kclvm/runner/src/test_indent_error/schema_indent_err.stderr @@ -0,0 +1 @@ +invalid indentation with 1 space, try to align indents by adding or removing spaces \ No newline at end of file diff --git a/kclvm/runner/src/test_uuid/main.k b/kclvm/runner/src/test_uuid/main.k new file mode 100644 index 000000000..caec6bd4f --- /dev/null +++ b/kclvm/runner/src/test_uuid/main.k @@ -0,0 +1,3 @@ +import crypto + +a = crypto.uuid() \ No newline at end of file diff --git a/kclvm/runner/src/tests.rs b/kclvm/runner/src/tests.rs index 8e53c2a52..9431dc7c0 100644 --- a/kclvm/runner/src/tests.rs +++ b/kclvm/runner/src/tests.rs @@ -13,6 +13,7 @@ use kclvm_config::settings::load_file; use kclvm_parser::load_program; use kclvm_parser::ParseSession; use kclvm_sema::resolver::resolve_program; +use serde_json::Value; use std::fs::create_dir_all; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -22,6 +23,7 @@ use std::{ fs::{self, File}, }; use tempfile::tempdir; +use uuid::Uuid; use walkdir::WalkDir; const MULTI_FILE_TEST_CASES: &[&str; 5] = &[ @@ -140,7 +142,7 @@ fn gen_full_path(rel_path: String) -> Result { /// Load test kcl file to ast.Program fn load_test_program(filename: String) -> Program { - let module = kclvm_parser::parse_file(&filename, None).unwrap(); + let module = kclvm_parser::parse_file_force_errors(&filename, None).unwrap(); construct_program(module) } @@ -151,22 +153,22 @@ fn parse_program(test_kcl_case_path: &str) -> Program { Arc::new(ParseSession::default()), &[test_kcl_case_path], Some(opts), + None, ) .unwrap() + .program } /// Construct ast.Program by ast.Module and default configuration. /// Default configuration: /// module.pkg = "__main__" /// Program.root = "__main__" -/// Program.main = "__main__" fn construct_program(mut module: Module) -> Program { module.pkg = MAIN_PKG_NAME.to_string(); let mut pkgs_ast = HashMap::new(); pkgs_ast.insert(MAIN_PKG_NAME.to_string(), vec![module]); Program { root: MAIN_PKG_NAME.to_string(), - main: MAIN_PKG_NAME.to_string(), pkgs: pkgs_ast, } } @@ -207,7 +209,9 @@ fn execute_for_test(kcl_path: &String) -> String { // Parse kcl file let program = load_test_program(kcl_path.to_string()); // Generate libs, link libs and execute. - execute(Arc::new(ParseSession::default()), program, &args).unwrap() + execute(Arc::new(ParseSession::default()), program, &args) + .unwrap() + .json_result } fn gen_assembler(entry_file: &str, test_kcl_case_path: &str) -> KclvmAssembler { @@ -232,7 +236,7 @@ fn gen_libs_for_test(entry_file: &str, test_kcl_case_path: &str) { OBJECT_FILE_SUFFIX.to_string(), ); - let lib_paths = assembler.gen_libs().unwrap(); + let lib_paths = assembler.gen_libs(&ExecProgramArgs::default()).unwrap(); assert_eq!(lib_paths.len(), expected_pkg_paths.len()); @@ -261,7 +265,9 @@ fn assemble_lib_for_test( let opts = args.get_load_program_options(); let sess = Arc::new(ParseSession::default()); // parse and resolve kcl - let mut program = load_program(sess, &files, Some(opts)).unwrap(); + let mut program = load_program(sess, &files, Some(opts), None) + .unwrap() + .program; let scope = resolve_program(&mut program); @@ -275,6 +281,7 @@ fn assemble_lib_for_test( scope.import_names, entry_file, temp_entry_file_path, + &ExecProgramArgs::default(), ) .unwrap() } @@ -479,9 +486,6 @@ fn test_from_setting_file_program_arg() { } fn test_exec_file() { - let prev_hook = std::panic::take_hook(); - // disable print panic info - std::panic::set_hook(Box::new(|_| {})); let result = std::panic::catch_unwind(|| { for file in get_files(exec_data_path(), false, true, ".k") { exec(&file).unwrap(); @@ -489,7 +493,6 @@ fn test_exec_file() { } }); assert!(result.is_ok()); - std::panic::set_hook(prev_hook); } fn test_custom_manifests_output() { @@ -538,6 +541,32 @@ fn test_exec() { test_exec_with_err_result(); println!("test_exec_with_err_result - PASS"); + + test_indent_error(); + println!("test_indent_error - PASS"); + + test_compile_with_file_pattern(); + println!("test_compile_with_file_pattern - PASS"); + + test_uuid(); + println!("test_uuid - PASS"); +} + +fn test_indent_error() { + let test_path = PathBuf::from("./src/test_indent_error"); + let kcl_files = get_files(test_path.clone(), false, true, ".k"); + let output_files = get_files(test_path, false, true, ".stderr"); + + for (kcl_file, err_file) in kcl_files.iter().zip(&output_files) { + let mut args = ExecProgramArgs::default(); + args.k_filename_list.push(kcl_file.to_string()); + let res = exec_program(Arc::new(ParseSession::default()), &args); + assert!(res.is_err()); + if let Err(err_msg) = res { + let expect_err = fs::read_to_string(err_file).expect("Failed to read file"); + assert!(err_msg.to_string().contains(&expect_err)); + } + } } fn exec(file: &str) -> Result { @@ -546,9 +575,20 @@ fn exec(file: &str) -> Result { let opts = args.get_load_program_options(); let sess = Arc::new(ParseSession::default()); // Load AST program - let program = load_program(sess.clone(), &[file], Some(opts)).unwrap(); + let program = load_program(sess.clone(), &[file], Some(opts), None) + .unwrap() + .program; // Resolve ATS, generate libs, link libs and execute. - execute(sess, program, &args) + match execute(sess, program, &args) { + Ok(result) => { + if result.err_message.is_empty() { + Ok(result.json_result) + } else { + Err(result.err_message) + } + } + Err(err) => Err(err.to_string()), + } } /// Run all kcl files at path and compare the exec result with the expect output. @@ -574,7 +614,11 @@ fn exec_with_result_at(path: &str) { #[cfg(target_os = "windows")] let expected = expected.replace("\r\n", "\n"); - assert_eq!(result.yaml_result, expected); + assert_eq!( + result.yaml_result, expected, + "test case {} {} failed", + path, kcl_file + ); } } @@ -590,7 +634,12 @@ fn exec_with_err_result_at(path: &str) { for (kcl_file, _) in kcl_files.iter().zip(&output_files) { let mut args = ExecProgramArgs::default(); args.k_filename_list.push(kcl_file.to_string()); - assert!(exec_program(Arc::new(ParseSession::default()), &args).is_err()); + let result = exec_program(Arc::new(ParseSession::default()), &args); + if let Ok(result) = result { + assert!(!result.err_message.is_empty(), "{}", result.err_message); + } else { + assert!(result.is_err()); + } } }); assert!(result.is_ok()); @@ -619,3 +668,38 @@ fn get_files>( } files } + +fn test_compile_with_file_pattern() { + let test_path = PathBuf::from("./src/test_file_pattern/**/main.k"); + let mut args = ExecProgramArgs::default(); + args.k_filename_list.push(test_path.display().to_string()); + let res = exec_program(Arc::new(ParseSession::default()), &args); + assert!(res.is_ok()); + assert_eq!( + res.as_ref().unwrap().yaml_result, + "k3: Hello World!\nk1: Hello World!\nk2: Hello World!" + ); + assert_eq!( + res.as_ref().unwrap().json_result, + "{\"k3\": \"Hello World!\", \"k1\": \"Hello World!\", \"k2\": \"Hello World!\"}" + ); +} + +fn test_uuid() { + let res = exec( + &PathBuf::from(".") + .join("src") + .join("test_uuid") + .join("main.k") + .canonicalize() + .unwrap() + .display() + .to_string(), + ); + + let v: Value = serde_json::from_str(res.clone().unwrap().as_str()).unwrap(); + assert!(v["a"].as_str().is_some()); + if let Some(uuid_str) = v["a"].as_str() { + assert!(Uuid::parse_str(uuid_str).is_ok()); + } +} diff --git a/kclvm/runtime/Cargo.toml b/kclvm/runtime/Cargo.toml index 53dabf8c3..6fc47c3b0 100644 --- a/kclvm/runtime/Cargo.toml +++ b/kclvm/runtime/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "kclvm-runtime" -version = "0.5.0" +version = "0.8.1" edition = "2021" [dependencies] kclvm_runtime_internal_macros = { path = "./internal_macros" } serde_json = {package = "serde_json", version = "= 1.0.86"} serde = { version = "1", features = ["derive"] } -serde_yaml = "0.8.23" +serde_yaml = "0.9.32" base64 = "0.13.0" libc = "0.2.112" @@ -26,3 +26,5 @@ indexmap = "1.0" phf = { version = "0.9", features = ["macros"] } fancy-regex = "0.7.1" num-integer = "0.1.44" +glob = "0.3.0" +uuid = { version = "1.7.0", features = ["serde", "v4"] } diff --git a/kclvm/runtime/internal_macros/src/lib.rs b/kclvm/runtime/internal_macros/src/lib.rs index 26f445474..2a7ea763b 100644 --- a/kclvm/runtime/internal_macros/src/lib.rs +++ b/kclvm/runtime/internal_macros/src/lib.rs @@ -19,6 +19,7 @@ pub fn runtime_fn(_attr: TokenStream, item: TokenStream) -> TokenStream { } // ---------------------------------------------------------------------------- +#[allow(clippy::upper_case_acronyms)] #[derive(Debug)] enum TargetName { C, diff --git a/kclvm/runtime/src/_kcl_run.rs b/kclvm/runtime/src/_kcl_run.rs index 7e8d6b2a5..52b7b45d8 100644 --- a/kclvm/runtime/src/_kcl_run.rs +++ b/kclvm/runtime/src/_kcl_run.rs @@ -1,42 +1,84 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #![allow(clippy::missing_safety_doc)] -use crate::*; +use std::os::raw::c_char; -#[allow(dead_code, non_camel_case_types)] -pub type kclvm_buffer_t = Buffer; +use crate::*; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_context_t = Context; +type kclvm_context_t = Context; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_kind_t = Kind; +type kclvm_kind_t = Kind; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_type_t = Type; +type kclvm_type_t = Type; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_value_ref_t = ValueRef; +type kclvm_value_ref_t = ValueRef; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_iterator_t = ValueIterator; +type kclvm_iterator_t = ValueIterator; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_char_t = i8; +type kclvm_char_t = c_char; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_size_t = i32; +type kclvm_size_t = i32; #[allow(dead_code, non_camel_case_types)] type kclvm_bool_t = i8; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_int_t = i64; +type kclvm_int_t = i64; #[allow(dead_code, non_camel_case_types)] -pub type kclvm_float_t = f64; +type kclvm_float_t = f64; + +#[derive(Debug, Default)] +pub(crate) struct RuntimePanicRecord { + pub kcl_panic_info: bool, + pub message: String, + pub rust_file: String, + pub rust_line: i32, + pub rust_col: i32, +} + +#[derive(Debug, Default, Clone, Copy)] +#[repr(C)] +pub struct FFIRunOptions { + pub strict_range_check: i32, + pub disable_none: i32, + pub disable_schema_check: i32, + pub list_option_mode: i32, + pub debug_mode: i32, + pub show_hidden: i32, + pub sort_keys: i32, + pub include_schema_type_path: i32, + pub disable_empty_list: i32, +} -// const SHOULD_PROFILE: bool = false; +thread_local! { + static KCL_RUNTIME_PANIC_RECORD: std::cell::RefCell = std::cell::RefCell::new(RuntimePanicRecord::default()) +} + +fn new_ctx_with_opts(opts: FFIRunOptions, path_selector: &[String]) -> Context { + let mut ctx = Context::new(); + // Config + ctx.cfg.strict_range_check = opts.strict_range_check != 0; + ctx.cfg.disable_schema_check = opts.disable_schema_check != 0; + ctx.cfg.disable_schema_check = opts.disable_schema_check != 0; + ctx.cfg.list_option_mode = opts.list_option_mode != 0; + ctx.cfg.debug_mode = opts.debug_mode != 0; + // Plan options + ctx.plan_opts.disable_none = opts.disable_none != 0; + ctx.plan_opts.show_hidden = opts.show_hidden != 0; + ctx.plan_opts.sort_keys = opts.sort_keys != 0; + ctx.plan_opts.include_schema_type_path = opts.include_schema_type_path != 0; + ctx.plan_opts.disable_empty_list = opts.disable_empty_list != 0; + ctx.plan_opts.query_paths = path_selector.to_vec(); + ctx +} #[no_mangle] #[runtime_fn] @@ -45,134 +87,91 @@ pub unsafe extern "C" fn _kcl_run( option_len: kclvm_size_t, option_keys: *const *const kclvm_char_t, option_values: *const *const kclvm_char_t, - strict_range_check: i32, - disable_none: i32, - disable_schema_check: i32, - list_option_mode: i32, - debug_mode: i32, - result_buffer_len: kclvm_size_t, - result_buffer: *mut kclvm_char_t, - warn_buffer_len: kclvm_size_t, - warn_buffer: *mut kclvm_char_t, + opts: FFIRunOptions, + path_selector: *const *const kclvm_char_t, + json_result_buffer_len: *mut kclvm_size_t, + json_result_buffer: *mut kclvm_char_t, + yaml_result_buffer_len: *mut kclvm_size_t, + yaml_result_buffer: *mut kclvm_char_t, + err_buffer_len: *mut kclvm_size_t, + err_buffer: *mut kclvm_char_t, + log_buffer_len: *mut kclvm_size_t, + log_buffer: *mut kclvm_char_t, ) -> kclvm_size_t { - let ctx = kclvm_context_new(); - + // Init runtime context with options + let ctx = Box::new(new_ctx_with_opts(opts, &c2str_vec(path_selector))).into_raw(); + let option_keys = std::slice::from_raw_parts(option_keys, option_len as usize); + let option_values = std::slice::from_raw_parts(option_values, option_len as usize); + for i in 0..(option_len as usize) { + kclvm_builtin_option_init(ctx, option_keys[i], option_values[i]); + } let prev_hook = std::panic::take_hook(); std::panic::set_hook(Box::new(|info: &std::panic::PanicInfo| { - let ctx = Context::current_context_mut(); - ctx.set_panic_info(info); - let _ = ctx; + KCL_RUNTIME_PANIC_RECORD.with(|record| { + let mut record = record.borrow_mut(); + record.kcl_panic_info = true; + + record.message = if let Some(s) = info.payload().downcast_ref::<&str>() { + s.to_string() + } else if let Some(s) = info.payload().downcast_ref::<&String>() { + (*s).clone() + } else if let Some(s) = info.payload().downcast_ref::() { + (*s).clone() + } else { + "".to_string() + }; + if let Some(location) = info.location() { + record.rust_file = location.file().to_string(); + record.rust_line = location.line() as i32; + record.rust_col = location.column() as i32; + } + }) })); - - let result = std::panic::catch_unwind(|| { - _kcl_run_in_closure( - kclvm_main_ptr, - option_len, - option_keys, - option_values, - strict_range_check, - disable_none, - disable_schema_check, - list_option_mode, - debug_mode, - result_buffer_len, - result_buffer, - ) - }); + let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, kclvm_main_ptr)); std::panic::set_hook(prev_hook); - match result { - Ok(n) => { - let json_panic_info = Context::current_context().get_panic_info_json_string(); - - let c_str_ptr = json_panic_info.as_ptr() as *const i8; - let c_str_len = json_panic_info.len() as i32; - - unsafe { - if c_str_len <= warn_buffer_len { - std::ptr::copy(c_str_ptr, warn_buffer, c_str_len as usize); - } - } - - kclvm_context_delete(ctx); - n - } - Err(_) => { - let json_panic_info = Context::current_context().get_panic_info_json_string(); - - let c_str_ptr = json_panic_info.as_ptr() as *const i8; - let c_str_len = json_panic_info.len() as i32; - - let mut return_len = c_str_len; - - unsafe { - if return_len <= result_buffer_len { - std::ptr::copy(c_str_ptr, result_buffer, return_len as usize); - } else { - *result_buffer = '\0' as kclvm_char_t; - return_len = 0 - return_len; - } - } - - kclvm_context_delete(ctx); - return_len - } - } + KCL_RUNTIME_PANIC_RECORD.with(|record| { + let record = record.borrow(); + let ctx = mut_ptr_as_ref(ctx); + ctx.set_panic_info(&record); + }); + // Get the runtime context. + let ctx_ref = ptr_as_ref(ctx); + // Copy planned result and log message + copy_str_to( + &ctx_ref.json_result, + json_result_buffer, + json_result_buffer_len, + ); + copy_str_to( + &ctx_ref.yaml_result, + yaml_result_buffer, + yaml_result_buffer_len, + ); + copy_str_to(&ctx_ref.log_message, log_buffer, log_buffer_len); + // Copy JSON panic info message pointer + let json_panic_info = if result.is_err() { + ctx_ref.get_panic_info_json_string().unwrap_or_default() + } else { + "".to_string() + }; + copy_str_to(&json_panic_info, err_buffer, err_buffer_len); + // Delete the context + kclvm_context_delete(ctx); + result.is_err() as kclvm_size_t } #[allow(clippy::too_many_arguments)] unsafe fn _kcl_run_in_closure( + ctx: *mut Context, kclvm_main_ptr: u64, // main.k => kclvm_main - option_len: kclvm_size_t, - option_keys: *const *const kclvm_char_t, - option_values: *const *const kclvm_char_t, - strict_range_check: i32, - disable_none: i32, - disable_schema_check: i32, - list_option_mode: i32, - debug_mode: i32, - result_buffer_len: kclvm_size_t, - result_buffer: *mut kclvm_char_t, -) -> kclvm_size_t { - let ctx = kclvm_context_current(); - +) { let kclvm_main = (&kclvm_main_ptr as *const u64) as *const () as *const extern "C" fn(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t; - kclvm_context_set_strict_range_check(ctx, strict_range_check as kclvm_bool_t); - kclvm_context_set_disable_none(ctx, disable_none as kclvm_bool_t); - kclvm_context_set_disable_schema_check(ctx, disable_schema_check as kclvm_bool_t); - kclvm_context_set_list_option_mode(ctx, list_option_mode as kclvm_bool_t); - kclvm_context_set_debug_mode(ctx, debug_mode as kclvm_bool_t); - unsafe { - let option_keys = std::slice::from_raw_parts(option_keys, option_len as usize); - let option_values = std::slice::from_raw_parts(option_values, option_len as usize); - - for i in 0..(option_len as usize) { - kclvm_builtin_option_init(ctx, option_keys[i], option_values[i]); - } - - let value = if kclvm_main.is_null() { - kclvm_value_Str(b"{}\0" as *const u8 as *const kclvm_char_t) - } else { - kclvm_context_main_begin_hook(ctx); - let x = (*kclvm_main)(ctx); - kclvm_context_main_end_hook(ctx, x) - }; - - let c_str_ptr = kclvm_value_Str_ptr(value); - let c_str_len = kclvm_value_len(value); - - let mut return_len = c_str_len; - - if return_len <= result_buffer_len { - std::ptr::copy(c_str_ptr, result_buffer, return_len as usize); - } else { - *result_buffer = '\0' as kclvm_char_t; - return_len = 0 - return_len; + if kclvm_main.is_null() { + panic!("kcl program main function not found"); } - - // Delete by context to ignore pointer double free. - return_len + (*kclvm_main)(ctx); } } diff --git a/kclvm/runtime/src/_kclvm.bc b/kclvm/runtime/src/_kclvm.bc index bc168956a..167a95684 100644 Binary files a/kclvm/runtime/src/_kclvm.bc and b/kclvm/runtime/src/_kclvm.bc differ diff --git a/kclvm/runtime/src/_kclvm.h b/kclvm/runtime/src/_kclvm.h index a6da2e9e1..fe2c4af74 100644 --- a/kclvm/runtime/src/_kclvm.h +++ b/kclvm/runtime/src/_kclvm.h @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -64,6 +64,8 @@ typedef struct kclvm_context_t kclvm_context_t; typedef struct kclvm_decorator_value_t kclvm_decorator_value_t; +typedef struct kclvm_eval_scope_t kclvm_eval_scope_t; + typedef double kclvm_float_t; typedef int64_t kclvm_int_t; @@ -80,161 +82,137 @@ typedef struct kclvm_value_ref_t kclvm_value_ref_t; typedef struct kclvm_value_t kclvm_value_t; -void kclvm_assert(kclvm_value_ref_t* value, kclvm_value_ref_t* msg); - -kclvm_value_ref_t* kclvm_base64_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); - -kclvm_value_ref_t* kclvm_base64_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); - -kclvm_char_t* kclvm_buffer_data(kclvm_buffer_t* p); +void kclvm_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_value_ref_t* msg); -void kclvm_buffer_delete(kclvm_buffer_t* p); +kclvm_value_ref_t* kclvm_base64_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_buffer_t* kclvm_buffer_new(kclvm_size_t size); +kclvm_value_ref_t* kclvm_base64_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_size_t kclvm_buffer_size(kclvm_buffer_t* p); +kclvm_value_ref_t* kclvm_builtin_abs(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_abs(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); - -kclvm_value_ref_t* kclvm_builtin_all_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_all_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_any_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_bin(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_bin(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_bool(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_bool(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_dict(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); kclvm_value_ref_t* kclvm_builtin_float(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_hex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_hex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_int(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_isunique(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_isunique(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_len(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_len(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_list(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_list(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_max(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_max(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_min(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_min(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_multiplyof(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_multiplyof(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_oct(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_oct(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_option(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -void kclvm_builtin_option_init(kclvm_context_t* ctx, int8_t* key, int8_t* value); +void kclvm_builtin_option_init(kclvm_context_t* ctx, char* key, char* value); kclvm_value_ref_t* kclvm_builtin_option_reset(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_ord(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_ord(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_print(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_range(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_range(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_round(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_round(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_sorted(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_str(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_capitalize(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_capitalize(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_count(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_count(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_endswith(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_endswith(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_find(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_find(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_format(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_str_format(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_str_index(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_index(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_isalnum(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_isalnum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_isalpha(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_isalpha(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_isdigit(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_isdigit(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_islower(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_islower(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_isspace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_isspace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_istitle(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_istitle(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_isupper(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_isupper(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_join(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_join(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_lower(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_lower(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_lstrip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_lstrip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_removeprefix(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_removeprefix(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_removesuffix(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_removesuffix(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_replace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_replace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_rfind(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_rfind(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_rindex(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_rindex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_rsplit(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_str_rsplit(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_str_rstrip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_rstrip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_split(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_str_split(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_str_splitlines(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_str_splitlines(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_str_startswith(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_startswith(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_strip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_strip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_title(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_title(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_str_upper(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_builtin_str_upper(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_builtin_sum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_sum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_builtin_typeof(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_builtin_zip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_builtin_zip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); void kclvm_config_attr_map(kclvm_value_ref_t* value, kclvm_char_t* name, kclvm_char_t* type_str); -void kclvm_context_args_clear(kclvm_context_t* p); - -kclvm_char_t* kclvm_context_args_get(kclvm_context_t* _p, kclvm_char_t* _key); - -void kclvm_context_args_set(kclvm_context_t* _p, kclvm_char_t* _key, kclvm_char_t* _value); - -void kclvm_context_clear_all_types(kclvm_context_t* p); - -kclvm_context_t* kclvm_context_current(); - void kclvm_context_delete(kclvm_context_t* p); char* kclvm_context_invoke(kclvm_context_t* p, char* method, char* args, char* kwargs); -void kclvm_context_main_begin_hook(kclvm_context_t* p); - -kclvm_value_ref_t* kclvm_context_main_end_hook(kclvm_context_t* p, kclvm_value_ref_t* return_value); - kclvm_context_t* kclvm_context_new(); -kclvm_bool_t kclvm_context_pkgpath_is_imported(kclvm_char_t* pkgpath); - -void kclvm_context_put_type(kclvm_context_t* p, kclvm_type_t* typ); +kclvm_bool_t kclvm_context_pkgpath_is_imported(kclvm_context_t* ctx, kclvm_char_t* pkgpath); void kclvm_context_set_debug_mode(kclvm_context_t* p, kclvm_bool_t v); @@ -244,47 +222,47 @@ void kclvm_context_set_disable_schema_check(kclvm_context_t* p, kclvm_bool_t v); void kclvm_context_set_import_names(kclvm_context_t* p, kclvm_value_ref_t* import_names); -void kclvm_context_set_kcl_filename(int8_t* filename); +void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, char* filename); -void kclvm_context_set_kcl_line_col(int32_t line, int32_t col); +void kclvm_context_set_kcl_line_col(kclvm_context_t* ctx, int32_t line, int32_t col); -void kclvm_context_set_kcl_location(kclvm_context_t* p, int8_t* filename, int32_t line, int32_t col); +void kclvm_context_set_kcl_location(kclvm_context_t* p, char* filename, int32_t line, int32_t col); -void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, int8_t* pkgpath); +void kclvm_context_set_kcl_modpath(kclvm_context_t* p, char* module_path); -void kclvm_context_set_list_option_mode(kclvm_context_t* p, kclvm_bool_t v); +void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, char* pkgpath); -void kclvm_context_set_strict_range_check(kclvm_context_t* p, kclvm_bool_t v); +void kclvm_context_set_kcl_workdir(kclvm_context_t* p, char* workdir); -void kclvm_context_symbol_init(kclvm_context_t* p, kclvm_size_t n, kclvm_char_t** symbol_names); +void kclvm_context_set_list_option_mode(kclvm_context_t* p, kclvm_bool_t v); -kclvm_char_t* kclvm_context_symbol_name(kclvm_context_t* p, kclvm_size_t i); +void kclvm_context_set_strict_range_check(kclvm_context_t* p, kclvm_bool_t v); -kclvm_size_t kclvm_context_symbol_num(kclvm_context_t* p); +kclvm_value_ref_t* kclvm_convert_collection_value(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_char_t* tpe, kclvm_value_ref_t* is_in_schema); -kclvm_value_t* kclvm_context_symbol_value(kclvm_context_t* p, kclvm_size_t i); +kclvm_value_ref_t* kclvm_crypto_filesha256(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_convert_collection_value(kclvm_value_ref_t* value, kclvm_char_t* tpe, kclvm_value_ref_t* is_in_schema); +kclvm_value_ref_t* kclvm_crypto_md5(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_md5(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_sha1(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_sha1(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_sha224(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_sha224(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_sha256(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_sha256(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_sha384(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_sha384(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_sha512(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_crypto_sha512(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_crypto_uuid(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_datetime_date(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_datetime_date(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_datetime_now(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_datetime_now(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_datetime_ticks(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_datetime_ticks(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_datetime_today(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_datetime_today(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); void kclvm_default_collection_insert_int_pointer(kclvm_value_ref_t* p, kclvm_char_t* key, uint64_t* ptr); @@ -292,41 +270,49 @@ void kclvm_default_collection_insert_value(kclvm_value_ref_t* p, kclvm_char_t* k void kclvm_dict_clear(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_dict_get(kclvm_value_ref_t* p, kclvm_value_ref_t* key); +kclvm_value_ref_t* kclvm_dict_get(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* key); -kclvm_value_ref_t* kclvm_dict_get_entry(kclvm_value_ref_t* p, kclvm_char_t* key); +kclvm_value_ref_t* kclvm_dict_get_entry(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); -kclvm_value_ref_t* kclvm_dict_get_value(kclvm_value_ref_t* p, kclvm_char_t* key); +kclvm_value_ref_t* kclvm_dict_get_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); -kclvm_value_ref_t* kclvm_dict_get_value_by_path(kclvm_value_ref_t* p, kclvm_char_t* path); +kclvm_value_ref_t* kclvm_dict_get_value_by_path(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* path); kclvm_bool_t kclvm_dict_has_value(kclvm_value_ref_t* p, kclvm_char_t* key); -void kclvm_dict_insert(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +void kclvm_dict_insert(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -void kclvm_dict_insert_unpack(kclvm_value_ref_t* p, kclvm_value_ref_t* v); +void kclvm_dict_insert_unpack(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* v); -void kclvm_dict_insert_value(kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +void kclvm_dict_insert_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -kclvm_value_ref_t* kclvm_dict_keys(kclvm_value_ref_t* p); +kclvm_bool_t kclvm_dict_is_override_attr(kclvm_value_ref_t* p, kclvm_char_t* key); + +kclvm_value_ref_t* kclvm_dict_keys(kclvm_context_t* ctx, kclvm_value_ref_t* p); kclvm_size_t kclvm_dict_len(kclvm_value_ref_t* p); -void kclvm_dict_merge(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +void kclvm_dict_merge(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); void kclvm_dict_remove(kclvm_value_ref_t* p, kclvm_char_t* key); -void kclvm_dict_safe_insert(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +void kclvm_dict_safe_insert(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -void kclvm_dict_set_value(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* val); +void kclvm_dict_set_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* val); void kclvm_dict_update(kclvm_value_ref_t* p, kclvm_value_ref_t* v); void kclvm_dict_update_key_value(kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v); -kclvm_value_ref_t* kclvm_dict_values(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_dict_values(kclvm_context_t* ctx, kclvm_value_ref_t* p); + +kclvm_value_ref_t* kclvm_file_glob(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); + +kclvm_value_ref_t* kclvm_file_modpath(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -void kclvm_free(uint8_t* ptr); +kclvm_value_ref_t* kclvm_file_read(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); + +kclvm_value_ref_t* kclvm_file_workdir(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_iterator_cur_key(kclvm_iterator_t* p); @@ -338,11 +324,13 @@ kclvm_bool_t kclvm_iterator_is_end(kclvm_iterator_t* p); kclvm_value_ref_t* kclvm_iterator_next_value(kclvm_iterator_t* p, kclvm_value_ref_t* host); -kclvm_value_ref_t* kclvm_json_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_json_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); + +kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_json_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_json_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_json_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); void kclvm_list_append(kclvm_value_ref_t* p, kclvm_value_ref_t* v); @@ -358,21 +346,21 @@ void kclvm_list_append_unpack(kclvm_value_ref_t* p, kclvm_value_ref_t* v); void kclvm_list_clear(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_list_count(kclvm_value_ref_t* p, kclvm_value_ref_t* item); +kclvm_value_ref_t* kclvm_list_count(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* item); -kclvm_value_ref_t* kclvm_list_find(kclvm_value_ref_t* p, kclvm_value_ref_t* item); +kclvm_value_ref_t* kclvm_list_find(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* item); -kclvm_value_ref_t* kclvm_list_get(kclvm_value_ref_t* p, kclvm_size_t i); +kclvm_value_ref_t* kclvm_list_get(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_size_t i); -kclvm_value_ref_t* kclvm_list_get_option(kclvm_value_ref_t* p, kclvm_size_t i); +kclvm_value_ref_t* kclvm_list_get_option(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_size_t i); void kclvm_list_insert(kclvm_value_ref_t* p, kclvm_value_ref_t* index, kclvm_value_ref_t* value); kclvm_size_t kclvm_list_len(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_list_pop(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_list_pop(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_list_pop_first(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_list_pop_first(kclvm_context_t* ctx, kclvm_value_ref_t* p); void kclvm_list_remove_at(kclvm_value_ref_t* p, kclvm_size_t i); @@ -380,69 +368,67 @@ void kclvm_list_resize(kclvm_value_ref_t* p, kclvm_size_t newsize); void kclvm_list_set(kclvm_value_ref_t* p, kclvm_size_t i, kclvm_value_ref_t* v); -uint8_t* kclvm_malloc(int32_t n); - void kclvm_manifests_yaml_stream(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_math_ceil(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_ceil(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_exp(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_exp(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_expm1(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_expm1(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_factorial(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_factorial(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_floor(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_floor(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_gcd(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_gcd(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_isfinite(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_isfinite(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_isinf(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_isinf(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_isnan(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_isnan(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_log(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_log(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_log10(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_log10(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_log1p(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_log1p(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_log2(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_log2(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_modf(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_modf(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_pow(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_math_sqrt(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_math_sqrt(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_IP_string(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_IP_string(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_net_fqdn(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_IPv4(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_IPv4(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_global_unicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_global_unicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_interface_local_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_interface_local_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_link_local_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_link_local_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_net_is_link_local_unicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_net_is_loopback_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_loopback_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_is_unspecified_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_is_unspecified_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_net_join_host_port(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_join_host_port(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_net_parse_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_net_split_host_port(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_net_split_host_port(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_net_to_IP16(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); @@ -450,305 +436,259 @@ kclvm_value_ref_t* kclvm_net_to_IP4(kclvm_context_t* ctx, kclvm_value_ref_t* arg void kclvm_plugin_init(void* fn_ptr); -kclvm_value_ref_t* kclvm_plugin_invoke(int8_t* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, char* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -char* kclvm_plugin_invoke_json(int8_t* method, char* args, char* kwargs); +char* kclvm_plugin_invoke_json(char* method, char* args, char* kwargs); -kclvm_value_ref_t* kclvm_regex_compile(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_compile(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_regex_findall(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_findall(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_regex_match(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_match(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_regex_replace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_replace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_regex_search(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_search(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_regex_split(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_regex_split(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -void kclvm_schema_assert(kclvm_value_ref_t* value, kclvm_value_ref_t* msg, kclvm_value_ref_t* config_meta); +void kclvm_schema_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_value_ref_t* msg, kclvm_value_ref_t* config_meta); -void kclvm_schema_backtrack_cache(kclvm_value_ref_t* schema, kclvm_value_ref_t* cache, kclvm_value_ref_t* cal_map, kclvm_char_t* name, kclvm_value_ref_t* runtime_type); +void kclvm_schema_backtrack_cache(kclvm_context_t* ctx, kclvm_value_ref_t* schema, kclvm_value_ref_t* cache, kclvm_value_ref_t* cal_map, kclvm_char_t* name, kclvm_value_ref_t* runtime_type); -void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* config_value, kclvm_char_t* runtime_type); +void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* runtime_type); void kclvm_schema_do_check_with_index_sign_attr(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, uint64_t* check_fn_ptr, kclvm_char_t* attr_name); -kclvm_value_ref_t* kclvm_schema_get_value(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_value_ref_t* cal_map, kclvm_char_t* target_attr, kclvm_value_ref_t* backtrack_level_map, kclvm_value_ref_t* backtrack_cache, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_schema_get_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_value_ref_t* cal_map, kclvm_char_t* target_attr, kclvm_value_ref_t* backtrack_level_map, kclvm_value_ref_t* backtrack_cache, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); kclvm_value_ref_t* kclvm_schema_instances(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -void kclvm_schema_optional_check(kclvm_value_ref_t* p); +void kclvm_schema_optional_check(kclvm_context_t* ctx, kclvm_value_ref_t* p); -void kclvm_schema_value_check(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* schema_config, kclvm_value_ref_t* _config_meta, kclvm_char_t* schema_name, kclvm_value_ref_t* index_sign_value, kclvm_char_t* key_name, kclvm_char_t* key_type, kclvm_char_t* value_type, kclvm_bool_t _any_other); +void kclvm_schema_value_check(kclvm_context_t* ctx, kclvm_value_ref_t* schema_value, kclvm_value_ref_t* schema_config, kclvm_value_ref_t* _config_meta, kclvm_char_t* schema_name, kclvm_value_ref_t* index_sign_value, kclvm_char_t* key_name, kclvm_char_t* key_type, kclvm_char_t* value_type, kclvm_bool_t _any_other); kclvm_value_ref_t* kclvm_schema_value_new(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* schema_value_or_func, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* pkgpath); -kclvm_size_t kclvm_strlen(uint8_t* ptr); - -void kclvm_testing_arguments(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); - -void kclvm_testing_setting_file(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); - -kclvm_bool_t kclvm_type_BoolLit_value(kclvm_type_t* p); +void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter); -double kclvm_type_FloatLit_value(kclvm_type_t* p); +void kclvm_scope_free(kclvm_eval_scope_t* scope); -int64_t kclvm_type_IntLit_value(kclvm_type_t* p); +kclvm_value_ref_t* kclvm_scope_get(kclvm_context_t* ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, char* target, kclvm_value_ref_t* default); -kclvm_char_t* kclvm_type_StrLit_value(kclvm_type_t* p); +kclvm_eval_scope_t* kclvm_scope_new(); -kclvm_size_t kclvm_type_arg_num(kclvm_type_t* p); +void kclvm_scope_set(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, kclvm_value_ref_t* value); -kclvm_type_t* kclvm_type_arg_type(kclvm_type_t* p, kclvm_size_t i); +kclvm_value_ref_t* kclvm_units_to_G(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -void kclvm_type_delete(kclvm_type_t* p); +kclvm_value_ref_t* kclvm_units_to_Gi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_type_t* kclvm_type_elem_type(kclvm_type_t* p); +kclvm_value_ref_t* kclvm_units_to_K(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_type_t* kclvm_type_key_type(kclvm_type_t* p); - -kclvm_kind_t kclvm_type_kind(kclvm_type_t* p); - -kclvm_type_t* kclvm_type_return_type(kclvm_type_t* p); - -kclvm_char_t* kclvm_type_schema_field_name(kclvm_type_t* p, kclvm_size_t i); - -kclvm_size_t kclvm_type_schema_field_num(kclvm_type_t* p); - -kclvm_type_t* kclvm_type_schema_field_type(kclvm_type_t* p, kclvm_size_t i); - -kclvm_char_t* kclvm_type_schema_name(kclvm_type_t* p); - -kclvm_char_t* kclvm_type_schema_parent_name(kclvm_type_t* p); - -kclvm_bool_t kclvm_type_schema_relaxed(kclvm_type_t* p); - -kclvm_kind_t kclvm_type_str(kclvm_type_t* p); - -kclvm_value_ref_t* kclvm_units_to_G(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); - -kclvm_value_ref_t* kclvm_units_to_Gi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); - -kclvm_value_ref_t* kclvm_units_to_K(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); - -kclvm_value_ref_t* kclvm_units_to_Ki(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_Ki(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); kclvm_value_ref_t* kclvm_units_to_M(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_units_to_Mi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_Mi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_P(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_P(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_Pi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_Pi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_T(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_T(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_Ti(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_Ti(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_m(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_m(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_n(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_n(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_units_to_u(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_units_to_u(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_value_Bool(kclvm_bool_t v); +kclvm_value_ref_t* kclvm_value_Bool(kclvm_context_t* ctx, kclvm_bool_t v); -kclvm_bool_t* kclvm_value_Bool_ptr(kclvm_value_ref_t* p); +kclvm_decorator_value_t* kclvm_value_Decorator(kclvm_context_t* ctx, kclvm_char_t* name, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* config_meta, kclvm_char_t* attr_name, kclvm_value_ref_t* config_value, kclvm_value_ref_t* is_schema_target); -kclvm_decorator_value_t* kclvm_value_Decorator(kclvm_char_t* name, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* config_meta, kclvm_char_t* attr_name, kclvm_value_ref_t* config_value, kclvm_value_ref_t* is_schema_target); +kclvm_value_ref_t* kclvm_value_Dict(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_Dict(); +kclvm_value_ref_t* kclvm_value_False(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_False(); +kclvm_value_ref_t* kclvm_value_Float(kclvm_context_t* ctx, kclvm_float_t v); -kclvm_value_ref_t* kclvm_value_Float(kclvm_float_t v); +kclvm_value_ref_t* kclvm_value_Function(kclvm_context_t* ctx, uint64_t* fn_ptr, kclvm_value_ref_t* closure, kclvm_char_t* name, kclvm_bool_t is_external); -kclvm_float_t* kclvm_value_Float_ptr(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_Function_using_ptr(kclvm_context_t* ctx, uint64_t* fn_ptr, kclvm_char_t* name); -kclvm_value_ref_t* kclvm_value_Function(uint64_t* fn_ptr, kclvm_value_ref_t* closure, kclvm_char_t* name, kclvm_bool_t is_external); +kclvm_value_ref_t* kclvm_value_Int(kclvm_context_t* ctx, kclvm_int_t v); -kclvm_value_ref_t* kclvm_value_Function_using_ptr(uint64_t* fn_ptr, kclvm_char_t* name); +kclvm_value_ref_t* kclvm_value_List(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_Int(kclvm_int_t v); +kclvm_value_ref_t* kclvm_value_List10(kclvm_context_t* ctx, kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6, kclvm_value_ref_t* v7, kclvm_value_ref_t* v8, kclvm_value_ref_t* v9, kclvm_value_ref_t* v10); -kclvm_int_t* kclvm_value_Int_ptr(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_List6(kclvm_context_t* ctx, kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6); -kclvm_value_ref_t* kclvm_value_List(); +kclvm_value_ref_t* kclvm_value_None(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_List10(kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6, kclvm_value_ref_t* v7, kclvm_value_ref_t* v8, kclvm_value_ref_t* v9, kclvm_value_ref_t* v10); +kclvm_value_ref_t* kclvm_value_Schema(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_List6(kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6); - -kclvm_value_ref_t* kclvm_value_ListN(kclvm_int_t n, kclvm_value_ref_t** elem_values); - -kclvm_value_ref_t* kclvm_value_None(); - -kclvm_value_ref_t* kclvm_value_Schema(); - -kclvm_value_ref_t* kclvm_value_Str(kclvm_char_t* v); - -kclvm_size_t kclvm_value_Str_len(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_Str(kclvm_context_t* ctx, kclvm_char_t* v); kclvm_char_t* kclvm_value_Str_ptr(kclvm_value_ref_t* p); -void kclvm_value_Str_resize(kclvm_value_ref_t* p, kclvm_size_t n); - -kclvm_value_ref_t* kclvm_value_True(); +kclvm_value_ref_t* kclvm_value_True(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_Undefined(); +kclvm_value_ref_t* kclvm_value_Undefined(kclvm_context_t* ctx); -kclvm_value_ref_t* kclvm_value_Unit(kclvm_float_t v, kclvm_int_t raw, kclvm_char_t* unit); +kclvm_value_ref_t* kclvm_value_Unit(kclvm_context_t* ctx, kclvm_float_t v, kclvm_int_t raw, kclvm_char_t* unit); -kclvm_value_ref_t* kclvm_value_as(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_as(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); uint64_t* kclvm_value_check_function_ptr(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_cmp_equal_to(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_equal_to(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_cmp_greater_than(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_greater_than(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_cmp_greater_than_or_equal(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_greater_than_or_equal(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_cmp_less_than(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_less_than(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_cmp_less_than_or_equal(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_less_than_or_equal(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_cmp_not_equal_to(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_cmp_not_equal_to(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_deep_copy(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_deep_copy(kclvm_context_t* ctx, kclvm_value_ref_t* p); void kclvm_value_delete(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_from_json(kclvm_char_t* s); - -kclvm_value_ref_t* kclvm_value_function_external_invoke(kclvm_value_ref_t* p, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); - -kclvm_value_ref_t* kclvm_value_function_get_closure(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_from_json(kclvm_context_t* ctx, kclvm_char_t* s); kclvm_value_ref_t* kclvm_value_function_invoke(kclvm_value_ref_t* p, kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_in_schema); -kclvm_bool_t kclvm_value_function_is_external(kclvm_value_ref_t* p); - uint64_t* kclvm_value_function_ptr(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_in(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_in(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_is(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_is(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_is_not(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_is_not(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); kclvm_bool_t kclvm_value_is_truthy(kclvm_value_ref_t* p); kclvm_iterator_t* kclvm_value_iter(kclvm_value_ref_t* p); -kclvm_kind_t kclvm_value_kind(kclvm_value_ref_t* p); - kclvm_size_t kclvm_value_len(kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_load_attr(kclvm_value_ref_t* obj, kclvm_char_t* key); +kclvm_value_ref_t* kclvm_value_load_attr(kclvm_context_t* ctx, kclvm_value_ref_t* obj, kclvm_char_t* key); -kclvm_value_ref_t* kclvm_value_load_attr_option(kclvm_value_ref_t* p, kclvm_char_t* key); +kclvm_value_ref_t* kclvm_value_load_attr_option(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); -kclvm_value_ref_t* kclvm_value_logic_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_logic_and(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_logic_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_logic_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_not_in(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_not_in(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_add(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_add(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_add(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_add(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_bit_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_bit_and(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_bit_lshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_bit_lshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_bit_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_bit_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_bit_rshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_bit_rshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_bit_xor(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_bit_xor(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_div(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_floor_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_floor_div(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_mod(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_mod(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_mul(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_mul(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_pow(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_pow(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_aug_sub(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_aug_sub(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_bit_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_bit_and(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_bit_lshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_bit_lshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_bit_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_bit_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_bit_rshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_bit_rshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_bit_xor(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_bit_xor(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_div(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_floor_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_floor_div(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_mod(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_mod(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_mul(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_mul(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_pow(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_pow(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_op_sub(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_op_sub(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_plan_to_json(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_plan_to_json(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_plan_to_yaml(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_plan_to_yaml(kclvm_context_t* ctx, kclvm_value_ref_t* p); void kclvm_value_remove_item(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_schema_function(uint64_t* fn_ptr, uint64_t* check_fn_ptr, kclvm_char_t* tpe); +kclvm_value_ref_t* kclvm_value_schema_function(kclvm_context_t* ctx, uint64_t* fn_ptr, uint64_t* check_fn_ptr, kclvm_value_ref_t* attr_map, kclvm_char_t* tpe); + +kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); + +kclvm_value_ref_t* kclvm_value_slice(kclvm_context_t* ctx, kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); + +kclvm_value_ref_t* kclvm_value_slice_option(kclvm_context_t* ctx, kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); -kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping); +kclvm_value_ref_t* kclvm_value_subscr(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_slice(kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); +kclvm_value_ref_t* kclvm_value_subscr_option(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_slice_option(kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); +kclvm_value_ref_t* kclvm_value_to_json_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_subscr(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_to_json_value_with_null(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_subscr_option(kclvm_value_ref_t* a, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_value_to_str_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_buffer_t* kclvm_value_to_json(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_to_yaml_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); -kclvm_value_ref_t* kclvm_value_to_json_value(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_unary_l_not(kclvm_context_t* ctx, kclvm_value_ref_t* a); -kclvm_value_ref_t* kclvm_value_to_json_value_with_null(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_unary_minus(kclvm_context_t* ctx, kclvm_value_ref_t* a); -kclvm_value_ref_t* kclvm_value_to_str_value(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_unary_not(kclvm_context_t* ctx, kclvm_value_ref_t* a); -kclvm_value_ref_t* kclvm_value_to_yaml_value(kclvm_value_ref_t* p); +kclvm_value_ref_t* kclvm_value_unary_plus(kclvm_context_t* ctx, kclvm_value_ref_t* a); -kclvm_value_ref_t* kclvm_value_unary_l_not(kclvm_value_ref_t* a); +kclvm_value_ref_t* kclvm_value_union(kclvm_context_t* ctx, kclvm_value_ref_t* schema, kclvm_value_ref_t* b); -kclvm_value_ref_t* kclvm_value_unary_minus(kclvm_value_ref_t* a); +kclvm_value_ref_t* kclvm_value_union_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_value_unary_not(kclvm_value_ref_t* a); +kclvm_value_ref_t* kclvm_yaml_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_value_unary_plus(kclvm_value_ref_t* a); +kclvm_value_ref_t* kclvm_yaml_decode_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_value_union(kclvm_value_ref_t* schema, kclvm_value_ref_t* b); +kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_value_union_all(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_yaml_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_yaml_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +kclvm_value_ref_t* kclvm_yaml_encode_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_yaml_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_yaml_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); #ifdef __cplusplus } // extern "C" diff --git a/kclvm/runtime/src/_kclvm.ll b/kclvm/runtime/src/_kclvm.ll index 1e7aa628c..6c6140f1e 100644 --- a/kclvm/runtime/src/_kclvm.ll +++ b/kclvm/runtime/src/_kclvm.ll @@ -1,4 +1,4 @@ -; Copyright 2021 The KCL Authors. All rights reserved. +; Copyright The KCL Authors. All rights reserved. ; Auto generated, DONOT EDIT!!! @@ -12,6 +12,8 @@ %"kclvm_decorator_value_t" = type opaque +%"kclvm_eval_scope_t" = type { i8* } + %"kclvm_float_t" = type double %"kclvm_int_t" = type i64 @@ -28,51 +30,43 @@ %"kclvm_value_t" = type { i8* } -declare void @kclvm_assert(%kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg); - -declare %kclvm_value_ref_t* @kclvm_base64_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); - -declare %kclvm_value_ref_t* @kclvm_base64_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); - -declare %kclvm_char_t* @kclvm_buffer_data(%kclvm_buffer_t* %p); +declare void @kclvm_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg); -declare void @kclvm_buffer_delete(%kclvm_buffer_t* %p); +declare %kclvm_value_ref_t* @kclvm_base64_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_buffer_t* @kclvm_buffer_new(%kclvm_size_t %size); +declare %kclvm_value_ref_t* @kclvm_base64_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_size_t @kclvm_buffer_size(%kclvm_buffer_t* %p); +declare %kclvm_value_ref_t* @kclvm_builtin_abs(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_abs(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - -declare %kclvm_value_ref_t* @kclvm_builtin_all_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_all_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_any_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_bin(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_bin(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_bool(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_bool(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_dict(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_float(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_hex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_hex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_int(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_isunique(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_isunique(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_len(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_len(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_list(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_list(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_max(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_max(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_min(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_min(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_multiplyof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_multiplyof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_oct(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_oct(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); @@ -80,109 +74,93 @@ declare void @kclvm_builtin_option_init(%kclvm_context_t* %ctx, i8* %key, i8* %v declare %kclvm_value_ref_t* @kclvm_builtin_option_reset(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_ord(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_ord(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_print(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_range(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_range(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_round(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_round(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_sorted(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_capitalize(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_capitalize(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_count(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_count(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_endswith(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_endswith(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_find(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_find(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_format(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_format(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_index(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_index(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_isalnum(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_isalnum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_isalpha(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_isalpha(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_isdigit(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_isdigit(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_islower(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_islower(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_isspace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_isspace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_istitle(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_istitle(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_isupper(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_isupper(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_join(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_join(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_lower(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_lower(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_lstrip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_lstrip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_removeprefix(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_removeprefix(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_removesuffix(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_removesuffix(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_replace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_replace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_rfind(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_rfind(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_rindex(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_rindex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_rsplit(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_rsplit(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_rstrip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_rstrip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_split(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_split(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_splitlines(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_splitlines(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_startswith(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_startswith(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_strip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_strip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_title(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_title(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_str_upper(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_str_upper(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_sum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_sum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_builtin_typeof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_builtin_zip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_builtin_zip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare void @kclvm_config_attr_map(%kclvm_value_ref_t* %value, %kclvm_char_t* %name, %kclvm_char_t* %type_str); -declare void @kclvm_context_args_clear(%kclvm_context_t* %p); - -declare %kclvm_char_t* @kclvm_context_args_get(%kclvm_context_t* %_p, %kclvm_char_t* %_key); - -declare void @kclvm_context_args_set(%kclvm_context_t* %_p, %kclvm_char_t* %_key, %kclvm_char_t* %_value); - -declare void @kclvm_context_clear_all_types(%kclvm_context_t* %p); - -declare %kclvm_context_t* @kclvm_context_current(); - declare void @kclvm_context_delete(%kclvm_context_t* %p); declare i8* @kclvm_context_invoke(%kclvm_context_t* %p, i8* %method, i8* %args, i8* %kwargs); -declare void @kclvm_context_main_begin_hook(%kclvm_context_t* %p); - -declare %kclvm_value_ref_t* @kclvm_context_main_end_hook(%kclvm_context_t* %p, %kclvm_value_ref_t* %return_value); - declare %kclvm_context_t* @kclvm_context_new(); -declare %kclvm_bool_t @kclvm_context_pkgpath_is_imported(%kclvm_char_t* %pkgpath); - -declare void @kclvm_context_put_type(%kclvm_context_t* %p, %kclvm_type_t* %typ); +declare %kclvm_bool_t @kclvm_context_pkgpath_is_imported(%kclvm_context_t* %ctx, %kclvm_char_t* %pkgpath); declare void @kclvm_context_set_debug_mode(%kclvm_context_t* %p, %kclvm_bool_t %v); @@ -192,47 +170,47 @@ declare void @kclvm_context_set_disable_schema_check(%kclvm_context_t* %p, %kclv declare void @kclvm_context_set_import_names(%kclvm_context_t* %p, %kclvm_value_ref_t* %import_names); -declare void @kclvm_context_set_kcl_filename(i8* %filename); +declare void @kclvm_context_set_kcl_filename(%kclvm_context_t* %ctx, i8* %filename); -declare void @kclvm_context_set_kcl_line_col(i32 %line, i32 %col); +declare void @kclvm_context_set_kcl_line_col(%kclvm_context_t* %ctx, i32 %line, i32 %col); declare void @kclvm_context_set_kcl_location(%kclvm_context_t* %p, i8* %filename, i32 %line, i32 %col); +declare void @kclvm_context_set_kcl_modpath(%kclvm_context_t* %p, i8* %module_path); + declare void @kclvm_context_set_kcl_pkgpath(%kclvm_context_t* %p, i8* %pkgpath); +declare void @kclvm_context_set_kcl_workdir(%kclvm_context_t* %p, i8* %workdir); + declare void @kclvm_context_set_list_option_mode(%kclvm_context_t* %p, %kclvm_bool_t %v); declare void @kclvm_context_set_strict_range_check(%kclvm_context_t* %p, %kclvm_bool_t %v); -declare void @kclvm_context_symbol_init(%kclvm_context_t* %p, %kclvm_size_t %n, %kclvm_char_t** %symbol_names); - -declare %kclvm_char_t* @kclvm_context_symbol_name(%kclvm_context_t* %p, %kclvm_size_t %i); - -declare %kclvm_size_t @kclvm_context_symbol_num(%kclvm_context_t* %p); +declare %kclvm_value_ref_t* @kclvm_convert_collection_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_char_t* %tpe, %kclvm_value_ref_t* %is_in_schema); -declare %kclvm_value_t* @kclvm_context_symbol_value(%kclvm_context_t* %p, %kclvm_size_t %i); +declare %kclvm_value_ref_t* @kclvm_crypto_filesha256(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_convert_collection_value(%kclvm_value_ref_t* %value, %kclvm_char_t* %tpe, %kclvm_value_ref_t* %is_in_schema); +declare %kclvm_value_ref_t* @kclvm_crypto_md5(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_md5(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_sha1(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_sha1(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_sha224(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_sha224(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_sha256(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_sha256(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_sha384(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_sha384(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_sha512(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_crypto_sha512(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_crypto_uuid(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_datetime_date(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_datetime_date(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_datetime_now(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_datetime_now(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_datetime_ticks(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_datetime_ticks(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_datetime_today(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_datetime_today(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); declare void @kclvm_default_collection_insert_int_pointer(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, i64* %ptr); @@ -240,41 +218,49 @@ declare void @kclvm_default_collection_insert_value(%kclvm_value_ref_t* %p, %kcl declare void @kclvm_dict_clear(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_dict_get(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key); +declare %kclvm_value_ref_t* @kclvm_dict_get(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key); -declare %kclvm_value_ref_t* @kclvm_dict_get_entry(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +declare %kclvm_value_ref_t* @kclvm_dict_get_entry(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); -declare %kclvm_value_ref_t* @kclvm_dict_get_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +declare %kclvm_value_ref_t* @kclvm_dict_get_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); -declare %kclvm_value_ref_t* @kclvm_dict_get_value_by_path(%kclvm_value_ref_t* %p, %kclvm_char_t* %path); +declare %kclvm_value_ref_t* @kclvm_dict_get_value_by_path(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %path); declare %kclvm_bool_t @kclvm_dict_has_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); -declare void @kclvm_dict_insert(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +declare void @kclvm_dict_insert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); -declare void @kclvm_dict_insert_unpack(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); +declare void @kclvm_dict_insert_unpack(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); -declare void @kclvm_dict_insert_value(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +declare void @kclvm_dict_insert_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); -declare %kclvm_value_ref_t* @kclvm_dict_keys(%kclvm_value_ref_t* %p); +declare %kclvm_bool_t @kclvm_dict_is_override_attr(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); + +declare %kclvm_value_ref_t* @kclvm_dict_keys(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); declare %kclvm_size_t @kclvm_dict_len(%kclvm_value_ref_t* %p); -declare void @kclvm_dict_merge(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +declare void @kclvm_dict_merge(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); declare void @kclvm_dict_remove(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); -declare void @kclvm_dict_safe_insert(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +declare void @kclvm_dict_safe_insert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); -declare void @kclvm_dict_set_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %val); +declare void @kclvm_dict_set_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %val); declare void @kclvm_dict_update(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); declare void @kclvm_dict_update_key_value(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v); -declare %kclvm_value_ref_t* @kclvm_dict_values(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_dict_values(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); + +declare %kclvm_value_ref_t* @kclvm_file_glob(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +declare %kclvm_value_ref_t* @kclvm_file_modpath(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); -declare void @kclvm_free(i8* %ptr); +declare %kclvm_value_ref_t* @kclvm_file_read(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +declare %kclvm_value_ref_t* @kclvm_file_workdir(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_iterator_cur_key(%kclvm_iterator_t* %p); @@ -286,11 +272,13 @@ declare %kclvm_bool_t @kclvm_iterator_is_end(%kclvm_iterator_t* %p); declare %kclvm_value_ref_t* @kclvm_iterator_next_value(%kclvm_iterator_t* %p, %kclvm_value_ref_t* %host); -declare %kclvm_value_ref_t* @kclvm_json_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_json_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_json_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_json_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_json_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare void @kclvm_list_append(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); @@ -306,21 +294,21 @@ declare void @kclvm_list_append_unpack(%kclvm_value_ref_t* %p, %kclvm_value_ref_ declare void @kclvm_list_clear(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_list_count(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); +declare %kclvm_value_ref_t* @kclvm_list_count(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); -declare %kclvm_value_ref_t* @kclvm_list_find(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); +declare %kclvm_value_ref_t* @kclvm_list_find(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); -declare %kclvm_value_ref_t* @kclvm_list_get(%kclvm_value_ref_t* %p, %kclvm_size_t %i); +declare %kclvm_value_ref_t* @kclvm_list_get(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_size_t %i); -declare %kclvm_value_ref_t* @kclvm_list_get_option(%kclvm_value_ref_t* %p, %kclvm_size_t %i); +declare %kclvm_value_ref_t* @kclvm_list_get_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_size_t %i); declare void @kclvm_list_insert(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %index, %kclvm_value_ref_t* %value); declare %kclvm_size_t @kclvm_list_len(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_list_pop(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_list_pop(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_list_pop_first(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_list_pop_first(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); declare void @kclvm_list_remove_at(%kclvm_value_ref_t* %p, %kclvm_size_t %i); @@ -328,69 +316,67 @@ declare void @kclvm_list_resize(%kclvm_value_ref_t* %p, %kclvm_size_t %newsize); declare void @kclvm_list_set(%kclvm_value_ref_t* %p, %kclvm_size_t %i, %kclvm_value_ref_t* %v); -declare i8* @kclvm_malloc(i32 %n); - declare void @kclvm_manifests_yaml_stream(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_math_ceil(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_ceil(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_exp(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_exp(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_expm1(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_expm1(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_factorial(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_factorial(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_floor(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_floor(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_gcd(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_gcd(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_isfinite(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_isfinite(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_isinf(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_isinf(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_isnan(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_isnan(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_log(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_log(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_log10(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_log10(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_log1p(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_log1p(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_log2(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_log2(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_modf(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_modf(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_pow(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_math_sqrt(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_math_sqrt(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_IP_string(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_IP_string(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_net_fqdn(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_IPv4(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_IPv4(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_global_unicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_global_unicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_interface_local_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_interface_local_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_link_local_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_link_local_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_net_is_link_local_unicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_loopback_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_loopback_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_is_unspecified_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_is_unspecified_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_net_join_host_port(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_join_host_port(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_net_parse_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_net_split_host_port(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_net_split_host_port(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_net_to_IP16(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); @@ -398,307 +384,261 @@ declare %kclvm_value_ref_t* @kclvm_net_to_IP4(%kclvm_context_t* %ctx, %kclvm_val declare void @kclvm_plugin_init(i8* %fn_ptr); -declare %kclvm_value_ref_t* @kclvm_plugin_invoke(i8* %method, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_plugin_invoke(%kclvm_context_t* %ctx, i8* %method, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare i8* @kclvm_plugin_invoke_json(i8* %method, i8* %args, i8* %kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_compile(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_compile(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_findall(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_findall(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_match(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_match(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_replace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_replace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_search(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_search(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_regex_split(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_regex_split(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare void @kclvm_schema_assert(%kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg, %kclvm_value_ref_t* %config_meta); +declare void @kclvm_schema_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg, %kclvm_value_ref_t* %config_meta); -declare void @kclvm_schema_backtrack_cache(%kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %cache, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %name, %kclvm_value_ref_t* %runtime_type); +declare void @kclvm_schema_backtrack_cache(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %cache, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %name, %kclvm_value_ref_t* %runtime_type); -declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %config_value, %kclvm_char_t* %runtime_type); +declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %runtime_type); declare void @kclvm_schema_do_check_with_index_sign_attr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, i64* %check_fn_ptr, %kclvm_char_t* %attr_name); -declare %kclvm_value_ref_t* @kclvm_schema_get_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %target_attr, %kclvm_value_ref_t* %backtrack_level_map, %kclvm_value_ref_t* %backtrack_cache, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_schema_get_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %target_attr, %kclvm_value_ref_t* %backtrack_level_map, %kclvm_value_ref_t* %backtrack_cache, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare %kclvm_value_ref_t* @kclvm_schema_instances(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare void @kclvm_schema_optional_check(%kclvm_value_ref_t* %p); +declare void @kclvm_schema_optional_check(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare void @kclvm_schema_value_check(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %schema_config, %kclvm_value_ref_t* %_config_meta, %kclvm_char_t* %schema_name, %kclvm_value_ref_t* %index_sign_value, %kclvm_char_t* %key_name, %kclvm_char_t* %key_type, %kclvm_char_t* %value_type, %kclvm_bool_t %_any_other); +declare void @kclvm_schema_value_check(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %schema_config, %kclvm_value_ref_t* %_config_meta, %kclvm_char_t* %schema_name, %kclvm_value_ref_t* %index_sign_value, %kclvm_char_t* %key_name, %kclvm_char_t* %key_type, %kclvm_char_t* %value_type, %kclvm_bool_t %_any_other); declare %kclvm_value_ref_t* @kclvm_schema_value_new(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %schema_value_or_func, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %pkgpath); -declare %kclvm_size_t @kclvm_strlen(i8* %ptr); - -declare void @kclvm_testing_arguments(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); - -declare void @kclvm_testing_setting_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); - -declare %kclvm_bool_t @kclvm_type_BoolLit_value(%kclvm_type_t* %p); +declare void @kclvm_scope_add_setter(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i64* %setter); -declare double @kclvm_type_FloatLit_value(%kclvm_type_t* %p); +declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope); -declare i64 @kclvm_type_IntLit_value(%kclvm_type_t* %p); +declare %kclvm_value_ref_t* @kclvm_scope_get(%kclvm_context_t* %ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i8* %target, %kclvm_value_ref_t* %default); -declare %kclvm_char_t* @kclvm_type_StrLit_value(%kclvm_type_t* %p); +declare %kclvm_eval_scope_t* @kclvm_scope_new(); -declare %kclvm_size_t @kclvm_type_arg_num(%kclvm_type_t* %p); +declare void @kclvm_scope_set(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, %kclvm_value_ref_t* %value); -declare %kclvm_type_t* @kclvm_type_arg_type(%kclvm_type_t* %p, %kclvm_size_t %i); +declare %kclvm_value_ref_t* @kclvm_units_to_G(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare void @kclvm_type_delete(%kclvm_type_t* %p); +declare %kclvm_value_ref_t* @kclvm_units_to_Gi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_type_t* @kclvm_type_elem_type(%kclvm_type_t* %p); +declare %kclvm_value_ref_t* @kclvm_units_to_K(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_type_t* @kclvm_type_key_type(%kclvm_type_t* %p); - -declare %kclvm_kind_t @kclvm_type_kind(%kclvm_type_t* %p); - -declare %kclvm_type_t* @kclvm_type_return_type(%kclvm_type_t* %p); - -declare %kclvm_char_t* @kclvm_type_schema_field_name(%kclvm_type_t* %p, %kclvm_size_t %i); - -declare %kclvm_size_t @kclvm_type_schema_field_num(%kclvm_type_t* %p); - -declare %kclvm_type_t* @kclvm_type_schema_field_type(%kclvm_type_t* %p, %kclvm_size_t %i); - -declare %kclvm_char_t* @kclvm_type_schema_name(%kclvm_type_t* %p); - -declare %kclvm_char_t* @kclvm_type_schema_parent_name(%kclvm_type_t* %p); - -declare %kclvm_bool_t @kclvm_type_schema_relaxed(%kclvm_type_t* %p); - -declare %kclvm_kind_t @kclvm_type_str(%kclvm_type_t* %p); - -declare %kclvm_value_ref_t* @kclvm_units_to_G(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - -declare %kclvm_value_ref_t* @kclvm_units_to_Gi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - -declare %kclvm_value_ref_t* @kclvm_units_to_K(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - -declare %kclvm_value_ref_t* @kclvm_units_to_Ki(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_Ki(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); declare %kclvm_value_ref_t* @kclvm_units_to_M(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_Mi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_Mi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_P(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_P(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_Pi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_Pi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_T(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_T(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_Ti(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_Ti(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_m(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_m(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_n(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_n(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_units_to_u(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_units_to_u(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_value_Bool(%kclvm_bool_t %v); +declare %kclvm_value_ref_t* @kclvm_value_Bool(%kclvm_context_t* %ctx, %kclvm_bool_t %v); -declare %kclvm_bool_t* @kclvm_value_Bool_ptr(%kclvm_value_ref_t* %p); +declare %kclvm_decorator_value_t* @kclvm_value_Decorator(%kclvm_context_t* %ctx, %kclvm_char_t* %name, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %attr_name, %kclvm_value_ref_t* %config_value, %kclvm_value_ref_t* %is_schema_target); -declare %kclvm_decorator_value_t* @kclvm_value_Decorator(%kclvm_char_t* %name, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %attr_name, %kclvm_value_ref_t* %config_value, %kclvm_value_ref_t* %is_schema_target); +declare %kclvm_value_ref_t* @kclvm_value_Dict(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_Dict(); +declare %kclvm_value_ref_t* @kclvm_value_False(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_False(); +declare %kclvm_value_ref_t* @kclvm_value_Float(%kclvm_context_t* %ctx, %kclvm_float_t %v); -declare %kclvm_value_ref_t* @kclvm_value_Float(%kclvm_float_t %v); +declare %kclvm_value_ref_t* @kclvm_value_Function(%kclvm_context_t* %ctx, i64* %fn_ptr, %kclvm_value_ref_t* %closure, %kclvm_char_t* %name, %kclvm_bool_t %is_external); -declare %kclvm_float_t* @kclvm_value_Float_ptr(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_Function_using_ptr(%kclvm_context_t* %ctx, i64* %fn_ptr, %kclvm_char_t* %name); -declare %kclvm_value_ref_t* @kclvm_value_Function(i64* %fn_ptr, %kclvm_value_ref_t* %closure, %kclvm_char_t* %name, %kclvm_bool_t %is_external); +declare %kclvm_value_ref_t* @kclvm_value_Int(%kclvm_context_t* %ctx, %kclvm_int_t %v); -declare %kclvm_value_ref_t* @kclvm_value_Function_using_ptr(i64* %fn_ptr, %kclvm_char_t* %name); +declare %kclvm_value_ref_t* @kclvm_value_List(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_Int(%kclvm_int_t %v); +declare %kclvm_value_ref_t* @kclvm_value_List10(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6, %kclvm_value_ref_t* %v7, %kclvm_value_ref_t* %v8, %kclvm_value_ref_t* %v9, %kclvm_value_ref_t* %v10); -declare %kclvm_int_t* @kclvm_value_Int_ptr(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_List6(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6); -declare %kclvm_value_ref_t* @kclvm_value_List(); +declare %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_List10(%kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6, %kclvm_value_ref_t* %v7, %kclvm_value_ref_t* %v8, %kclvm_value_ref_t* %v9, %kclvm_value_ref_t* %v10); +declare %kclvm_value_ref_t* @kclvm_value_Schema(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_List6(%kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6); - -declare %kclvm_value_ref_t* @kclvm_value_ListN(%kclvm_int_t %n, %kclvm_value_ref_t** %elem_values); - -declare %kclvm_value_ref_t* @kclvm_value_None(); - -declare %kclvm_value_ref_t* @kclvm_value_Schema(); - -declare %kclvm_value_ref_t* @kclvm_value_Str(%kclvm_char_t* %v); - -declare %kclvm_size_t @kclvm_value_Str_len(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_Str(%kclvm_context_t* %ctx, %kclvm_char_t* %v); declare %kclvm_char_t* @kclvm_value_Str_ptr(%kclvm_value_ref_t* %p); -declare void @kclvm_value_Str_resize(%kclvm_value_ref_t* %p, %kclvm_size_t %n); - -declare %kclvm_value_ref_t* @kclvm_value_True(); +declare %kclvm_value_ref_t* @kclvm_value_True(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_Undefined(); +declare %kclvm_value_ref_t* @kclvm_value_Undefined(%kclvm_context_t* %ctx); -declare %kclvm_value_ref_t* @kclvm_value_Unit(%kclvm_float_t %v, %kclvm_int_t %raw, %kclvm_char_t* %unit); +declare %kclvm_value_ref_t* @kclvm_value_Unit(%kclvm_context_t* %ctx, %kclvm_float_t %v, %kclvm_int_t %raw, %kclvm_char_t* %unit); -declare %kclvm_value_ref_t* @kclvm_value_as(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_as(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); declare i64* @kclvm_value_check_function_ptr(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_cmp_equal_to(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_equal_to(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than_or_equal(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than_or_equal(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than_or_equal(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than_or_equal(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_cmp_not_equal_to(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_cmp_not_equal_to(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_deep_copy(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_deep_copy(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); declare void @kclvm_value_delete(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_from_json(%kclvm_char_t* %s); - -declare %kclvm_value_ref_t* @kclvm_value_function_external_invoke(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - -declare %kclvm_value_ref_t* @kclvm_value_function_get_closure(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_from_json(%kclvm_context_t* %ctx, %kclvm_char_t* %s); declare %kclvm_value_ref_t* @kclvm_value_function_invoke(%kclvm_value_ref_t* %p, %kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_in_schema); -declare %kclvm_bool_t @kclvm_value_function_is_external(%kclvm_value_ref_t* %p); - declare i64* @kclvm_value_function_ptr(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_in(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_in(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_is(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_is(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_is_not(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_is_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); declare %kclvm_bool_t @kclvm_value_is_truthy(%kclvm_value_ref_t* %p); declare %kclvm_iterator_t* @kclvm_value_iter(%kclvm_value_ref_t* %p); -declare %kclvm_kind_t @kclvm_value_kind(%kclvm_value_ref_t* %p); - declare %kclvm_size_t @kclvm_value_len(%kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_load_attr(%kclvm_value_ref_t* %obj, %kclvm_char_t* %key); +declare %kclvm_value_ref_t* @kclvm_value_load_attr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %obj, %kclvm_char_t* %key); -declare %kclvm_value_ref_t* @kclvm_value_load_attr_option(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +declare %kclvm_value_ref_t* @kclvm_value_load_attr_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); -declare %kclvm_value_ref_t* @kclvm_value_logic_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_logic_and(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_logic_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_logic_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_not_in(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_not_in(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_add(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_add(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_add(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_add(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_and(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_lshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_lshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_rshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_rshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_xor(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_xor(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_div(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_floor_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_floor_div(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_mod(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_mod(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_mul(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_mul(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_pow(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_aug_sub(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_aug_sub(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_bit_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_bit_and(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_bit_lshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_bit_lshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_bit_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_bit_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_bit_rshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_bit_rshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_bit_xor(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_bit_xor(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_div(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_floor_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_floor_div(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_mod(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_mod(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_mul(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_mul(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_pow(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_op_sub(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_op_sub(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_plan_to_json(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_plan_to_json(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_plan_to_yaml(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_plan_to_yaml(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); declare void @kclvm_value_remove_item(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_schema_function(i64* %fn_ptr, i64* %check_fn_ptr, %kclvm_char_t* %tpe); +declare %kclvm_value_ref_t* @kclvm_value_schema_function(%kclvm_context_t* %ctx, i64* %fn_ptr, i64* %check_fn_ptr, %kclvm_value_ref_t* %attr_map, %kclvm_char_t* %tpe); + +declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); + +declare %kclvm_value_ref_t* @kclvm_value_slice(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); + +declare %kclvm_value_ref_t* @kclvm_value_slice_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); -declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping); +declare %kclvm_value_ref_t* @kclvm_value_subscr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_slice(%kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); +declare %kclvm_value_ref_t* @kclvm_value_subscr_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_slice_option(%kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); +declare %kclvm_value_ref_t* @kclvm_value_to_json_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_subscr(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_to_json_value_with_null(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_subscr_option(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_value_to_str_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_buffer_t* @kclvm_value_to_json(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_to_yaml_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); -declare %kclvm_value_ref_t* @kclvm_value_to_json_value(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_unary_l_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); -declare %kclvm_value_ref_t* @kclvm_value_to_json_value_with_null(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_unary_minus(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); -declare %kclvm_value_ref_t* @kclvm_value_to_str_value(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_unary_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); -declare %kclvm_value_ref_t* @kclvm_value_to_yaml_value(%kclvm_value_ref_t* %p); +declare %kclvm_value_ref_t* @kclvm_value_unary_plus(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); -declare %kclvm_value_ref_t* @kclvm_value_unary_l_not(%kclvm_value_ref_t* %a); +declare %kclvm_value_ref_t* @kclvm_value_union(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %b); -declare %kclvm_value_ref_t* @kclvm_value_unary_minus(%kclvm_value_ref_t* %a); +declare %kclvm_value_ref_t* @kclvm_value_union_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_value_unary_not(%kclvm_value_ref_t* %a); +declare %kclvm_value_ref_t* @kclvm_yaml_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_value_unary_plus(%kclvm_value_ref_t* %a); +declare %kclvm_value_ref_t* @kclvm_yaml_decode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_value_union(%kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %b); +declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_value_union_all(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_yaml_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_encode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_yaml_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* %_b) { - call %kclvm_value_ref_t*() @kclvm_value_None() + call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b) ret void } diff --git a/kclvm/runtime/src/_kclvm.rs b/kclvm/runtime/src/_kclvm.rs index 0d6e71994..d64a47db8 100644 --- a/kclvm/runtime/src/_kclvm.rs +++ b/kclvm/runtime/src/_kclvm.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -29,10 +29,6 @@ pub enum ApiFunc { kclvm_assert, kclvm_base64_decode, kclvm_base64_encode, - kclvm_buffer_data, - kclvm_buffer_delete, - kclvm_buffer_new, - kclvm_buffer_size, kclvm_builtin_abs, kclvm_builtin_all_true, kclvm_builtin_any_true, @@ -92,18 +88,10 @@ pub enum ApiFunc { kclvm_builtin_typeof, kclvm_builtin_zip, kclvm_config_attr_map, - kclvm_context_args_clear, - kclvm_context_args_get, - kclvm_context_args_set, - kclvm_context_clear_all_types, - kclvm_context_current, kclvm_context_delete, kclvm_context_invoke, - kclvm_context_main_begin_hook, - kclvm_context_main_end_hook, kclvm_context_new, kclvm_context_pkgpath_is_imported, - kclvm_context_put_type, kclvm_context_set_debug_mode, kclvm_context_set_disable_none, kclvm_context_set_disable_schema_check, @@ -111,20 +99,20 @@ pub enum ApiFunc { kclvm_context_set_kcl_filename, kclvm_context_set_kcl_line_col, kclvm_context_set_kcl_location, + kclvm_context_set_kcl_modpath, kclvm_context_set_kcl_pkgpath, + kclvm_context_set_kcl_workdir, kclvm_context_set_list_option_mode, kclvm_context_set_strict_range_check, - kclvm_context_symbol_init, - kclvm_context_symbol_name, - kclvm_context_symbol_num, - kclvm_context_symbol_value, kclvm_convert_collection_value, + kclvm_crypto_filesha256, kclvm_crypto_md5, kclvm_crypto_sha1, kclvm_crypto_sha224, kclvm_crypto_sha256, kclvm_crypto_sha384, kclvm_crypto_sha512, + kclvm_crypto_uuid, kclvm_datetime_date, kclvm_datetime_now, kclvm_datetime_ticks, @@ -140,6 +128,7 @@ pub enum ApiFunc { kclvm_dict_insert, kclvm_dict_insert_unpack, kclvm_dict_insert_value, + kclvm_dict_is_override_attr, kclvm_dict_keys, kclvm_dict_len, kclvm_dict_merge, @@ -149,7 +138,10 @@ pub enum ApiFunc { kclvm_dict_update, kclvm_dict_update_key_value, kclvm_dict_values, - kclvm_free, + kclvm_file_glob, + kclvm_file_modpath, + kclvm_file_read, + kclvm_file_workdir, kclvm_iterator_cur_key, kclvm_iterator_cur_value, kclvm_iterator_delete, @@ -158,6 +150,7 @@ pub enum ApiFunc { kclvm_json_decode, kclvm_json_dump_to_file, kclvm_json_encode, + kclvm_json_validate, kclvm_list_append, kclvm_list_append_bool, kclvm_list_append_float, @@ -176,7 +169,6 @@ pub enum ApiFunc { kclvm_list_remove_at, kclvm_list_resize, kclvm_list_set, - kclvm_malloc, kclvm_manifests_yaml_stream, kclvm_math_ceil, kclvm_math_exp, @@ -228,27 +220,11 @@ pub enum ApiFunc { kclvm_schema_optional_check, kclvm_schema_value_check, kclvm_schema_value_new, - kclvm_strlen, - kclvm_testing_arguments, - kclvm_testing_setting_file, - kclvm_type_BoolLit_value, - kclvm_type_FloatLit_value, - kclvm_type_IntLit_value, - kclvm_type_StrLit_value, - kclvm_type_arg_num, - kclvm_type_arg_type, - kclvm_type_delete, - kclvm_type_elem_type, - kclvm_type_key_type, - kclvm_type_kind, - kclvm_type_return_type, - kclvm_type_schema_field_name, - kclvm_type_schema_field_num, - kclvm_type_schema_field_type, - kclvm_type_schema_name, - kclvm_type_schema_parent_name, - kclvm_type_schema_relaxed, - kclvm_type_str, + kclvm_scope_add_setter, + kclvm_scope_free, + kclvm_scope_get, + kclvm_scope_new, + kclvm_scope_set, kclvm_units_to_G, kclvm_units_to_Gi, kclvm_units_to_K, @@ -263,26 +239,20 @@ pub enum ApiFunc { kclvm_units_to_n, kclvm_units_to_u, kclvm_value_Bool, - kclvm_value_Bool_ptr, kclvm_value_Decorator, kclvm_value_Dict, kclvm_value_False, kclvm_value_Float, - kclvm_value_Float_ptr, kclvm_value_Function, kclvm_value_Function_using_ptr, kclvm_value_Int, - kclvm_value_Int_ptr, kclvm_value_List, kclvm_value_List10, kclvm_value_List6, - kclvm_value_ListN, kclvm_value_None, kclvm_value_Schema, kclvm_value_Str, - kclvm_value_Str_len, kclvm_value_Str_ptr, - kclvm_value_Str_resize, kclvm_value_True, kclvm_value_Undefined, kclvm_value_Unit, @@ -297,17 +267,13 @@ pub enum ApiFunc { kclvm_value_deep_copy, kclvm_value_delete, kclvm_value_from_json, - kclvm_value_function_external_invoke, - kclvm_value_function_get_closure, kclvm_value_function_invoke, - kclvm_value_function_is_external, kclvm_value_function_ptr, kclvm_value_in, kclvm_value_is, kclvm_value_is_not, kclvm_value_is_truthy, kclvm_value_iter, - kclvm_value_kind, kclvm_value_len, kclvm_value_load_attr, kclvm_value_load_attr_option, @@ -347,7 +313,6 @@ pub enum ApiFunc { kclvm_value_slice_option, kclvm_value_subscr, kclvm_value_subscr_option, - kclvm_value_to_json, kclvm_value_to_json_value, kclvm_value_to_json_value_with_null, kclvm_value_to_str_value, @@ -359,8 +324,12 @@ pub enum ApiFunc { kclvm_value_union, kclvm_value_union_all, kclvm_yaml_decode, + kclvm_yaml_decode_all, + kclvm_yaml_dump_all_to_file, kclvm_yaml_dump_to_file, kclvm_yaml_encode, + kclvm_yaml_encode_all, + kclvm_yaml_validate, } impl std::fmt::Display for ApiFunc { diff --git a/kclvm/runtime/src/_kclvm_addr.rs b/kclvm/runtime/src/_kclvm_addr.rs index f7f285980..a85a406c7 100644 --- a/kclvm/runtime/src/_kclvm_addr.rs +++ b/kclvm/runtime/src/_kclvm_addr.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -8,10 +8,6 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_assert" => crate::kclvm_assert as *const () as u64, "kclvm_base64_decode" => crate::kclvm_base64_decode as *const () as u64, "kclvm_base64_encode" => crate::kclvm_base64_encode as *const () as u64, - "kclvm_buffer_data" => crate::kclvm_buffer_data as *const () as u64, - "kclvm_buffer_delete" => crate::kclvm_buffer_delete as *const () as u64, - "kclvm_buffer_new" => crate::kclvm_buffer_new as *const () as u64, - "kclvm_buffer_size" => crate::kclvm_buffer_size as *const () as u64, "kclvm_builtin_abs" => crate::kclvm_builtin_abs as *const () as u64, "kclvm_builtin_all_true" => crate::kclvm_builtin_all_true as *const () as u64, "kclvm_builtin_any_true" => crate::kclvm_builtin_any_true as *const () as u64, @@ -75,20 +71,12 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_builtin_typeof" => crate::kclvm_builtin_typeof as *const () as u64, "kclvm_builtin_zip" => crate::kclvm_builtin_zip as *const () as u64, "kclvm_config_attr_map" => crate::kclvm_config_attr_map as *const () as u64, - "kclvm_context_args_clear" => crate::kclvm_context_args_clear as *const () as u64, - "kclvm_context_args_get" => crate::kclvm_context_args_get as *const () as u64, - "kclvm_context_args_set" => crate::kclvm_context_args_set as *const () as u64, - "kclvm_context_clear_all_types" => crate::kclvm_context_clear_all_types as *const () as u64, - "kclvm_context_current" => crate::kclvm_context_current as *const () as u64, "kclvm_context_delete" => crate::kclvm_context_delete as *const () as u64, "kclvm_context_invoke" => crate::kclvm_context_invoke as *const () as u64, - "kclvm_context_main_begin_hook" => crate::kclvm_context_main_begin_hook as *const () as u64, - "kclvm_context_main_end_hook" => crate::kclvm_context_main_end_hook as *const () as u64, "kclvm_context_new" => crate::kclvm_context_new as *const () as u64, "kclvm_context_pkgpath_is_imported" => { crate::kclvm_context_pkgpath_is_imported as *const () as u64 } - "kclvm_context_put_type" => crate::kclvm_context_put_type as *const () as u64, "kclvm_context_set_debug_mode" => crate::kclvm_context_set_debug_mode as *const () as u64, "kclvm_context_set_disable_none" => { crate::kclvm_context_set_disable_none as *const () as u64 @@ -108,26 +96,26 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_context_set_kcl_location" => { crate::kclvm_context_set_kcl_location as *const () as u64 } + "kclvm_context_set_kcl_modpath" => crate::kclvm_context_set_kcl_modpath as *const () as u64, "kclvm_context_set_kcl_pkgpath" => crate::kclvm_context_set_kcl_pkgpath as *const () as u64, + "kclvm_context_set_kcl_workdir" => crate::kclvm_context_set_kcl_workdir as *const () as u64, "kclvm_context_set_list_option_mode" => { crate::kclvm_context_set_list_option_mode as *const () as u64 } "kclvm_context_set_strict_range_check" => { crate::kclvm_context_set_strict_range_check as *const () as u64 } - "kclvm_context_symbol_init" => crate::kclvm_context_symbol_init as *const () as u64, - "kclvm_context_symbol_name" => crate::kclvm_context_symbol_name as *const () as u64, - "kclvm_context_symbol_num" => crate::kclvm_context_symbol_num as *const () as u64, - "kclvm_context_symbol_value" => crate::kclvm_context_symbol_value as *const () as u64, "kclvm_convert_collection_value" => { crate::kclvm_convert_collection_value as *const () as u64 } + "kclvm_crypto_filesha256" => crate::kclvm_crypto_filesha256 as *const () as u64, "kclvm_crypto_md5" => crate::kclvm_crypto_md5 as *const () as u64, "kclvm_crypto_sha1" => crate::kclvm_crypto_sha1 as *const () as u64, "kclvm_crypto_sha224" => crate::kclvm_crypto_sha224 as *const () as u64, "kclvm_crypto_sha256" => crate::kclvm_crypto_sha256 as *const () as u64, "kclvm_crypto_sha384" => crate::kclvm_crypto_sha384 as *const () as u64, "kclvm_crypto_sha512" => crate::kclvm_crypto_sha512 as *const () as u64, + "kclvm_crypto_uuid" => crate::kclvm_crypto_uuid as *const () as u64, "kclvm_datetime_date" => crate::kclvm_datetime_date as *const () as u64, "kclvm_datetime_now" => crate::kclvm_datetime_now as *const () as u64, "kclvm_datetime_ticks" => crate::kclvm_datetime_ticks as *const () as u64, @@ -147,6 +135,7 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_dict_insert" => crate::kclvm_dict_insert as *const () as u64, "kclvm_dict_insert_unpack" => crate::kclvm_dict_insert_unpack as *const () as u64, "kclvm_dict_insert_value" => crate::kclvm_dict_insert_value as *const () as u64, + "kclvm_dict_is_override_attr" => crate::kclvm_dict_is_override_attr as *const () as u64, "kclvm_dict_keys" => crate::kclvm_dict_keys as *const () as u64, "kclvm_dict_len" => crate::kclvm_dict_len as *const () as u64, "kclvm_dict_merge" => crate::kclvm_dict_merge as *const () as u64, @@ -156,7 +145,10 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_dict_update" => crate::kclvm_dict_update as *const () as u64, "kclvm_dict_update_key_value" => crate::kclvm_dict_update_key_value as *const () as u64, "kclvm_dict_values" => crate::kclvm_dict_values as *const () as u64, - "kclvm_free" => crate::kclvm_free as *const () as u64, + "kclvm_file_glob" => crate::kclvm_file_glob as *const () as u64, + "kclvm_file_modpath" => crate::kclvm_file_modpath as *const () as u64, + "kclvm_file_read" => crate::kclvm_file_read as *const () as u64, + "kclvm_file_workdir" => crate::kclvm_file_workdir as *const () as u64, "kclvm_iterator_cur_key" => crate::kclvm_iterator_cur_key as *const () as u64, "kclvm_iterator_cur_value" => crate::kclvm_iterator_cur_value as *const () as u64, "kclvm_iterator_delete" => crate::kclvm_iterator_delete as *const () as u64, @@ -165,6 +157,7 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_json_decode" => crate::kclvm_json_decode as *const () as u64, "kclvm_json_dump_to_file" => crate::kclvm_json_dump_to_file as *const () as u64, "kclvm_json_encode" => crate::kclvm_json_encode as *const () as u64, + "kclvm_json_validate" => crate::kclvm_json_validate as *const () as u64, "kclvm_list_append" => crate::kclvm_list_append as *const () as u64, "kclvm_list_append_bool" => crate::kclvm_list_append_bool as *const () as u64, "kclvm_list_append_float" => crate::kclvm_list_append_float as *const () as u64, @@ -183,7 +176,6 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_list_remove_at" => crate::kclvm_list_remove_at as *const () as u64, "kclvm_list_resize" => crate::kclvm_list_resize as *const () as u64, "kclvm_list_set" => crate::kclvm_list_set as *const () as u64, - "kclvm_malloc" => crate::kclvm_malloc as *const () as u64, "kclvm_manifests_yaml_stream" => crate::kclvm_manifests_yaml_stream as *const () as u64, "kclvm_math_ceil" => crate::kclvm_math_ceil as *const () as u64, "kclvm_math_exp" => crate::kclvm_math_exp as *const () as u64, @@ -245,27 +237,11 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_schema_optional_check" => crate::kclvm_schema_optional_check as *const () as u64, "kclvm_schema_value_check" => crate::kclvm_schema_value_check as *const () as u64, "kclvm_schema_value_new" => crate::kclvm_schema_value_new as *const () as u64, - "kclvm_strlen" => crate::kclvm_strlen as *const () as u64, - "kclvm_testing_arguments" => crate::kclvm_testing_arguments as *const () as u64, - "kclvm_testing_setting_file" => crate::kclvm_testing_setting_file as *const () as u64, - "kclvm_type_BoolLit_value" => crate::kclvm_type_BoolLit_value as *const () as u64, - "kclvm_type_FloatLit_value" => crate::kclvm_type_FloatLit_value as *const () as u64, - "kclvm_type_IntLit_value" => crate::kclvm_type_IntLit_value as *const () as u64, - "kclvm_type_StrLit_value" => crate::kclvm_type_StrLit_value as *const () as u64, - "kclvm_type_arg_num" => crate::kclvm_type_arg_num as *const () as u64, - "kclvm_type_arg_type" => crate::kclvm_type_arg_type as *const () as u64, - "kclvm_type_delete" => crate::kclvm_type_delete as *const () as u64, - "kclvm_type_elem_type" => crate::kclvm_type_elem_type as *const () as u64, - "kclvm_type_key_type" => crate::kclvm_type_key_type as *const () as u64, - "kclvm_type_kind" => crate::kclvm_type_kind as *const () as u64, - "kclvm_type_return_type" => crate::kclvm_type_return_type as *const () as u64, - "kclvm_type_schema_field_name" => crate::kclvm_type_schema_field_name as *const () as u64, - "kclvm_type_schema_field_num" => crate::kclvm_type_schema_field_num as *const () as u64, - "kclvm_type_schema_field_type" => crate::kclvm_type_schema_field_type as *const () as u64, - "kclvm_type_schema_name" => crate::kclvm_type_schema_name as *const () as u64, - "kclvm_type_schema_parent_name" => crate::kclvm_type_schema_parent_name as *const () as u64, - "kclvm_type_schema_relaxed" => crate::kclvm_type_schema_relaxed as *const () as u64, - "kclvm_type_str" => crate::kclvm_type_str as *const () as u64, + "kclvm_scope_add_setter" => crate::kclvm_scope_add_setter as *const () as u64, + "kclvm_scope_free" => crate::kclvm_scope_free as *const () as u64, + "kclvm_scope_get" => crate::kclvm_scope_get as *const () as u64, + "kclvm_scope_new" => crate::kclvm_scope_new as *const () as u64, + "kclvm_scope_set" => crate::kclvm_scope_set as *const () as u64, "kclvm_units_to_G" => crate::kclvm_units_to_G as *const () as u64, "kclvm_units_to_Gi" => crate::kclvm_units_to_Gi as *const () as u64, "kclvm_units_to_K" => crate::kclvm_units_to_K as *const () as u64, @@ -280,28 +256,22 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_units_to_n" => crate::kclvm_units_to_n as *const () as u64, "kclvm_units_to_u" => crate::kclvm_units_to_u as *const () as u64, "kclvm_value_Bool" => crate::kclvm_value_Bool as *const () as u64, - "kclvm_value_Bool_ptr" => crate::kclvm_value_Bool_ptr as *const () as u64, "kclvm_value_Decorator" => crate::kclvm_value_Decorator as *const () as u64, "kclvm_value_Dict" => crate::kclvm_value_Dict as *const () as u64, "kclvm_value_False" => crate::kclvm_value_False as *const () as u64, "kclvm_value_Float" => crate::kclvm_value_Float as *const () as u64, - "kclvm_value_Float_ptr" => crate::kclvm_value_Float_ptr as *const () as u64, "kclvm_value_Function" => crate::kclvm_value_Function as *const () as u64, "kclvm_value_Function_using_ptr" => { crate::kclvm_value_Function_using_ptr as *const () as u64 } "kclvm_value_Int" => crate::kclvm_value_Int as *const () as u64, - "kclvm_value_Int_ptr" => crate::kclvm_value_Int_ptr as *const () as u64, "kclvm_value_List" => crate::kclvm_value_List as *const () as u64, "kclvm_value_List10" => crate::kclvm_value_List10 as *const () as u64, "kclvm_value_List6" => crate::kclvm_value_List6 as *const () as u64, - "kclvm_value_ListN" => crate::kclvm_value_ListN as *const () as u64, "kclvm_value_None" => crate::kclvm_value_None as *const () as u64, "kclvm_value_Schema" => crate::kclvm_value_Schema as *const () as u64, "kclvm_value_Str" => crate::kclvm_value_Str as *const () as u64, - "kclvm_value_Str_len" => crate::kclvm_value_Str_len as *const () as u64, "kclvm_value_Str_ptr" => crate::kclvm_value_Str_ptr as *const () as u64, - "kclvm_value_Str_resize" => crate::kclvm_value_Str_resize as *const () as u64, "kclvm_value_True" => crate::kclvm_value_True as *const () as u64, "kclvm_value_Undefined" => crate::kclvm_value_Undefined as *const () as u64, "kclvm_value_Unit" => crate::kclvm_value_Unit as *const () as u64, @@ -322,23 +292,13 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_value_deep_copy" => crate::kclvm_value_deep_copy as *const () as u64, "kclvm_value_delete" => crate::kclvm_value_delete as *const () as u64, "kclvm_value_from_json" => crate::kclvm_value_from_json as *const () as u64, - "kclvm_value_function_external_invoke" => { - crate::kclvm_value_function_external_invoke as *const () as u64 - } - "kclvm_value_function_get_closure" => { - crate::kclvm_value_function_get_closure as *const () as u64 - } "kclvm_value_function_invoke" => crate::kclvm_value_function_invoke as *const () as u64, - "kclvm_value_function_is_external" => { - crate::kclvm_value_function_is_external as *const () as u64 - } "kclvm_value_function_ptr" => crate::kclvm_value_function_ptr as *const () as u64, "kclvm_value_in" => crate::kclvm_value_in as *const () as u64, "kclvm_value_is" => crate::kclvm_value_is as *const () as u64, "kclvm_value_is_not" => crate::kclvm_value_is_not as *const () as u64, "kclvm_value_is_truthy" => crate::kclvm_value_is_truthy as *const () as u64, "kclvm_value_iter" => crate::kclvm_value_iter as *const () as u64, - "kclvm_value_kind" => crate::kclvm_value_kind as *const () as u64, "kclvm_value_len" => crate::kclvm_value_len as *const () as u64, "kclvm_value_load_attr" => crate::kclvm_value_load_attr as *const () as u64, "kclvm_value_load_attr_option" => crate::kclvm_value_load_attr_option as *const () as u64, @@ -380,7 +340,6 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_value_slice_option" => crate::kclvm_value_slice_option as *const () as u64, "kclvm_value_subscr" => crate::kclvm_value_subscr as *const () as u64, "kclvm_value_subscr_option" => crate::kclvm_value_subscr_option as *const () as u64, - "kclvm_value_to_json" => crate::kclvm_value_to_json as *const () as u64, "kclvm_value_to_json_value" => crate::kclvm_value_to_json_value as *const () as u64, "kclvm_value_to_json_value_with_null" => { crate::kclvm_value_to_json_value_with_null as *const () as u64 @@ -394,8 +353,12 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_value_union" => crate::kclvm_value_union as *const () as u64, "kclvm_value_union_all" => crate::kclvm_value_union_all as *const () as u64, "kclvm_yaml_decode" => crate::kclvm_yaml_decode as *const () as u64, + "kclvm_yaml_decode_all" => crate::kclvm_yaml_decode_all as *const () as u64, + "kclvm_yaml_dump_all_to_file" => crate::kclvm_yaml_dump_all_to_file as *const () as u64, "kclvm_yaml_dump_to_file" => crate::kclvm_yaml_dump_to_file as *const () as u64, "kclvm_yaml_encode" => crate::kclvm_yaml_encode as *const () as u64, + "kclvm_yaml_encode_all" => crate::kclvm_yaml_encode_all as *const () as u64, + "kclvm_yaml_validate" => crate::kclvm_yaml_validate as *const () as u64, _ => panic!("unknown {name}"), } } diff --git a/kclvm/runtime/src/_kclvm_api_spec.rs b/kclvm/runtime/src/_kclvm_api_spec.rs index deba63948..ff1a9c24a 100644 --- a/kclvm/runtime/src/_kclvm_api_spec.rs +++ b/kclvm/runtime/src/_kclvm_api_spec.rs @@ -2,38 +2,6 @@ // Auto generated by command, DONOT EDIT!!! -// api-spec: kclvm_buffer_new -// api-spec(c): kclvm_buffer_t* kclvm_buffer_new(kclvm_size_t size); -// api-spec(llvm): declare %kclvm_buffer_t* @kclvm_buffer_new(%kclvm_size_t %size); - -// api-spec: kclvm_buffer_delete -// api-spec(c): void kclvm_buffer_delete(kclvm_buffer_t* p); -// api-spec(llvm): declare void @kclvm_buffer_delete(%kclvm_buffer_t* %p); - -// api-spec: kclvm_buffer_size -// api-spec(c): kclvm_size_t kclvm_buffer_size(kclvm_buffer_t* p); -// api-spec(llvm): declare %kclvm_size_t @kclvm_buffer_size(%kclvm_buffer_t* %p); - -// api-spec: kclvm_buffer_data -// api-spec(c): kclvm_char_t* kclvm_buffer_data(kclvm_buffer_t* p); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_buffer_data(%kclvm_buffer_t* %p); - -// api-spec: kclvm_malloc -// api-spec(c): uint8_t* kclvm_malloc(int32_t n); -// api-spec(llvm): declare i8* @kclvm_malloc(i32 %n); - -// api-spec: kclvm_free -// api-spec(c): void kclvm_free(uint8_t* ptr); -// api-spec(llvm): declare void @kclvm_free(i8* %ptr); - -// api-spec: kclvm_strlen -// api-spec(c): kclvm_size_t kclvm_strlen(uint8_t* ptr); -// api-spec(llvm): declare %kclvm_size_t @kclvm_strlen(i8* %ptr); - -// api-spec: kclvm_context_current -// api-spec(c): kclvm_context_t* kclvm_context_current(); -// api-spec(llvm): declare %kclvm_context_t* @kclvm_context_current(); - // api-spec: kclvm_context_new // api-spec(c): kclvm_context_t* kclvm_context_new(); // api-spec(llvm): declare %kclvm_context_t* @kclvm_context_new(); @@ -42,65 +10,49 @@ // api-spec(c): void kclvm_context_delete(kclvm_context_t* p); // api-spec(llvm): declare void @kclvm_context_delete(%kclvm_context_t* %p); -// api-spec: kclvm_context_main_begin_hook -// api-spec(c): void kclvm_context_main_begin_hook(kclvm_context_t* p); -// api-spec(llvm): declare void @kclvm_context_main_begin_hook(%kclvm_context_t* %p); - -// api-spec: kclvm_context_main_end_hook -// api-spec(c): kclvm_value_ref_t* kclvm_context_main_end_hook(kclvm_context_t* p, kclvm_value_ref_t* return_value); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_context_main_end_hook(%kclvm_context_t* %p, %kclvm_value_ref_t* %return_value); - // api-spec: kclvm_context_set_kcl_location -// api-spec(c): void kclvm_context_set_kcl_location(kclvm_context_t* p, int8_t* filename, int32_t line, int32_t col); +// api-spec(c): void kclvm_context_set_kcl_location(kclvm_context_t* p, char* filename, int32_t line, int32_t col); // api-spec(llvm): declare void @kclvm_context_set_kcl_location(%kclvm_context_t* %p, i8* %filename, i32 %line, i32 %col); // api-spec: kclvm_context_set_kcl_pkgpath -// api-spec(c): void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, int8_t* pkgpath); +// api-spec(c): void kclvm_context_set_kcl_pkgpath(kclvm_context_t* p, char* pkgpath); // api-spec(llvm): declare void @kclvm_context_set_kcl_pkgpath(%kclvm_context_t* %p, i8* %pkgpath); -// api-spec: kclvm_context_set_kcl_filename -// api-spec(c): void kclvm_context_set_kcl_filename(int8_t* filename); -// api-spec(llvm): declare void @kclvm_context_set_kcl_filename(i8* %filename); +// api-spec: kclvm_context_set_kcl_modpath +// api-spec(c): void kclvm_context_set_kcl_modpath(kclvm_context_t* p, char* module_path); +// api-spec(llvm): declare void @kclvm_context_set_kcl_modpath(%kclvm_context_t* %p, i8* %module_path); -// api-spec: kclvm_context_set_kcl_line_col -// api-spec(c): void kclvm_context_set_kcl_line_col(int32_t line, int32_t col); -// api-spec(llvm): declare void @kclvm_context_set_kcl_line_col(i32 %line, i32 %col); +// api-spec: kclvm_context_set_kcl_workdir +// api-spec(c): void kclvm_context_set_kcl_workdir(kclvm_context_t* p, char* workdir); +// api-spec(llvm): declare void @kclvm_context_set_kcl_workdir(%kclvm_context_t* %p, i8* %workdir); -// api-spec: kclvm_context_put_type -// api-spec(c): void kclvm_context_put_type(kclvm_context_t* p, kclvm_type_t* typ); -// api-spec(llvm): declare void @kclvm_context_put_type(%kclvm_context_t* %p, %kclvm_type_t* %typ); - -// api-spec: kclvm_context_clear_all_types -// api-spec(c): void kclvm_context_clear_all_types(kclvm_context_t* p); -// api-spec(llvm): declare void @kclvm_context_clear_all_types(%kclvm_context_t* %p); - -// api-spec: kclvm_context_symbol_init -// api-spec(c): void kclvm_context_symbol_init(kclvm_context_t* p, kclvm_size_t n, kclvm_char_t** symbol_names); -// api-spec(llvm): declare void @kclvm_context_symbol_init(%kclvm_context_t* %p, %kclvm_size_t %n, %kclvm_char_t** %symbol_names); +// api-spec: kclvm_context_set_kcl_filename +// api-spec(c): void kclvm_context_set_kcl_filename(kclvm_context_t* ctx, char* filename); +// api-spec(llvm): declare void @kclvm_context_set_kcl_filename(%kclvm_context_t* %ctx, i8* %filename); -// api-spec: kclvm_context_symbol_num -// api-spec(c): kclvm_size_t kclvm_context_symbol_num(kclvm_context_t* p); -// api-spec(llvm): declare %kclvm_size_t @kclvm_context_symbol_num(%kclvm_context_t* %p); +// api-spec: kclvm_context_set_kcl_line_col +// api-spec(c): void kclvm_context_set_kcl_line_col(kclvm_context_t* ctx, int32_t line, int32_t col); +// api-spec(llvm): declare void @kclvm_context_set_kcl_line_col(%kclvm_context_t* %ctx, i32 %line, i32 %col); -// api-spec: kclvm_context_symbol_name -// api-spec(c): kclvm_char_t* kclvm_context_symbol_name(kclvm_context_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_context_symbol_name(%kclvm_context_t* %p, %kclvm_size_t %i); +// api-spec: kclvm_scope_new +// api-spec(c): kclvm_eval_scope_t* kclvm_scope_new(); +// api-spec(llvm): declare %kclvm_eval_scope_t* @kclvm_scope_new(); -// api-spec: kclvm_context_symbol_value -// api-spec(c): kclvm_value_t* kclvm_context_symbol_value(kclvm_context_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_value_t* @kclvm_context_symbol_value(%kclvm_context_t* %p, %kclvm_size_t %i); +// api-spec: kclvm_scope_free +// api-spec(c): void kclvm_scope_free(kclvm_eval_scope_t* scope); +// api-spec(llvm): declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope); -// api-spec: kclvm_context_args_get -// api-spec(c): kclvm_char_t* kclvm_context_args_get(kclvm_context_t* _p, kclvm_char_t* _key); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_context_args_get(%kclvm_context_t* %_p, %kclvm_char_t* %_key); +// api-spec: kclvm_scope_add_setter +// api-spec(c): void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter); +// api-spec(llvm): declare void @kclvm_scope_add_setter(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i64* %setter); -// api-spec: kclvm_context_args_set -// api-spec(c): void kclvm_context_args_set(kclvm_context_t* _p, kclvm_char_t* _key, kclvm_char_t* _value); -// api-spec(llvm): declare void @kclvm_context_args_set(%kclvm_context_t* %_p, %kclvm_char_t* %_key, %kclvm_char_t* %_value); +// api-spec: kclvm_scope_set +// api-spec(c): void kclvm_scope_set(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, kclvm_value_ref_t* value); +// api-spec(llvm): declare void @kclvm_scope_set(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, %kclvm_value_ref_t* %value); -// api-spec: kclvm_context_args_clear -// api-spec(c): void kclvm_context_args_clear(kclvm_context_t* p); -// api-spec(llvm): declare void @kclvm_context_args_clear(%kclvm_context_t* %p); +// api-spec: kclvm_scope_get +// api-spec(c): kclvm_value_ref_t* kclvm_scope_get(kclvm_context_t* ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, char* target, kclvm_value_ref_t* default); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_scope_get(%kclvm_context_t* %ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i8* %target, %kclvm_value_ref_t* %default); // api-spec: kclvm_context_set_debug_mode // api-spec(c): void kclvm_context_set_debug_mode(kclvm_context_t* p, kclvm_bool_t v); @@ -127,217 +79,117 @@ // api-spec(llvm): declare i8* @kclvm_context_invoke(%kclvm_context_t* %p, i8* %method, i8* %args, i8* %kwargs); // api-spec: kclvm_context_pkgpath_is_imported -// api-spec(c): kclvm_bool_t kclvm_context_pkgpath_is_imported(kclvm_char_t* pkgpath); -// api-spec(llvm): declare %kclvm_bool_t @kclvm_context_pkgpath_is_imported(%kclvm_char_t* %pkgpath); - -// api-spec: kclvm_type_delete -// api-spec(c): void kclvm_type_delete(kclvm_type_t* p); -// api-spec(llvm): declare void @kclvm_type_delete(%kclvm_type_t* %p); - -// api-spec: kclvm_type_kind -// api-spec(c): kclvm_kind_t kclvm_type_kind(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_kind_t @kclvm_type_kind(%kclvm_type_t* %p); - -// api-spec: kclvm_type_str -// api-spec(c): kclvm_kind_t kclvm_type_str(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_kind_t @kclvm_type_str(%kclvm_type_t* %p); - -// api-spec: kclvm_type_BoolLit_value -// api-spec(c): kclvm_bool_t kclvm_type_BoolLit_value(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_bool_t @kclvm_type_BoolLit_value(%kclvm_type_t* %p); - -// api-spec: kclvm_type_IntLit_value -// api-spec(c): int64_t kclvm_type_IntLit_value(kclvm_type_t* p); -// api-spec(llvm): declare i64 @kclvm_type_IntLit_value(%kclvm_type_t* %p); - -// api-spec: kclvm_type_FloatLit_value -// api-spec(c): double kclvm_type_FloatLit_value(kclvm_type_t* p); -// api-spec(llvm): declare double @kclvm_type_FloatLit_value(%kclvm_type_t* %p); - -// api-spec: kclvm_type_StrLit_value -// api-spec(c): kclvm_char_t* kclvm_type_StrLit_value(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_type_StrLit_value(%kclvm_type_t* %p); - -// api-spec: kclvm_type_key_type -// api-spec(c): kclvm_type_t* kclvm_type_key_type(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_type_t* @kclvm_type_key_type(%kclvm_type_t* %p); - -// api-spec: kclvm_type_elem_type -// api-spec(c): kclvm_type_t* kclvm_type_elem_type(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_type_t* @kclvm_type_elem_type(%kclvm_type_t* %p); - -// api-spec: kclvm_type_schema_name -// api-spec(c): kclvm_char_t* kclvm_type_schema_name(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_type_schema_name(%kclvm_type_t* %p); - -// api-spec: kclvm_type_schema_parent_name -// api-spec(c): kclvm_char_t* kclvm_type_schema_parent_name(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_type_schema_parent_name(%kclvm_type_t* %p); - -// api-spec: kclvm_type_schema_relaxed -// api-spec(c): kclvm_bool_t kclvm_type_schema_relaxed(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_bool_t @kclvm_type_schema_relaxed(%kclvm_type_t* %p); - -// api-spec: kclvm_type_schema_field_num -// api-spec(c): kclvm_size_t kclvm_type_schema_field_num(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_size_t @kclvm_type_schema_field_num(%kclvm_type_t* %p); - -// api-spec: kclvm_type_schema_field_name -// api-spec(c): kclvm_char_t* kclvm_type_schema_field_name(kclvm_type_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_char_t* @kclvm_type_schema_field_name(%kclvm_type_t* %p, %kclvm_size_t %i); - -// api-spec: kclvm_type_schema_field_type -// api-spec(c): kclvm_type_t* kclvm_type_schema_field_type(kclvm_type_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_type_t* @kclvm_type_schema_field_type(%kclvm_type_t* %p, %kclvm_size_t %i); - -// api-spec: kclvm_type_arg_num -// api-spec(c): kclvm_size_t kclvm_type_arg_num(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_size_t @kclvm_type_arg_num(%kclvm_type_t* %p); - -// api-spec: kclvm_type_arg_type -// api-spec(c): kclvm_type_t* kclvm_type_arg_type(kclvm_type_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_type_t* @kclvm_type_arg_type(%kclvm_type_t* %p, %kclvm_size_t %i); - -// api-spec: kclvm_type_return_type -// api-spec(c): kclvm_type_t* kclvm_type_return_type(kclvm_type_t* p); -// api-spec(llvm): declare %kclvm_type_t* @kclvm_type_return_type(%kclvm_type_t* %p); +// api-spec(c): kclvm_bool_t kclvm_context_pkgpath_is_imported(kclvm_context_t* ctx, kclvm_char_t* pkgpath); +// api-spec(llvm): declare %kclvm_bool_t @kclvm_context_pkgpath_is_imported(%kclvm_context_t* %ctx, %kclvm_char_t* %pkgpath); // api-spec: kclvm_context_set_import_names // api-spec(c): void kclvm_context_set_import_names(kclvm_context_t* p, kclvm_value_ref_t* import_names); // api-spec(llvm): declare void @kclvm_context_set_import_names(%kclvm_context_t* %p, %kclvm_value_ref_t* %import_names); // api-spec: kclvm_value_Undefined -// api-spec(c): kclvm_value_ref_t* kclvm_value_Undefined(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Undefined(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Undefined(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Undefined(%kclvm_context_t* %ctx); // api-spec: kclvm_value_None -// api-spec(c): kclvm_value_ref_t* kclvm_value_None(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_None(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_None(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %ctx); // api-spec: kclvm_value_True -// api-spec(c): kclvm_value_ref_t* kclvm_value_True(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_True(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_True(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_True(%kclvm_context_t* %ctx); // api-spec: kclvm_value_False -// api-spec(c): kclvm_value_ref_t* kclvm_value_False(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_False(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_False(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_False(%kclvm_context_t* %ctx); // api-spec: kclvm_value_Bool -// api-spec(c): kclvm_value_ref_t* kclvm_value_Bool(kclvm_bool_t v); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Bool(%kclvm_bool_t %v); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Bool(kclvm_context_t* ctx, kclvm_bool_t v); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Bool(%kclvm_context_t* %ctx, %kclvm_bool_t %v); // api-spec: kclvm_value_Int -// api-spec(c): kclvm_value_ref_t* kclvm_value_Int(kclvm_int_t v); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Int(%kclvm_int_t %v); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Int(kclvm_context_t* ctx, kclvm_int_t v); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Int(%kclvm_context_t* %ctx, %kclvm_int_t %v); // api-spec: kclvm_value_Float -// api-spec(c): kclvm_value_ref_t* kclvm_value_Float(kclvm_float_t v); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Float(%kclvm_float_t %v); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Float(kclvm_context_t* ctx, kclvm_float_t v); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Float(%kclvm_context_t* %ctx, %kclvm_float_t %v); // api-spec: kclvm_value_Unit -// api-spec(c): kclvm_value_ref_t* kclvm_value_Unit(kclvm_float_t v, kclvm_int_t raw, kclvm_char_t* unit); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Unit(%kclvm_float_t %v, %kclvm_int_t %raw, %kclvm_char_t* %unit); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Unit(kclvm_context_t* ctx, kclvm_float_t v, kclvm_int_t raw, kclvm_char_t* unit); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Unit(%kclvm_context_t* %ctx, %kclvm_float_t %v, %kclvm_int_t %raw, %kclvm_char_t* %unit); // api-spec: kclvm_value_Str -// api-spec(c): kclvm_value_ref_t* kclvm_value_Str(kclvm_char_t* v); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Str(%kclvm_char_t* %v); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Str(kclvm_context_t* ctx, kclvm_char_t* v); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Str(%kclvm_context_t* %ctx, %kclvm_char_t* %v); // api-spec: kclvm_value_List -// api-spec(c): kclvm_value_ref_t* kclvm_value_List(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_List(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List(%kclvm_context_t* %ctx); // api-spec: kclvm_value_List6 -// api-spec(c): kclvm_value_ref_t* kclvm_value_List6(kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List6(%kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6); +// api-spec(c): kclvm_value_ref_t* kclvm_value_List6(kclvm_context_t* ctx, kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List6(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6); // api-spec: kclvm_value_List10 -// api-spec(c): kclvm_value_ref_t* kclvm_value_List10(kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6, kclvm_value_ref_t* v7, kclvm_value_ref_t* v8, kclvm_value_ref_t* v9, kclvm_value_ref_t* v10); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List10(%kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6, %kclvm_value_ref_t* %v7, %kclvm_value_ref_t* %v8, %kclvm_value_ref_t* %v9, %kclvm_value_ref_t* %v10); - -// api-spec: kclvm_value_ListN -// api-spec(c): kclvm_value_ref_t* kclvm_value_ListN(kclvm_int_t n, kclvm_value_ref_t** elem_values); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_ListN(%kclvm_int_t %n, %kclvm_value_ref_t** %elem_values); +// api-spec(c): kclvm_value_ref_t* kclvm_value_List10(kclvm_context_t* ctx, kclvm_value_ref_t* v1, kclvm_value_ref_t* v2, kclvm_value_ref_t* v3, kclvm_value_ref_t* v4, kclvm_value_ref_t* v5, kclvm_value_ref_t* v6, kclvm_value_ref_t* v7, kclvm_value_ref_t* v8, kclvm_value_ref_t* v9, kclvm_value_ref_t* v10); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_List10(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %v1, %kclvm_value_ref_t* %v2, %kclvm_value_ref_t* %v3, %kclvm_value_ref_t* %v4, %kclvm_value_ref_t* %v5, %kclvm_value_ref_t* %v6, %kclvm_value_ref_t* %v7, %kclvm_value_ref_t* %v8, %kclvm_value_ref_t* %v9, %kclvm_value_ref_t* %v10); // api-spec: kclvm_value_Dict -// api-spec(c): kclvm_value_ref_t* kclvm_value_Dict(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Dict(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Dict(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Dict(%kclvm_context_t* %ctx); // api-spec: kclvm_value_Schema -// api-spec(c): kclvm_value_ref_t* kclvm_value_Schema(); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Schema(); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Schema(kclvm_context_t* ctx); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Schema(%kclvm_context_t* %ctx); // api-spec: kclvm_value_schema_with_config -// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping); +// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_value_Function -// api-spec(c): kclvm_value_ref_t* kclvm_value_Function(uint64_t* fn_ptr, kclvm_value_ref_t* closure, kclvm_char_t* name, kclvm_bool_t is_external); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Function(i64* %fn_ptr, %kclvm_value_ref_t* %closure, %kclvm_char_t* %name, %kclvm_bool_t %is_external); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Function(kclvm_context_t* ctx, uint64_t* fn_ptr, kclvm_value_ref_t* closure, kclvm_char_t* name, kclvm_bool_t is_external); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Function(%kclvm_context_t* %ctx, i64* %fn_ptr, %kclvm_value_ref_t* %closure, %kclvm_char_t* %name, %kclvm_bool_t %is_external); // api-spec: kclvm_value_Function_using_ptr -// api-spec(c): kclvm_value_ref_t* kclvm_value_Function_using_ptr(uint64_t* fn_ptr, kclvm_char_t* name); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Function_using_ptr(i64* %fn_ptr, %kclvm_char_t* %name); +// api-spec(c): kclvm_value_ref_t* kclvm_value_Function_using_ptr(kclvm_context_t* ctx, uint64_t* fn_ptr, kclvm_char_t* name); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Function_using_ptr(%kclvm_context_t* %ctx, i64* %fn_ptr, %kclvm_char_t* %name); // api-spec: kclvm_value_schema_function -// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_function(uint64_t* fn_ptr, uint64_t* check_fn_ptr, kclvm_char_t* tpe); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_function(i64* %fn_ptr, i64* %check_fn_ptr, %kclvm_char_t* %tpe); +// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_function(kclvm_context_t* ctx, uint64_t* fn_ptr, uint64_t* check_fn_ptr, kclvm_value_ref_t* attr_map, kclvm_char_t* tpe); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_function(%kclvm_context_t* %ctx, i64* %fn_ptr, i64* %check_fn_ptr, %kclvm_value_ref_t* %attr_map, %kclvm_char_t* %tpe); // api-spec: kclvm_value_from_json -// api-spec(c): kclvm_value_ref_t* kclvm_value_from_json(kclvm_char_t* s); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_from_json(%kclvm_char_t* %s); - -// api-spec: kclvm_value_to_json -// api-spec(c): kclvm_buffer_t* kclvm_value_to_json(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_buffer_t* @kclvm_value_to_json(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_from_json(kclvm_context_t* ctx, kclvm_char_t* s); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_from_json(%kclvm_context_t* %ctx, %kclvm_char_t* %s); // api-spec: kclvm_value_to_json_value -// api-spec(c): kclvm_value_ref_t* kclvm_value_to_json_value(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_json_value(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_to_json_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_json_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_to_json_value_with_null -// api-spec(c): kclvm_value_ref_t* kclvm_value_to_json_value_with_null(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_json_value_with_null(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_to_json_value_with_null(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_json_value_with_null(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_plan_to_json -// api-spec(c): kclvm_value_ref_t* kclvm_value_plan_to_json(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_plan_to_json(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_plan_to_json(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_plan_to_json(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_plan_to_yaml -// api-spec(c): kclvm_value_ref_t* kclvm_value_plan_to_yaml(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_plan_to_yaml(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_plan_to_yaml(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_plan_to_yaml(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_to_yaml_value -// api-spec(c): kclvm_value_ref_t* kclvm_value_to_yaml_value(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_yaml_value(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_to_yaml_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_yaml_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_to_str_value -// api-spec(c): kclvm_value_ref_t* kclvm_value_to_str_value(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_str_value(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_Bool_ptr -// api-spec(c): kclvm_bool_t* kclvm_value_Bool_ptr(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_bool_t* @kclvm_value_Bool_ptr(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_Int_ptr -// api-spec(c): kclvm_int_t* kclvm_value_Int_ptr(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_int_t* @kclvm_value_Int_ptr(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_Float_ptr -// api-spec(c): kclvm_float_t* kclvm_value_Float_ptr(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_float_t* @kclvm_value_Float_ptr(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_to_str_value(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_to_str_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_Str_ptr // api-spec(c): kclvm_char_t* kclvm_value_Str_ptr(kclvm_value_ref_t* p); // api-spec(llvm): declare %kclvm_char_t* @kclvm_value_Str_ptr(%kclvm_value_ref_t* %p); -// api-spec: kclvm_value_Str_len -// api-spec(c): kclvm_size_t kclvm_value_Str_len(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_size_t @kclvm_value_Str_len(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_Str_resize -// api-spec(c): void kclvm_value_Str_resize(kclvm_value_ref_t* p, kclvm_size_t n); -// api-spec(llvm): declare void @kclvm_value_Str_resize(%kclvm_value_ref_t* %p, %kclvm_size_t %n); - // api-spec: kclvm_value_function_ptr // api-spec(c): uint64_t* kclvm_value_function_ptr(kclvm_value_ref_t* p); // api-spec(llvm): declare i64* @kclvm_value_function_ptr(%kclvm_value_ref_t* %p); @@ -346,29 +198,13 @@ // api-spec(c): uint64_t* kclvm_value_check_function_ptr(kclvm_value_ref_t* p); // api-spec(llvm): declare i64* @kclvm_value_check_function_ptr(%kclvm_value_ref_t* %p); -// api-spec: kclvm_value_function_is_external -// api-spec(c): kclvm_bool_t kclvm_value_function_is_external(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_bool_t @kclvm_value_function_is_external(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_function_external_invoke -// api-spec(c): kclvm_value_ref_t* kclvm_value_function_external_invoke(kclvm_value_ref_t* p, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_function_external_invoke(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); - // api-spec: kclvm_value_function_invoke // api-spec(c): kclvm_value_ref_t* kclvm_value_function_invoke(kclvm_value_ref_t* p, kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_in_schema); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_function_invoke(%kclvm_value_ref_t* %p, %kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_in_schema); -// api-spec: kclvm_value_function_get_closure -// api-spec(c): kclvm_value_ref_t* kclvm_value_function_get_closure(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_function_get_closure(%kclvm_value_ref_t* %p); - -// api-spec: kclvm_value_kind -// api-spec(c): kclvm_kind_t kclvm_value_kind(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_kind_t @kclvm_value_kind(%kclvm_value_ref_t* %p); - // api-spec: kclvm_value_deep_copy -// api-spec(c): kclvm_value_ref_t* kclvm_value_deep_copy(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_deep_copy(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_value_deep_copy(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_deep_copy(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_value_delete // api-spec(c): void kclvm_value_delete(kclvm_value_ref_t* p); @@ -411,36 +247,36 @@ // api-spec(llvm): declare void @kclvm_list_clear(%kclvm_value_ref_t* %p); // api-spec: kclvm_list_count -// api-spec(c): kclvm_value_ref_t* kclvm_list_count(kclvm_value_ref_t* p, kclvm_value_ref_t* item); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_count(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); +// api-spec(c): kclvm_value_ref_t* kclvm_list_count(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* item); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_count(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); // api-spec: kclvm_list_find -// api-spec(c): kclvm_value_ref_t* kclvm_list_find(kclvm_value_ref_t* p, kclvm_value_ref_t* item); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_find(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); +// api-spec(c): kclvm_value_ref_t* kclvm_list_find(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* item); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_find(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %item); // api-spec: kclvm_list_insert // api-spec(c): void kclvm_list_insert(kclvm_value_ref_t* p, kclvm_value_ref_t* index, kclvm_value_ref_t* value); // api-spec(llvm): declare void @kclvm_list_insert(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %index, %kclvm_value_ref_t* %value); // api-spec: kclvm_list_get -// api-spec(c): kclvm_value_ref_t* kclvm_list_get(kclvm_value_ref_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_get(%kclvm_value_ref_t* %p, %kclvm_size_t %i); +// api-spec(c): kclvm_value_ref_t* kclvm_list_get(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_size_t i); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_get(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_size_t %i); // api-spec: kclvm_list_get_option -// api-spec(c): kclvm_value_ref_t* kclvm_list_get_option(kclvm_value_ref_t* p, kclvm_size_t i); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_get_option(%kclvm_value_ref_t* %p, %kclvm_size_t %i); +// api-spec(c): kclvm_value_ref_t* kclvm_list_get_option(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_size_t i); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_get_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_size_t %i); // api-spec: kclvm_list_set // api-spec(c): void kclvm_list_set(kclvm_value_ref_t* p, kclvm_size_t i, kclvm_value_ref_t* v); // api-spec(llvm): declare void @kclvm_list_set(%kclvm_value_ref_t* %p, %kclvm_size_t %i, %kclvm_value_ref_t* %v); // api-spec: kclvm_list_pop -// api-spec(c): kclvm_value_ref_t* kclvm_list_pop(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_pop(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_list_pop(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_pop(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_list_pop_first -// api-spec(c): kclvm_value_ref_t* kclvm_list_pop_first(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_pop_first(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_list_pop_first(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_list_pop_first(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_list_append // api-spec(c): void kclvm_list_append(kclvm_value_ref_t* p, kclvm_value_ref_t* v); @@ -478,61 +314,65 @@ // api-spec(c): void kclvm_dict_clear(kclvm_value_ref_t* p); // api-spec(llvm): declare void @kclvm_dict_clear(%kclvm_value_ref_t* %p); +// api-spec: kclvm_dict_is_override_attr +// api-spec(c): kclvm_bool_t kclvm_dict_is_override_attr(kclvm_value_ref_t* p, kclvm_char_t* key); +// api-spec(llvm): declare %kclvm_bool_t @kclvm_dict_is_override_attr(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); + // api-spec: kclvm_dict_get -// api-spec(c): kclvm_value_ref_t* kclvm_dict_get(kclvm_value_ref_t* p, kclvm_value_ref_t* key); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_get(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* key); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key); // api-spec: kclvm_dict_has_value // api-spec(c): kclvm_bool_t kclvm_dict_has_value(kclvm_value_ref_t* p, kclvm_char_t* key); // api-spec(llvm): declare %kclvm_bool_t @kclvm_dict_has_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); // api-spec: kclvm_dict_get_value -// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_value(kclvm_value_ref_t* p, kclvm_char_t* key); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); // api-spec: kclvm_dict_get_entry -// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_entry(kclvm_value_ref_t* p, kclvm_char_t* key); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_entry(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_entry(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_entry(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); // api-spec: kclvm_dict_get_value_by_path -// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_value_by_path(kclvm_value_ref_t* p, kclvm_char_t* path); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_value_by_path(%kclvm_value_ref_t* %p, %kclvm_char_t* %path); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_get_value_by_path(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* path); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_get_value_by_path(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %path); // api-spec: kclvm_dict_set_value -// api-spec(c): void kclvm_dict_set_value(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* val); -// api-spec(llvm): declare void @kclvm_dict_set_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %val); +// api-spec(c): void kclvm_dict_set_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* val); +// api-spec(llvm): declare void @kclvm_dict_set_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %val); // api-spec: kclvm_dict_keys -// api-spec(c): kclvm_value_ref_t* kclvm_dict_keys(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_keys(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_keys(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_keys(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_dict_values -// api-spec(c): kclvm_value_ref_t* kclvm_dict_values(kclvm_value_ref_t* p); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_values(%kclvm_value_ref_t* %p); +// api-spec(c): kclvm_value_ref_t* kclvm_dict_values(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_dict_values(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_dict_insert -// api-spec(c): void kclvm_dict_insert(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -// api-spec(llvm): declare void @kclvm_dict_insert(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +// api-spec(c): void kclvm_dict_insert(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +// api-spec(llvm): declare void @kclvm_dict_insert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); // api-spec: kclvm_dict_merge -// api-spec(c): void kclvm_dict_merge(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -// api-spec(llvm): declare void @kclvm_dict_merge(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +// api-spec(c): void kclvm_dict_merge(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +// api-spec(llvm): declare void @kclvm_dict_merge(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); // api-spec: kclvm_dict_insert_value -// api-spec(c): void kclvm_dict_insert_value(kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -// api-spec(llvm): declare void @kclvm_dict_insert_value(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +// api-spec(c): void kclvm_dict_insert_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +// api-spec(llvm): declare void @kclvm_dict_insert_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); // api-spec: kclvm_dict_update_key_value // api-spec(c): void kclvm_dict_update_key_value(kclvm_value_ref_t* p, kclvm_value_ref_t* key, kclvm_value_ref_t* v); // api-spec(llvm): declare void @kclvm_dict_update_key_value(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %key, %kclvm_value_ref_t* %v); // api-spec: kclvm_dict_safe_insert -// api-spec(c): void kclvm_dict_safe_insert(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); -// api-spec(llvm): declare void @kclvm_dict_safe_insert(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); +// api-spec(c): void kclvm_dict_safe_insert(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* v, kclvm_size_t op, kclvm_size_t insert_index); +// api-spec(llvm): declare void @kclvm_dict_safe_insert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %v, %kclvm_size_t %op, %kclvm_size_t %insert_index); // api-spec: kclvm_dict_insert_unpack -// api-spec(c): void kclvm_dict_insert_unpack(kclvm_value_ref_t* p, kclvm_value_ref_t* v); -// api-spec(llvm): declare void @kclvm_dict_insert_unpack(%kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); +// api-spec(c): void kclvm_dict_insert_unpack(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_value_ref_t* v); +// api-spec(llvm): declare void @kclvm_dict_insert_unpack(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_value_ref_t* %v); // api-spec: kclvm_default_collection_insert_int_pointer // api-spec(c): void kclvm_default_collection_insert_int_pointer(kclvm_value_ref_t* p, kclvm_char_t* key, uint64_t* ptr); @@ -559,504 +399,516 @@ // api-spec(llvm): declare %kclvm_size_t @kclvm_value_len(%kclvm_value_ref_t* %p); // api-spec: kclvm_value_cmp_equal_to -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_equal_to(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_equal_to(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_equal_to(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_equal_to(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_cmp_not_equal_to -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_not_equal_to(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_not_equal_to(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_not_equal_to(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_not_equal_to(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_cmp_less_than -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_less_than(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_less_than(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_cmp_less_than_or_equal -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_less_than_or_equal(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than_or_equal(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_less_than_or_equal(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_less_than_or_equal(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_cmp_greater_than -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_greater_than(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_greater_than(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_cmp_greater_than_or_equal -// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_greater_than_or_equal(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than_or_equal(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_cmp_greater_than_or_equal(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_cmp_greater_than_or_equal(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_is -// api-spec(c): kclvm_value_ref_t* kclvm_value_is(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_is(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_is(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_is(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_is_not -// api-spec(c): kclvm_value_ref_t* kclvm_value_is_not(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_is_not(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_is_not(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_is_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_in -// api-spec(c): kclvm_value_ref_t* kclvm_value_in(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_in(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_in(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_in(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_not_in -// api-spec(c): kclvm_value_ref_t* kclvm_value_not_in(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_not_in(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_not_in(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_not_in(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_as -// api-spec(c): kclvm_value_ref_t* kclvm_value_as(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_as(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_as(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_as(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_unary_plus -// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_plus(kclvm_value_ref_t* a); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_plus(%kclvm_value_ref_t* %a); +// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_plus(kclvm_context_t* ctx, kclvm_value_ref_t* a); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_plus(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); // api-spec: kclvm_value_unary_minus -// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_minus(kclvm_value_ref_t* a); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_minus(%kclvm_value_ref_t* %a); +// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_minus(kclvm_context_t* ctx, kclvm_value_ref_t* a); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_minus(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); // api-spec: kclvm_value_unary_not -// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_not(kclvm_value_ref_t* a); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_not(%kclvm_value_ref_t* %a); +// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_not(kclvm_context_t* ctx, kclvm_value_ref_t* a); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); // api-spec: kclvm_value_unary_l_not -// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_l_not(kclvm_value_ref_t* a); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_l_not(%kclvm_value_ref_t* %a); +// api-spec(c): kclvm_value_ref_t* kclvm_value_unary_l_not(kclvm_context_t* ctx, kclvm_value_ref_t* a); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_unary_l_not(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a); // api-spec: kclvm_value_op_add -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_add(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_add(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_add(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_add(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_sub -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_sub(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_sub(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_sub(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_sub(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_mul -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_mul(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_mul(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_mul(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_mul(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_div -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_div(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_div(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_mod -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_mod(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_mod(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_mod(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_mod(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_pow -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_pow(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_pow(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_pow(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_floor_div -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_floor_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_floor_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_floor_div(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_floor_div(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_bit_lshift -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_lshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_lshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_lshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_lshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_bit_rshift -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_rshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_rshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_rshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_rshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_bit_and -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_and(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_and(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_bit_xor -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_xor(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_xor(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_xor(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_xor(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_bit_or -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_bit_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_bit_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_add -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_add(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_add(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_add(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_add(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_sub -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_sub(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_sub(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_sub(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_sub(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_mul -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_mul(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_mul(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_mul(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_mul(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_div -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_div(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_div(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_mod -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_mod(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_mod(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_mod(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_mod(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_pow -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_pow(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_pow(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_pow(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_floor_div -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_floor_div(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_floor_div(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_floor_div(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_floor_div(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_bit_lshift -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_lshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_lshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_lshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_lshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_bit_rshift -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_rshift(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_rshift(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_rshift(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_rshift(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_bit_and -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_and(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_and(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_bit_xor -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_xor(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_xor(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_xor(kclvm_context_t* _ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_xor(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_op_aug_bit_or -// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_op_aug_bit_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_op_aug_bit_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_union -// api-spec(c): kclvm_value_ref_t* kclvm_value_union(kclvm_value_ref_t* schema, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_union(%kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_union(kclvm_context_t* ctx, kclvm_value_ref_t* schema, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_union(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_logic_and -// api-spec(c): kclvm_value_ref_t* kclvm_value_logic_and(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_logic_and(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_logic_and(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_logic_and(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_logic_or -// api-spec(c): kclvm_value_ref_t* kclvm_value_logic_or(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_logic_or(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_logic_or(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_logic_or(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_subscr -// api-spec(c): kclvm_value_ref_t* kclvm_value_subscr(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_subscr(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_subscr(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_subscr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_subscr_option -// api-spec(c): kclvm_value_ref_t* kclvm_value_subscr_option(kclvm_value_ref_t* a, kclvm_value_ref_t* b); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_subscr_option(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); +// api-spec(c): kclvm_value_ref_t* kclvm_value_subscr_option(kclvm_context_t* ctx, kclvm_value_ref_t* a, kclvm_value_ref_t* b); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_subscr_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_load_attr -// api-spec(c): kclvm_value_ref_t* kclvm_value_load_attr(kclvm_value_ref_t* obj, kclvm_char_t* key); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_load_attr(%kclvm_value_ref_t* %obj, %kclvm_char_t* %key); +// api-spec(c): kclvm_value_ref_t* kclvm_value_load_attr(kclvm_context_t* ctx, kclvm_value_ref_t* obj, kclvm_char_t* key); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_load_attr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %obj, %kclvm_char_t* %key); // api-spec: kclvm_value_load_attr_option -// api-spec(c): kclvm_value_ref_t* kclvm_value_load_attr_option(kclvm_value_ref_t* p, kclvm_char_t* key); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_load_attr_option(%kclvm_value_ref_t* %p, %kclvm_char_t* %key); +// api-spec(c): kclvm_value_ref_t* kclvm_value_load_attr_option(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_load_attr_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key); // api-spec: kclvm_value_remove_item // api-spec(c): void kclvm_value_remove_item(kclvm_value_ref_t* a, kclvm_value_ref_t* b); // api-spec(llvm): declare void @kclvm_value_remove_item(%kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b); // api-spec: kclvm_value_slice -// api-spec(c): kclvm_value_ref_t* kclvm_value_slice(kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_slice(%kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); +// api-spec(c): kclvm_value_ref_t* kclvm_value_slice(kclvm_context_t* ctx, kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_slice(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); // api-spec: kclvm_value_slice_option -// api-spec(c): kclvm_value_ref_t* kclvm_value_slice_option(kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_slice_option(%kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); +// api-spec(c): kclvm_value_ref_t* kclvm_value_slice_option(kclvm_context_t* ctx, kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_slice_option(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); // api-spec: kclvm_schema_backtrack_cache -// api-spec(c): void kclvm_schema_backtrack_cache(kclvm_value_ref_t* schema, kclvm_value_ref_t* cache, kclvm_value_ref_t* cal_map, kclvm_char_t* name, kclvm_value_ref_t* runtime_type); -// api-spec(llvm): declare void @kclvm_schema_backtrack_cache(%kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %cache, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %name, %kclvm_value_ref_t* %runtime_type); +// api-spec(c): void kclvm_schema_backtrack_cache(kclvm_context_t* ctx, kclvm_value_ref_t* schema, kclvm_value_ref_t* cache, kclvm_value_ref_t* cal_map, kclvm_char_t* name, kclvm_value_ref_t* runtime_type); +// api-spec(llvm): declare void @kclvm_schema_backtrack_cache(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %cache, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %name, %kclvm_value_ref_t* %runtime_type); // api-spec: kclvm_schema_instances // api-spec(c): kclvm_value_ref_t* kclvm_schema_instances(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_schema_instances(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_schema_value_check -// api-spec(c): void kclvm_schema_value_check(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* schema_config, kclvm_value_ref_t* _config_meta, kclvm_char_t* schema_name, kclvm_value_ref_t* index_sign_value, kclvm_char_t* key_name, kclvm_char_t* key_type, kclvm_char_t* value_type, kclvm_bool_t _any_other); -// api-spec(llvm): declare void @kclvm_schema_value_check(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %schema_config, %kclvm_value_ref_t* %_config_meta, %kclvm_char_t* %schema_name, %kclvm_value_ref_t* %index_sign_value, %kclvm_char_t* %key_name, %kclvm_char_t* %key_type, %kclvm_char_t* %value_type, %kclvm_bool_t %_any_other); +// api-spec(c): void kclvm_schema_value_check(kclvm_context_t* ctx, kclvm_value_ref_t* schema_value, kclvm_value_ref_t* schema_config, kclvm_value_ref_t* _config_meta, kclvm_char_t* schema_name, kclvm_value_ref_t* index_sign_value, kclvm_char_t* key_name, kclvm_char_t* key_type, kclvm_char_t* value_type, kclvm_bool_t _any_other); +// api-spec(llvm): declare void @kclvm_schema_value_check(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %schema_config, %kclvm_value_ref_t* %_config_meta, %kclvm_char_t* %schema_name, %kclvm_value_ref_t* %index_sign_value, %kclvm_char_t* %key_name, %kclvm_char_t* %key_type, %kclvm_char_t* %value_type, %kclvm_bool_t %_any_other); // api-spec: kclvm_schema_do_check_with_index_sign_attr // api-spec(c): void kclvm_schema_do_check_with_index_sign_attr(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, uint64_t* check_fn_ptr, kclvm_char_t* attr_name); // api-spec(llvm): declare void @kclvm_schema_do_check_with_index_sign_attr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, i64* %check_fn_ptr, %kclvm_char_t* %attr_name); // api-spec: kclvm_schema_optional_check -// api-spec(c): void kclvm_schema_optional_check(kclvm_value_ref_t* p); -// api-spec(llvm): declare void @kclvm_schema_optional_check(%kclvm_value_ref_t* %p); +// api-spec(c): void kclvm_schema_optional_check(kclvm_context_t* ctx, kclvm_value_ref_t* p); +// api-spec(llvm): declare void @kclvm_schema_optional_check(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_schema_default_settings -// api-spec(c): void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* config_value, kclvm_char_t* runtime_type); -// api-spec(llvm): declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %config_value, %kclvm_char_t* %runtime_type); +// api-spec(c): void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* runtime_type); +// api-spec(llvm): declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %runtime_type); // api-spec: kclvm_schema_assert -// api-spec(c): void kclvm_schema_assert(kclvm_value_ref_t* value, kclvm_value_ref_t* msg, kclvm_value_ref_t* config_meta); -// api-spec(llvm): declare void @kclvm_schema_assert(%kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg, %kclvm_value_ref_t* %config_meta); +// api-spec(c): void kclvm_schema_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_value_ref_t* msg, kclvm_value_ref_t* config_meta); +// api-spec(llvm): declare void @kclvm_schema_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg, %kclvm_value_ref_t* %config_meta); // api-spec: kclvm_schema_value_new // api-spec(c): kclvm_value_ref_t* kclvm_schema_value_new(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* schema_value_or_func, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* pkgpath); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_schema_value_new(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %schema_value_or_func, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %pkgpath); // api-spec: kclvm_convert_collection_value -// api-spec(c): kclvm_value_ref_t* kclvm_convert_collection_value(kclvm_value_ref_t* value, kclvm_char_t* tpe, kclvm_value_ref_t* is_in_schema); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_convert_collection_value(%kclvm_value_ref_t* %value, %kclvm_char_t* %tpe, %kclvm_value_ref_t* %is_in_schema); +// api-spec(c): kclvm_value_ref_t* kclvm_convert_collection_value(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_char_t* tpe, kclvm_value_ref_t* is_in_schema); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_convert_collection_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_char_t* %tpe, %kclvm_value_ref_t* %is_in_schema); // api-spec: kclvm_schema_get_value -// api-spec(c): kclvm_value_ref_t* kclvm_schema_get_value(kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_value_ref_t* cal_map, kclvm_char_t* target_attr, kclvm_value_ref_t* backtrack_level_map, kclvm_value_ref_t* backtrack_cache, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_schema_get_value(%kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %target_attr, %kclvm_value_ref_t* %backtrack_level_map, %kclvm_value_ref_t* %backtrack_cache, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_schema_get_value(kclvm_context_t* ctx, kclvm_value_ref_t* p, kclvm_char_t* key, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_value_ref_t* cal_map, kclvm_char_t* target_attr, kclvm_value_ref_t* backtrack_level_map, kclvm_value_ref_t* backtrack_cache, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_schema_get_value(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p, %kclvm_char_t* %key, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %target_attr, %kclvm_value_ref_t* %backtrack_level_map, %kclvm_value_ref_t* %backtrack_cache, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_config_attr_map // api-spec(c): void kclvm_config_attr_map(kclvm_value_ref_t* value, kclvm_char_t* name, kclvm_char_t* type_str); // api-spec(llvm): declare void @kclvm_config_attr_map(%kclvm_value_ref_t* %value, %kclvm_char_t* %name, %kclvm_char_t* %type_str); // api-spec: kclvm_value_Decorator -// api-spec(c): kclvm_decorator_value_t* kclvm_value_Decorator(kclvm_char_t* name, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* config_meta, kclvm_char_t* attr_name, kclvm_value_ref_t* config_value, kclvm_value_ref_t* is_schema_target); -// api-spec(llvm): declare %kclvm_decorator_value_t* @kclvm_value_Decorator(%kclvm_char_t* %name, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %attr_name, %kclvm_value_ref_t* %config_value, %kclvm_value_ref_t* %is_schema_target); +// api-spec(c): kclvm_decorator_value_t* kclvm_value_Decorator(kclvm_context_t* ctx, kclvm_char_t* name, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_value_ref_t* config_meta, kclvm_char_t* attr_name, kclvm_value_ref_t* config_value, kclvm_value_ref_t* is_schema_target); +// api-spec(llvm): declare %kclvm_decorator_value_t* @kclvm_value_Decorator(%kclvm_context_t* %ctx, %kclvm_char_t* %name, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %attr_name, %kclvm_value_ref_t* %config_value, %kclvm_value_ref_t* %is_schema_target); // api-spec: kclvm_builtin_str_lower -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_lower(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_lower(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_lower(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_lower(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_upper -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_upper(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_upper(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_upper(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_upper(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_capitalize -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_capitalize(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_capitalize(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_capitalize(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_capitalize(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_count -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_count(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_count(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_count(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_count(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_endswith -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_endswith(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_endswith(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_endswith(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_endswith(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_find -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_find(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_find(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_find(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_find(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_format -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_format(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_format(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_format(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_format(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_str_index -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_index(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_index(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_index(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_index(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_isalnum -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isalnum(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isalnum(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isalnum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isalnum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_isalpha -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isalpha(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isalpha(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isalpha(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isalpha(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_isdigit -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isdigit(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isdigit(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isdigit(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isdigit(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_islower -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_islower(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_islower(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_islower(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_islower(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_isspace -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isspace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isspace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isspace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isspace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_istitle -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_istitle(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_istitle(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_istitle(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_istitle(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_isupper -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isupper(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isupper(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_isupper(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_isupper(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_join -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_join(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_join(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_join(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_join(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_lstrip -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_lstrip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_lstrip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_lstrip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_lstrip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_rstrip -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rstrip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rstrip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rstrip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rstrip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_replace -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_replace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_replace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_replace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_replace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_removeprefix -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_removeprefix(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_removeprefix(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_removeprefix(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_removeprefix(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_removesuffix -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_removesuffix(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_removesuffix(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_removesuffix(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_removesuffix(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_rfind -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rfind(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rfind(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rfind(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rfind(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_rindex -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rindex(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rindex(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rindex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rindex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_rsplit -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rsplit(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rsplit(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_rsplit(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_rsplit(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_str_split -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_split(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_split(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_split(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_split(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_str_splitlines -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_splitlines(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_splitlines(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_splitlines(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_splitlines(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_str_startswith -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_startswith(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_startswith(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_startswith(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_startswith(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_strip -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_strip(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_strip(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_strip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_strip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str_title -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_title(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_title(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str_title(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str_title(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_base64_encode -// api-spec(c): kclvm_value_ref_t* kclvm_base64_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_base64_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_base64_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_base64_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_base64_decode -// api-spec(c): kclvm_value_ref_t* kclvm_base64_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_base64_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_base64_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_base64_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_value_union_all -// api-spec(c): kclvm_value_ref_t* kclvm_value_union_all(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_union_all(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_value_union_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_union_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_md5 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_md5(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_md5(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_md5(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_md5(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_sha1 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha1(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha1(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha1(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha1(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_sha224 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha224(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha224(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha224(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha224(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_sha256 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha256(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha256(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha256(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha256(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_sha384 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha384(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha384(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha384(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha384(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_crypto_sha512 -// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha512(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha512(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_sha512(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_sha512(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_crypto_uuid +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_uuid(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_uuid(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_crypto_filesha256 +// api-spec(c): kclvm_value_ref_t* kclvm_crypto_filesha256(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_crypto_filesha256(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_datetime_today -// api-spec(c): kclvm_value_ref_t* kclvm_datetime_today(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_today(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_datetime_today(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_today(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_datetime_now -// api-spec(c): kclvm_value_ref_t* kclvm_datetime_now(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_now(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_datetime_now(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_now(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_datetime_ticks -// api-spec(c): kclvm_value_ref_t* kclvm_datetime_ticks(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_ticks(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_datetime_ticks(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_ticks(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_datetime_date -// api-spec(c): kclvm_value_ref_t* kclvm_datetime_date(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_date(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_datetime_date(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_datetime_date(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_json_encode -// api-spec(c): kclvm_value_ref_t* kclvm_json_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_json_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_json_decode -// api-spec(c): kclvm_value_ref_t* kclvm_json_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_json_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_json_validate +// api-spec(c): kclvm_value_ref_t* kclvm_json_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_json_dump_to_file -// api-spec(c): kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_manifests_yaml_stream // api-spec(c): void kclvm_manifests_yaml_stream(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); // api-spec(llvm): declare void @kclvm_manifests_yaml_stream(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_math_ceil -// api-spec(c): kclvm_value_ref_t* kclvm_math_ceil(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_ceil(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_ceil(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_ceil(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_factorial -// api-spec(c): kclvm_value_ref_t* kclvm_math_factorial(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_factorial(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_factorial(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_factorial(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_floor -// api-spec(c): kclvm_value_ref_t* kclvm_math_floor(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_floor(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_floor(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_floor(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_gcd -// api-spec(c): kclvm_value_ref_t* kclvm_math_gcd(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_gcd(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_gcd(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_gcd(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_isfinite -// api-spec(c): kclvm_value_ref_t* kclvm_math_isfinite(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isfinite(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_isfinite(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isfinite(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_isinf -// api-spec(c): kclvm_value_ref_t* kclvm_math_isinf(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isinf(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_isinf(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isinf(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_isnan -// api-spec(c): kclvm_value_ref_t* kclvm_math_isnan(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isnan(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_isnan(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_isnan(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_modf -// api-spec(c): kclvm_value_ref_t* kclvm_math_modf(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_modf(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_modf(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_modf(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_exp -// api-spec(c): kclvm_value_ref_t* kclvm_math_exp(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_exp(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_exp(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_exp(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_expm1 -// api-spec(c): kclvm_value_ref_t* kclvm_math_expm1(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_expm1(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_expm1(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_expm1(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_log -// api-spec(c): kclvm_value_ref_t* kclvm_math_log(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_log(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_log1p -// api-spec(c): kclvm_value_ref_t* kclvm_math_log1p(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log1p(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_log1p(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log1p(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_log2 -// api-spec(c): kclvm_value_ref_t* kclvm_math_log2(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log2(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_log2(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log2(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_log10 -// api-spec(c): kclvm_value_ref_t* kclvm_math_log10(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log10(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_log10(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_log10(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_pow -// api-spec(c): kclvm_value_ref_t* kclvm_math_pow(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_pow(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_math_sqrt -// api-spec(c): kclvm_value_ref_t* kclvm_math_sqrt(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_sqrt(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_math_sqrt(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_math_sqrt(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_split_host_port -// api-spec(c): kclvm_value_ref_t* kclvm_net_split_host_port(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_split_host_port(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_split_host_port(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_split_host_port(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_join_host_port -// api-spec(c): kclvm_value_ref_t* kclvm_net_join_host_port(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_join_host_port(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_join_host_port(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_join_host_port(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_fqdn // api-spec(c): kclvm_value_ref_t* kclvm_net_fqdn(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); @@ -1075,75 +927,75 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_to_IP16(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_net_IP_string -// api-spec(c): kclvm_value_ref_t* kclvm_net_IP_string(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_IP_string(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_IP_string(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_IP_string(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_IPv4 -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_IPv4(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_IPv4(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_IPv4(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_IPv4(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_loopback_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_loopback_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_loopback_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_loopback_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_loopback_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_multicast_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_interface_local_multicast_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_interface_local_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_interface_local_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_interface_local_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_interface_local_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_link_local_multicast_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_link_local_multicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_link_local_multicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_link_local_multicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_link_local_multicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_link_local_unicast_IP // api-spec(c): kclvm_value_ref_t* kclvm_net_is_link_local_unicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_link_local_unicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_net_is_global_unicast_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_global_unicast_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_global_unicast_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_global_unicast_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_global_unicast_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_net_is_unspecified_IP -// api-spec(c): kclvm_value_ref_t* kclvm_net_is_unspecified_IP(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_unspecified_IP(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_net_is_unspecified_IP(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_net_is_unspecified_IP(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_match -// api-spec(c): kclvm_value_ref_t* kclvm_regex_match(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_match(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_match(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_match(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_replace -// api-spec(c): kclvm_value_ref_t* kclvm_regex_replace(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_replace(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_replace(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_replace(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_compile -// api-spec(c): kclvm_value_ref_t* kclvm_regex_compile(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_compile(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_compile(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_compile(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_findall -// api-spec(c): kclvm_value_ref_t* kclvm_regex_findall(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_findall(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_findall(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_findall(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_search -// api-spec(c): kclvm_value_ref_t* kclvm_regex_search(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_search(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_search(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_search(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_regex_split -// api-spec(c): kclvm_value_ref_t* kclvm_regex_split(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_split(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_regex_split(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_regex_split(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_assert -// api-spec(c): void kclvm_assert(kclvm_value_ref_t* value, kclvm_value_ref_t* msg); -// api-spec(llvm): declare void @kclvm_assert(%kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg); +// api-spec(c): void kclvm_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_value_ref_t* msg); +// api-spec(llvm): declare void @kclvm_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %value, %kclvm_value_ref_t* %msg); // api-spec: kclvm_builtin_option_init -// api-spec(c): void kclvm_builtin_option_init(kclvm_context_t* ctx, int8_t* key, int8_t* value); +// api-spec(c): void kclvm_builtin_option_init(kclvm_context_t* ctx, char* key, char* value); // api-spec(llvm): declare void @kclvm_builtin_option_init(%kclvm_context_t* %ctx, i8* %key, i8* %value); // api-spec: kclvm_builtin_option_reset @@ -1159,16 +1011,16 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_print(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_len -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_len(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_len(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_len(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_len(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_any_true // api-spec(c): kclvm_value_ref_t* kclvm_builtin_any_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_any_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_isunique -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_isunique(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_isunique(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_isunique(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_isunique(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_sorted // api-spec(c): kclvm_value_ref_t* kclvm_builtin_sorted(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); @@ -1183,56 +1035,56 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_float(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_bool -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_bool(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_bool(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_bool(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_bool(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_str -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_str(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_str(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_max -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_max(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_max(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_max(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_max(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_min -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_min(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_min(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_min(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_min(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_multiplyof -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_multiplyof(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_multiplyof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_multiplyof(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_multiplyof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_abs -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_abs(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_abs(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_abs(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_abs(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_all_true -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_all_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_all_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_all_true(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_all_true(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_hex -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_hex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_hex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_hex(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_hex(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_sum -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_sum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_sum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_sum(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_sum(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_pow -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_pow(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_pow(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_round -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_round(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_round(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_round(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_round(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_zip -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_zip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_zip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_zip(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_zip(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_list -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_list(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_list(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_list(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_list(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_dict // api-spec(c): kclvm_value_ref_t* kclvm_builtin_dict(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); @@ -1243,102 +1095,126 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_typeof(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_builtin_bin -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_bin(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_bin(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_bin(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_bin(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_oct -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_oct(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_oct(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_oct(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_oct(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_ord -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_ord(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_ord(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_ord(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_ord(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_builtin_range -// api-spec(c): kclvm_value_ref_t* kclvm_builtin_range(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_range(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_builtin_range(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_builtin_range(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_plugin_init // api-spec(c): void kclvm_plugin_init(void* fn_ptr); // api-spec(llvm): declare void @kclvm_plugin_init(i8* %fn_ptr); // api-spec: kclvm_plugin_invoke -// api-spec(c): kclvm_value_ref_t* kclvm_plugin_invoke(int8_t* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_plugin_invoke(i8* %method, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_plugin_invoke(kclvm_context_t* ctx, char* method, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_plugin_invoke(%kclvm_context_t* %ctx, i8* %method, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_plugin_invoke_json -// api-spec(c): char* kclvm_plugin_invoke_json(int8_t* method, char* args, char* kwargs); +// api-spec(c): char* kclvm_plugin_invoke_json(char* method, char* args, char* kwargs); // api-spec(llvm): declare i8* @kclvm_plugin_invoke_json(i8* %method, i8* %args, i8* %kwargs); -// api-spec: kclvm_testing_arguments -// api-spec(c): void kclvm_testing_arguments(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare void @kclvm_testing_arguments(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); - -// api-spec: kclvm_testing_setting_file -// api-spec(c): void kclvm_testing_setting_file(kclvm_context_t* _ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare void @kclvm_testing_setting_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); - // api-spec: kclvm_units_to_n -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_n(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_n(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_n(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_n(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_u -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_u(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_u(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_u(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_u(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_m -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_m(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_m(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_m(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_m(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_K -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_K(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_K(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_K(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_K(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_M // api-spec(c): kclvm_value_ref_t* kclvm_units_to_M(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_M(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_units_to_G -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_G(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_G(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_G(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_G(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_T -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_T(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_T(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_T(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_T(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_P -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_P(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_P(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_P(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_P(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_Ki -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Ki(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Ki(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Ki(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Ki(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_Mi -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Mi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Mi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Mi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Mi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_Gi -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Gi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Gi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Gi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Gi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_Ti -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Ti(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Ti(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Ti(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Ti(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_units_to_Pi -// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Pi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Pi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_units_to_Pi(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_units_to_Pi(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_yaml_encode -// api-spec(c): kclvm_value_ref_t* kclvm_yaml_encode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_encode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); + +// api-spec: kclvm_yaml_encode_all +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_encode_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_encode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_yaml_decode -// api-spec(c): kclvm_value_ref_t* kclvm_yaml_decode(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_decode(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_yaml_decode_all +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_decode_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_decode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_yaml_dump_to_file -// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); + +// api-spec: kclvm_yaml_dump_all_to_file +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); + +// api-spec: kclvm_yaml_validate +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_file_read +// api-spec(c): kclvm_value_ref_t* kclvm_file_read(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_file_read(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_file_glob +// api-spec(c): kclvm_value_ref_t* kclvm_file_glob(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_file_glob(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_file_modpath +// api-spec(c): kclvm_value_ref_t* kclvm_file_modpath(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_file_modpath(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); + +// api-spec: kclvm_file_workdir +// api-spec(c): kclvm_value_ref_t* kclvm_file_workdir(kclvm_context_t* ctx, kclvm_value_ref_t* _args, kclvm_value_ref_t* _kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_file_workdir(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %_args, %kclvm_value_ref_t* %_kwargs); diff --git a/kclvm/runtime/src/_kclvm_main_win.c b/kclvm/runtime/src/_kclvm_main_win.c index 917efac53..4e6473fdb 100644 --- a/kclvm/runtime/src/_kclvm_main_win.c +++ b/kclvm/runtime/src/_kclvm_main_win.c @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. extern void* kclvm_main(void* ctx); diff --git a/kclvm/runtime/src/api/buf.rs b/kclvm/runtime/src/api/buf.rs deleted file mode 100644 index 13de03676..000000000 --- a/kclvm/runtime/src/api/buf.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -use crate::*; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_bool_t = i8; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_char_t = i8; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_size_t = i32; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_buffer_t = Buffer; - -#[allow(dead_code, non_camel_case_types)] -pub type kclvm_value_t = Value; - -#[repr(C)] -#[derive(Debug, Clone, Default)] -pub struct Buffer { - buf: Vec, -} - -impl Buffer { - #[allow(dead_code)] - pub fn new_with_buf(buf: &[u8]) -> Self { - Buffer { buf: buf.to_vec() } - } - - #[allow(dead_code)] - pub fn into_raw(self) -> *mut Self { - Box::into_raw(Box::new(self)) - } - - #[allow(dead_code)] - pub fn malloc(size: usize) -> *mut u8 { - let p = Box::into_raw(Box::new(Buffer { - buf: vec![0u8; size + 8], - })); - - unsafe { - let data_ptr = (*p).buf.as_ptr() as *mut u8; - let u64bytes = (p as u64).to_le_bytes(); - (*p).buf[..8].clone_from_slice(&u64bytes[..8]); - data_ptr.add(8) - } - } - - #[allow(dead_code)] - pub fn free(_data_ptr: *mut u8) { - unsafe { - let p = u64::from_le_bytes( - std::slice::from_raw_parts(((_data_ptr as u64) - 8) as *const u8, 8) - .try_into() - .unwrap(), - ) as *mut Self; - - drop(Box::from_raw(p)); - } - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_buffer_new(size: kclvm_size_t) -> *mut kclvm_buffer_t { - let mut p = Buffer { buf: Vec::new() }; - p.buf.resize(size as usize, 0); - Box::into_raw(Box::new(p)) -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_buffer_delete(p: *mut kclvm_buffer_t) { - free_mut_ptr(p) -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_buffer_size(p: *const kclvm_buffer_t) -> kclvm_size_t { - let p = ptr_as_ref(p); - p.buf.len() as kclvm_size_t -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_buffer_data(p: *const kclvm_buffer_t) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - if !p.buf.is_empty() { - p.buf.as_ptr() as *const kclvm_char_t - } else { - std::ptr::null() - } -} diff --git a/kclvm/runtime/src/api/err_type.rs b/kclvm/runtime/src/api/err_type.rs deleted file mode 100644 index b36faf3e0..000000000 --- a/kclvm/runtime/src/api/err_type.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -// Auto generated, DONOT EDIT!!! - -// python: kclvm.kcl.error.ErrType - -#[derive(Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum ErrType { - InvalidSyntax_TYPE = 0, - TabError_TYPE = 1, - IndentationError_TYPE = 2, - CannotFindModule_TYPE = 3, - FailedLoadModule_TYPE = 4, - CompileError_TYPE = 5, - EvaluationError_TYPE = 6, - RecursiveLoad_TYPE = 7, - FloatOverflow_TYPE = 8, - FloatUnderflow_TYPE = 9, - IntOverflow_TYPE = 10, - InvalidDocstring_TYPE = 11, - Deprecated_TYPE = 12, - UnKnownDecorator_TYPE = 13, - InvalidDecoratorTarget_TYPE = 14, - InvalidFormatSpec_TYPE = 15, - SelectorError_TYPE = 16, - SchemaCheckFailure_TYPE = 17, - MixinNamingError_TYPE = 18, - MixinStructureIllegal_TYPE = 19, - IndexSignatureError_TYPE = 20, - TypeError_Runtime_TYPE = 21, - TypeError_Compile_TYPE = 22, - NameError_TYPE = 23, - ValueError_TYPE = 24, - KeyError_TYPE = 25, - UniqueKeyError_TYPE = 26, - AttributeError_TYPE = 27, - AttributeError_Runtime_TYPE = 28, - AssertionError_TYPE = 29, - ImmutableCompileError_TYPE = 30, - ImmutableRuntimeError_TYPE = 31, - MultiInheritError_TYPE = 32, - CycleInheritError_TYPE = 33, - IllegalInheritError_TYPE = 34, - IllegalAttributeError_TYPE = 35, - IllegalArgumentError_TYPE = 36, - IllegalArgumentError_Complie_TYPE = 37, - IllegalArgumentError_Syntax_TYPE = 38, - RecursionError_TYPE = 39, - PlanError_TYPE = 40, - Deprecated_Warning_TYPE = 41, - CannotAddMembers_TYPE = 42, - CannotAddMembers_Runtime_TYPE = 43, -} diff --git a/kclvm/runtime/src/api/error.rs b/kclvm/runtime/src/api/error.rs new file mode 100644 index 000000000..5a5578493 --- /dev/null +++ b/kclvm/runtime/src/api/error.rs @@ -0,0 +1,16 @@ +//! Copyright The KCL Authors. All rights reserved. + +#[derive(Copy, Clone)] +#[allow(non_camel_case_types)] +pub enum RuntimeErrorType { + EvaluationError = 1, + RecursiveLoad = 2, + FloatOverflow = 3, + FloatUnderflow = 4, + IntOverflow = 5, + TypeError = 6, + AssertionError = 7, + Deprecated = 8, + DeprecatedWarning = 9, + SchemaCheckFailure = 10, +} diff --git a/kclvm/runtime/src/api/kclvm.rs b/kclvm/runtime/src/api/kclvm.rs index 7c38573fc..1e67e2686 100644 --- a/kclvm/runtime/src/api/kclvm.rs +++ b/kclvm/runtime/src/api/kclvm.rs @@ -1,70 +1,50 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = crate::ValueRef; -use crate::{new_mut_ptr, IndexMap}; +use crate::{new_mut_ptr, IndexMap, PlanOptions}; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; +use std::panic::{RefUnwindSafe, UnwindSafe}; +use std::rc::Rc; use std::{ cell::RefCell, cmp::Ordering, hash::{Hash, Hasher}, - rc::Rc, }; +/* + * Single instance name constants Undefined, None, True, False + */ #[allow(non_upper_case_globals)] pub const UNDEFINED: Value = Value::undefined; - #[allow(non_upper_case_globals)] pub const NONE: Value = Value::none; - #[allow(non_upper_case_globals)] pub const TRUE: Value = Value::bool_value(true); - #[allow(non_upper_case_globals)] pub const FALSE: Value = Value::bool_value(false); -#[derive(PartialEq, Eq, Clone, Default, Debug)] -pub struct KclError { - pub err_code: i32, - pub err_text: String, - pub filename: String, - pub source_code: String, - pub line: i32, - pub column: i32, -} +/* + * Runtime types + */ -#[allow(non_camel_case_types)] -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, Default)] pub enum Type { - any_type, - bool_type, - bool_lit_type(bool), - int_type, - int_lit_type(i64), - float_type, - float_lit_type(f64), - str_type, - str_lit_type(String), - list_type(ListType), - dict_type(DictType), - union_type(UnionType), - schema_type(SchemaType), - func_type(FuncType), -} - -impl Default for Type { - fn default() -> Self { - Type::any_type - } -} - -impl Type { - #[allow(dead_code)] - pub fn into_raw(self) -> *mut Self { - Box::into_raw(Box::new(self)) - } + #[default] + Any, + Bool, + BoolLit(bool), + Int, + IntLit(i64), + Float, + FloatLit(f64), + Str, + StrLit(String), + List(ListType), + Dict(DictType), + Union(UnionType), + Schema(SchemaType), + Func(FuncType), } #[derive(PartialEq, Clone, Default, Debug)] @@ -83,12 +63,17 @@ pub struct UnionType { pub elem_types: Vec, } +/// The runtime schema type. #[derive(PartialEq, Clone, Default, Debug)] pub struct SchemaType { + /// The schema runtime type name. pub name: String, - pub parent_name: String, - pub field_names: Vec, - pub field_types: Vec, + /// Schema attributes. + pub attrs: IndexMap, + /// Schema index signature. + pub has_index_signature: bool, + /// Schema runtime function value. + pub func: ValueRef, } #[derive(PartialEq, Clone, Default, Debug)] @@ -151,8 +136,8 @@ impl PartialOrd for ValueRef { impl Hash for ValueRef { fn hash(&self, state: &mut H) { match &*self.rc.borrow() { - Value::undefined => panic!("unsupport hash for undefined"), - Value::none => panic!("unsupport hash for none"), + Value::undefined => 0.hash(state), + Value::none => 0.hash(state), Value::int_value(v) => (*v as f64).to_bits().hash(state), Value::unit_value(_real, raw, unit) => { raw.hash(state); @@ -199,12 +184,12 @@ impl ValueRef { std::ptr::eq(&*self.rc.borrow(), &*x.rc.borrow()) } - pub fn into_raw(self) -> *mut Self { - new_mut_ptr(self) + pub fn into_raw(self, ctx: &mut Context) -> *mut Self { + new_mut_ptr(ctx, self) } pub fn from_raw(&self) { - //if value is a func,clear captured ValueRef to break circular reference + // If value is a func, clear the captured ValueRef to break circular reference. if let Value::func_value(val) = &mut *self.rc.borrow_mut() { val.closure = ValueRef::none(); } @@ -244,6 +229,8 @@ pub struct DictValue { pub ops: IndexMap, pub insert_indexs: IndexMap, pub attr_map: IndexMap, + // The runtime dict to schema reflect type string. + pub potential_schema: Option, } #[derive(PartialEq, Clone, Default, Debug)] @@ -256,6 +243,10 @@ pub struct SchemaValue { pub config_meta: ValueRef, /// This map stores which attributes of the schema are optional and which are required. pub optional_mapping: ValueRef, + /// Schema instance argument values + pub args: ValueRef, + /// Schema instance keyword argument values + pub kwargs: ValueRef, } #[derive(PartialEq, Eq, Clone, Default, Debug)] @@ -267,7 +258,6 @@ pub struct DecoratorValue { #[derive(PartialEq, Eq, Clone, Default, Debug)] pub struct FuncValue { - // TODO (refactor): SchemaFuncValue pub fn_ptr: u64, pub check_fn_ptr: u64, pub closure: ValueRef, @@ -276,15 +266,10 @@ pub struct FuncValue { pub is_external: bool, } -#[derive(PartialEq, Clone, Default, Debug)] -pub struct ErrorValue { - pub errors: Vec, -} - #[derive(PartialEq, Eq, Clone, Default, Debug)] pub struct OptionHelp { pub name: String, - pub typ: String, + pub ty: String, pub required: bool, pub default_value: Option, pub help: String, @@ -293,7 +278,10 @@ pub struct OptionHelp { #[allow(non_snake_case)] #[derive(PartialEq, Eq, Clone, Default, Debug, Serialize, Deserialize)] pub struct PanicInfo { - pub __kcl_PanicInfo__: bool, // "__kcl_PanicInfo__" + // Used to distinguish whether it is an error + // message JSON or a program run result. + #[serde(rename = "__kcl_PanicInfo__")] + pub __kcl_PanicInfo__: bool, pub backtrace: Vec, pub rust_file: String, @@ -307,7 +295,7 @@ pub struct PanicInfo { pub kcl_col: i32, pub kcl_arg_msg: String, - // only for schema check + // Only for schema check failed error message pub kcl_config_meta_file: String, pub kcl_config_meta_line: i32, pub kcl_config_meta_col: i32, @@ -321,15 +309,9 @@ pub struct PanicInfo { #[derive(PartialEq, Eq, Clone, Default, Debug)] pub struct ContextConfig { pub debug_mode: bool, - pub strict_range_check: bool, pub disable_schema_check: bool, - pub list_option_mode: bool, - // Whether to emit none value in the plan process. - pub disable_none: bool, - // Whether to output empty list in the plan process. - pub plan_empty_list: bool, } #[derive(PartialEq, Eq, Clone, Debug)] @@ -348,50 +330,48 @@ impl Default for ContextBuffer { } } -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct ContextOutput { - pub stdout: String, - pub stderr: String, - - pub return_value: *mut kclvm_value_ref_t, // *mut kclvm_value_ref_t -} - -impl Default for ContextOutput { - fn default() -> Self { - Self { - stdout: "".to_string(), - stderr: "".to_string(), - return_value: std::ptr::null_mut(), - } - } -} - #[derive(PartialEq, Clone, Default, Debug)] pub struct Context { + /// Runtime evaluation config. pub cfg: ContextConfig, - pub output: ContextOutput, - pub panic_info: PanicInfo, - pub main_pkg_path: String, - pub main_pkg_files: Vec, + /// kcl.mod path or the pwd path + pub module_path: String, + /// Program work directory + pub workdir: String, pub backtrace: Vec, - + /// Imported package path to check the cyclic import process. pub imported_pkgpath: HashSet, + /// Runtime arguments for the option function. pub app_args: HashMap, - pub instances: RefCell>>, - pub all_types: Vec, - pub all_schemas: RefCell>, + /// All schema instances + pub instances: HashMap>, + /// All schema types + pub all_schemas: HashMap, + /// Import graph pub import_names: IndexMap>, - pub symbol_names: Vec, - pub symbol_values: Vec, - pub func_handlers: Vec, + /// All option function calling help messages. pub option_helps: Vec, + /// A buffer to store plugin or hooks function calling results. pub buffer: ContextBuffer, - /// objects is to store all KCL object pointers. + /// Objects is to store all KCL object pointers at runtime. pub objects: IndexSet, + /// Log message used to store print results. + pub log_message: String, + /// Planned JSON result + pub json_result: String, + /// Planned YAML result + pub yaml_result: String, + /// Panic information at runtime + pub panic_info: PanicInfo, + /// Planning options + pub plan_opts: PlanOptions, } +impl UnwindSafe for Context {} +impl RefUnwindSafe for Context {} + #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] pub struct BacktraceFrame { pub file: String, @@ -424,7 +404,7 @@ impl BacktraceFrame { impl Context { pub fn new() -> Self { Context { - instances: RefCell::new(HashMap::new()), + instances: HashMap::new(), panic_info: PanicInfo { kcl_func: "kclvm_main".to_string(), ..Default::default() @@ -464,19 +444,14 @@ pub enum Kind { Func = 18, } -#[derive(Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash, Default)] pub enum ConfigEntryOperationKind { + #[default] Union = 0, Override = 1, Insert = 2, } -impl Default for ConfigEntryOperationKind { - fn default() -> Self { - ConfigEntryOperationKind::Union - } -} - impl ConfigEntryOperationKind { pub fn from_i32(v: i32) -> Self { match v { diff --git a/kclvm/runtime/src/api/malloc.rs b/kclvm/runtime/src/api/malloc.rs deleted file mode 100644 index fb4deec35..000000000 --- a/kclvm/runtime/src/api/malloc.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use crate::*; - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_malloc(n: i32) -> *mut u8 { - Buffer::malloc(n as usize) -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_free(ptr: *mut u8) { - Buffer::free(ptr); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_strlen(ptr: *mut u8) -> kclvm_size_t { - unsafe { - let mut p = ptr; - while *p != b'\0' { - p = p.add(1); - } - (p as i32) - (ptr as i32) - } -} diff --git a/kclvm/runtime/src/api/mod.rs b/kclvm/runtime/src/api/mod.rs index 45eacd222..d9ceae469 100644 --- a/kclvm/runtime/src/api/mod.rs +++ b/kclvm/runtime/src/api/mod.rs @@ -1,16 +1,10 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod kclvm; pub use self::kclvm::*; -pub mod buf; -pub use self::buf::*; - -pub mod malloc; -pub use self::malloc::*; - pub mod utils; pub use self::utils::*; -pub mod err_type; -pub use self::err_type::*; +pub mod error; +pub use self::error::*; diff --git a/kclvm/runtime/src/api/utils.rs b/kclvm/runtime/src/api/utils.rs index 0da949ee4..cf69824d6 100644 --- a/kclvm/runtime/src/api/utils.rs +++ b/kclvm/runtime/src/api/utils.rs @@ -1,12 +1,14 @@ -// Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] +//! Copyright The KCL Authors. All rights reserved. -use crate::{kclvm_value_Undefined, Context, ValueRef}; +use std::os::raw::c_char; + +use crate::{kclvm_size_t, Context, ValueRef}; /// New a mutable raw pointer. -pub fn new_mut_ptr(x: ValueRef) -> *mut ValueRef { +/// Safety: The caller must ensure that `ctx` lives longer than the returned pointer +/// and that the pointer is properly deallocated by calling `free_mut_ptr`. +pub fn new_mut_ptr(ctx: &mut Context, x: ValueRef) -> *mut ValueRef { let ptr = Box::into_raw(Box::new(x)); - let ctx = Context::current_context_mut(); // Store the object pointer address to // drop it it after execution is complete ctx.objects.insert(ptr as usize); @@ -14,7 +16,8 @@ pub fn new_mut_ptr(x: ValueRef) -> *mut ValueRef { } /// Free a mutable raw pointer. -pub fn free_mut_ptr(p: *mut T) { +/// Safety: The caller must ensure `p` is a valid pointer obtained from `new_mut_ptr`. +pub(crate) fn free_mut_ptr(p: *mut T) { if !p.is_null() { unsafe { drop(Box::from_raw(p)); @@ -23,51 +26,58 @@ pub fn free_mut_ptr(p: *mut T) { } /// Convert a const raw pointer to a immutable borrow. -pub fn ptr_as_ref<'a, T>(p: *const T) -> &'a T { - unsafe { - if p.is_null() { - let v = kclvm_value_Undefined(); - ptr_as_ref(v as *const T) - } else { - &*p - } - } +/// Safety: The caller must ensure that `p` is valid for the lifetime `'a`. +pub(crate) fn ptr_as_ref<'a, T>(p: *const T) -> &'a T { + assert!(!p.is_null()); + unsafe { &*p } } /// Convert a mutable raw pointer to a mutable borrow. -pub unsafe fn mut_ptr_as_ref<'a, T>(p: *mut T) -> &'a mut T { +/// Safety: The caller must ensure that `p` is valid for the lifetime `'a`. +pub(crate) fn mut_ptr_as_ref<'a, T>(p: *mut T) -> &'a mut T { assert!(!p.is_null()); - if p.is_null() { - let v = kclvm_value_Undefined(); - mut_ptr_as_ref(v as *mut T) - } else { - unsafe { &mut *p } + unsafe { &mut *p } +} + +/// Copy str to mutable pointer with length +pub(crate) fn copy_str_to(v: &str, p: *mut c_char, size: *mut kclvm_size_t) { + unsafe { + let c_str_ptr = v.as_ptr() as *const c_char; + let c_str_len = v.len() as i32; + if c_str_len <= *size { + std::ptr::copy(c_str_ptr, p, c_str_len as usize); + *size = c_str_len + } } } /// Convert a C str pointer to a Rust &str. -pub fn c2str<'a>(s: *const i8) -> &'a str { - let s = unsafe { std::ffi::CStr::from_ptr(s) }.to_str().unwrap(); +/// Safety: The caller must ensure that `s` is a valid null-terminated C string. +pub fn c2str<'a>(p: *const c_char) -> &'a str { + let s = unsafe { std::ffi::CStr::from_ptr(p) }.to_str().unwrap(); s } -/// Convert a raw double pinter to a Rust Vec. -pub fn convert_double_pointer_to_vec(data: &mut &mut i8, len: usize) -> Vec { +/// Convert a C str pointer pointer to a Rust Vec. +pub fn c2str_vec(ptr_array: *const *const c_char) -> Vec { + let mut result = Vec::new(); + let mut index = 0; + unsafe { - match std::slice::from_raw_parts(data, len) - .iter() - .map(|arg| { - std::ffi::CStr::from_ptr(*arg) - .to_str() - .map(ToString::to_string) - }) - .collect() - { - Err(_error) => Vec::::new(), - Ok(x) => x, + loop { + let current_ptr = *ptr_array.offset(index); + if current_ptr.is_null() { + break; + } + let c_str = std::ffi::CStr::from_ptr(current_ptr); + let rust_string = c_str.to_string_lossy().to_string(); + result.push(rust_string); + index += 1; } } + + result } pub fn assert_panic(msg: &str, func: F) { diff --git a/kclvm/runtime/src/base64/base64.rs b/kclvm/runtime/src/base64/base64.rs deleted file mode 100644 index 577760e65..000000000 --- a/kclvm/runtime/src/base64/base64.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. -extern crate base64; -use base64::{decode, encode}; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_base64_encode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - let p = args.arg_0().unwrap(); - match &*p.rc.borrow() { - Value::str_value(x) => { - let s = encode(x.clone()); - return ValueRef::str(s.as_str()).into_raw(); - } - _ => { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::TypeError_Runtime_TYPE); - - panic!("a bytes-like object is required, not '{}'", p.as_str()); - } - }; -} - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_base64_decode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - let p = args.arg_0().unwrap(); - match &*p.rc.borrow() { - Value::str_value(x) => { - let de_str = decode(x.clone()).unwrap(); - return ValueRef::str(std::str::from_utf8(&de_str).unwrap()).into_raw(); - } - _ => { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::TypeError_Runtime_TYPE); - - panic!( - "argument should be a bytes-like object or ASCII string, not '{}'", - p.as_str() - ); - } - }; -} diff --git a/kclvm/runtime/src/base64/mod.rs b/kclvm/runtime/src/base64/mod.rs index e56a77ea1..58cd2b6e8 100644 --- a/kclvm/runtime/src/base64/mod.rs +++ b/kclvm/runtime/src/base64/mod.rs @@ -1,4 +1,52 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod base64; -pub use self::base64::*; +extern crate base64; +use base64::{decode, encode}; + +use crate::*; + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_base64_encode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + let p = args.arg_0().unwrap(); + match &*p.rc.borrow() { + Value::str_value(x) => { + let s = encode(x.clone()); + return ValueRef::str(s.as_str()).into_raw(ctx); + } + _ => { + ctx.set_err_type(&RuntimeErrorType::TypeError); + + panic!("a string object is required, not '{}'", p.as_str()); + } + }; +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_base64_decode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + let p = args.arg_0().unwrap(); + match &*p.rc.borrow() { + Value::str_value(x) => { + let de_str = decode(x.clone()).unwrap(); + return ValueRef::str(std::str::from_utf8(&de_str).unwrap()).into_raw(ctx); + } + _ => { + ctx.set_err_type(&RuntimeErrorType::TypeError); + + panic!("argument should be a string object, not '{}'", p.as_str()); + } + }; +} diff --git a/kclvm/runtime/src/collection/collection.rs b/kclvm/runtime/src/collection/collection.rs deleted file mode 100644 index b7e1dad98..000000000 --- a/kclvm/runtime/src/collection/collection.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! KCL collection system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_value_union_all( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - if let Some(arg) = args.arg_0() { - if !arg.is_truthy() || !arg.is_list() { - return ValueRef::dict(None).into_raw(); - } - let value = arg.as_list_ref(); - if value.values.is_empty() { - return ValueRef::dict(None).into_raw(); - } - let mut result = value.values[0].deep_copy(); - for (i, v) in value.values.iter().enumerate() { - if i > 0 { - result.bin_aug_union_with(v); - } - } - return result.into_raw(); - } - panic!("union_all() takes at least 1 argument (0 given)") -} diff --git a/kclvm/runtime/src/collection/mod.rs b/kclvm/runtime/src/collection/mod.rs index 552ad5847..7f4a02aa1 100644 --- a/kclvm/runtime/src/collection/mod.rs +++ b/kclvm/runtime/src/collection/mod.rs @@ -1,4 +1,31 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod collection; -pub use self::collection::*; +use crate::*; + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_value_union_all( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(arg) = args.arg_0() { + if !arg.is_truthy() || !arg.is_list() { + return ValueRef::dict(None).into_raw(ctx); + } + let value = arg.as_list_ref(); + if value.values.is_empty() { + return ValueRef::dict(None).into_raw(ctx); + } + let mut result = value.values[0].deep_copy(); + for (i, v) in value.values.iter().enumerate() { + if i > 0 { + result.bin_aug_union_with(ctx, v); + } + } + return result.into_raw(ctx); + } + panic!("union_all() takes at least 1 argument (0 given)") +} diff --git a/kclvm/runtime/src/context/api.rs b/kclvm/runtime/src/context/api.rs index 5f7cdca7c..7d50380c3 100644 --- a/kclvm/runtime/src/context/api.rs +++ b/kclvm/runtime/src/context/api.rs @@ -1,14 +1,16 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #![allow(clippy::missing_safety_doc)] use crate::*; use std::os::raw::c_char; +use self::eval::LazyEvalScope; + #[allow(dead_code, non_camel_case_types)] type kclvm_context_t = Context; #[allow(dead_code, non_camel_case_types)] -type kclvm_error_t = KclError; +type kclvm_eval_scope_t = LazyEvalScope; #[allow(dead_code, non_camel_case_types)] type kclvm_kind_t = Kind; @@ -20,7 +22,7 @@ type kclvm_type_t = Type; type kclvm_value_t = Value; #[allow(dead_code, non_camel_case_types)] -type kclvm_char_t = i8; +type kclvm_char_t = c_char; #[allow(dead_code, non_camel_case_types)] type kclvm_size_t = i32; @@ -38,30 +40,10 @@ type kclvm_float_t = f64; // new/delete // ---------------------------------------------------------------------------- -// singleton - -#[allow(non_camel_case_types, non_upper_case_globals)] -static mut _kclvm_context_current: u64 = 0; - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_context_current() -> *mut kclvm_context_t { - unsafe { - if _kclvm_context_current == 0 { - _kclvm_context_current = kclvm_context_new() as u64; - } - _kclvm_context_current as *mut kclvm_context_t - } -} - #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_context_new() -> *mut kclvm_context_t { - let p = Box::into_raw(Box::new(Context::new())); - unsafe { - _kclvm_context_current = p as u64; - } - p + Box::into_raw(Box::new(Context::new())) } #[no_mangle] @@ -72,35 +54,9 @@ pub unsafe extern "C" fn kclvm_context_delete(p: *mut kclvm_context_t) { let ptr = (*o) as *mut kclvm_value_ref_t; kclvm_value_delete(ptr); } - unsafe { - //todo: remove global _kclvm_context_current - //set _kclvm_context_current to null to invoid internal unsoundness - _kclvm_context_current = 0; - } free_mut_ptr(p); } -// ---------------------------------------------------------------------------- -// main begin/end -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_context_main_begin_hook(p: *mut kclvm_context_t) { - let p = mut_ptr_as_ref(p); - p.main_begin_hook(); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_context_main_end_hook( - p: *mut kclvm_context_t, - return_value: *mut kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let p = mut_ptr_as_ref(p); - p.main_end_hook(return_value) -} - // ---------------------------------------------------------------------------- // panic_info // ---------------------------------------------------------------------------- @@ -109,7 +65,7 @@ pub unsafe extern "C" fn kclvm_context_main_end_hook( #[runtime_fn] pub unsafe extern "C" fn kclvm_context_set_kcl_location( p: *mut kclvm_context_t, - filename: *const i8, + filename: *const c_char, line: i32, col: i32, ) { @@ -125,7 +81,7 @@ pub unsafe extern "C" fn kclvm_context_set_kcl_location( #[runtime_fn] pub unsafe extern "C" fn kclvm_context_set_kcl_pkgpath( p: *mut kclvm_context_t, - pkgpath: *const i8, + pkgpath: *const c_char, ) { let p = mut_ptr_as_ref(p); if !pkgpath.is_null() { @@ -135,135 +91,127 @@ pub unsafe extern "C" fn kclvm_context_set_kcl_pkgpath( #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_set_kcl_filename(filename: *const i8) { - let p = Context::current_context_mut(); - if !filename.is_null() { - p.set_kcl_filename(c2str(filename)); +pub unsafe extern "C" fn kclvm_context_set_kcl_modpath( + p: *mut kclvm_context_t, + module_path: *const c_char, +) { + let p = mut_ptr_as_ref(p); + if !module_path.is_null() { + p.set_kcl_module_path(c2str(module_path)); } } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_set_kcl_line_col(line: i32, col: i32) { - let p = Context::current_context_mut(); - p.set_kcl_line_col(line, col); +pub unsafe extern "C" fn kclvm_context_set_kcl_workdir( + p: *mut kclvm_context_t, + workdir: *const c_char, +) { + let p = mut_ptr_as_ref(p); + if !workdir.is_null() { + p.set_kcl_workdir(c2str(workdir)); + } } -// ---------------------------------------------------------------------------- -// manage types -// ---------------------------------------------------------------------------- - #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_put_type(p: *mut kclvm_context_t, typ: *const kclvm_type_t) { - let p = mut_ptr_as_ref(p); - let typ = ptr_as_ref(typ); - - p.all_types.push(typ.clone()); +pub unsafe extern "C" fn kclvm_context_set_kcl_filename( + ctx: *mut kclvm_context_t, + filename: *const c_char, +) { + let ctx = mut_ptr_as_ref(ctx); + if !filename.is_null() { + ctx.set_kcl_filename(c2str(filename)); + } } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_clear_all_types(p: *mut kclvm_context_t) { - let p = mut_ptr_as_ref(p); - p.all_types.clear(); +pub unsafe extern "C" fn kclvm_context_set_kcl_line_col( + ctx: *mut kclvm_context_t, + line: i32, + col: i32, +) { + let ctx = mut_ptr_as_ref(ctx); + ctx.set_kcl_line_col(line, col); } // ---------------------------------------------------------------------------- -// symbol +// Global values and evaluation scope. // ---------------------------------------------------------------------------- #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_symbol_init( - p: *mut kclvm_context_t, - n: kclvm_size_t, - symbol_names: *const *const kclvm_char_t, -) { - let p = mut_ptr_as_ref(p); - - unsafe { - p.symbol_names.clear(); - p.symbol_values.clear(); - - let _ = std::slice::from_raw_parts(symbol_names, n as usize) - .iter() - .map(|arg| { - p.symbol_names.push(c2str(*arg).to_string()); - p.symbol_values.push(Value::default()); - }); - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_context_symbol_num(p: *const kclvm_context_t) -> kclvm_size_t { - let p = ptr_as_ref(p); - - p.symbol_names.len() as kclvm_size_t +pub unsafe extern "C" fn kclvm_scope_new() -> *mut kclvm_eval_scope_t { + Box::into_raw(Box::new(LazyEvalScope::default())) } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_symbol_name( - p: *const kclvm_context_t, - i: kclvm_size_t, -) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - return match p.symbol_names.get(i as usize) { - Some(value) => value.as_bytes().as_ptr() as *const kclvm_char_t, - None => std::ptr::null(), - }; +pub unsafe extern "C" fn kclvm_scope_free(scope: *mut kclvm_eval_scope_t) { + drop(Box::from_raw(scope)); } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_symbol_value( - p: *const kclvm_context_t, - i: kclvm_size_t, -) -> *const kclvm_value_t { - let p = ptr_as_ref(p); - match p.symbol_values.get(i as usize) { - Some(v) => v as *const kclvm_value_t, - None => std::ptr::null(), +pub unsafe extern "C" fn kclvm_scope_add_setter( + _ctx: *mut kclvm_context_t, + scope: *mut kclvm_eval_scope_t, + pkg: *const c_char, + name: *const c_char, + setter: *const u64, +) { + let scope = mut_ptr_as_ref(scope); + let pkg = c2str(pkg); + let name = c2str(name); + let key = format!("{}.{}", pkg, name); + if !scope.setters.contains_key(&key) { + scope.setters.insert(key.clone(), vec![]); + } + if let Some(setters) = scope.setters.get_mut(&key) { + setters.push(setter as u64); } -} - -// ---------------------------------------------------------------------------- -// args -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_context_args_get( - _p: *const kclvm_context_t, - _key: *const kclvm_char_t, -) -> *const kclvm_char_t { - //let p = ptr_as_ref(p); - //match p.app_args.get(c2str(key)) { - // Some(value) => (*value).as_bytes().as_ptr() as *const kclvm_char_t, - // None => std::ptr::null(), - //}; - std::ptr::null() } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_args_set( - _p: *mut kclvm_context_t, - _key: *const kclvm_char_t, - _value: *const kclvm_char_t, +pub unsafe extern "C" fn kclvm_scope_set( + _ctx: *mut kclvm_context_t, + scope: *mut kclvm_eval_scope_t, + pkg: *const c_char, + name: *const c_char, + value: *const kclvm_value_ref_t, ) { - //let p = mut_ptr_as_ref(p); - //p.app_args - // .insert(c2str(key).to_string(), c2str(value).to_string()); + let scope = mut_ptr_as_ref(scope); + let value = ptr_as_ref(value); + let pkg = c2str(pkg); + let name = c2str(name); + let key = format!("{}.{}", pkg, name); + scope.set_value(&key, value); } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_context_args_clear(p: *mut kclvm_context_t) { - let p = mut_ptr_as_ref(p); - p.app_args.clear(); +pub unsafe extern "C" fn kclvm_scope_get( + ctx: *mut kclvm_context_t, + scope: *mut kclvm_eval_scope_t, + pkg: *const c_char, + name: *const c_char, + target: *const c_char, + default: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let scope = mut_ptr_as_ref(scope); + let pkg = c2str(pkg); + let name = c2str(name); + let target = format!("{}.{}", pkg, c2str(target)); + let key = format!("{}.{}", pkg, name); + // Existing values or existing but not yet calculated values. + if scope.contains_key(&key) || scope.setters.contains_key(&key) { + scope.get_value(ctx, &key, &target).into_raw(ctx) + } else { + default + } } // ---------------------------------------------------------------------------- @@ -291,7 +239,7 @@ pub unsafe extern "C" fn kclvm_context_set_strict_range_check( #[runtime_fn] pub unsafe extern "C" fn kclvm_context_set_disable_none(p: *mut kclvm_context_t, v: kclvm_bool_t) { let p = mut_ptr_as_ref(p); - p.cfg.disable_none = v != 0; + p.plan_opts.disable_none = v != 0; } #[no_mangle] @@ -329,12 +277,12 @@ pub unsafe extern "C" fn kclvm_context_invoke( let p = mut_ptr_as_ref(p); let method = c2str(method); - let args = kclvm_value_from_json(args); - let kwargs = kclvm_value_from_json(kwargs); + let args = kclvm_value_from_json(p, args); + let kwargs = kclvm_value_from_json(p, kwargs); let result = _kclvm_context_invoke(p, method, args, kwargs); p.buffer.kclvm_context_invoke_result = ptr_as_ref(result).to_json_string_with_null(); - let result_json = p.buffer.kclvm_context_invoke_result.as_ptr() as *const i8; + let result_json = p.buffer.kclvm_context_invoke_result.as_ptr() as *const c_char; kclvm_value_delete(args); kclvm_value_delete(kwargs); @@ -369,10 +317,11 @@ unsafe fn _kclvm_context_invoke( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_context_pkgpath_is_imported( + ctx: *mut kclvm_context_t, pkgpath: *const kclvm_char_t, ) -> kclvm_bool_t { let pkgpath = c2str(pkgpath); - let ctx = Context::current_context_mut(); + let ctx = mut_ptr_as_ref(ctx); let result = ctx.imported_pkgpath.contains(pkgpath); ctx.imported_pkgpath.insert(pkgpath.to_string()); result as kclvm_bool_t diff --git a/kclvm/runtime/src/context/mod.rs b/kclvm/runtime/src/context/mod.rs index 42a285b34..4f90afa52 100644 --- a/kclvm/runtime/src/context/mod.rs +++ b/kclvm/runtime/src/context/mod.rs @@ -1,13 +1,10 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod api; pub use api::*; use std::fmt; -use crate::{BacktraceFrame, PanicInfo}; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = crate::ValueRef; +use crate::{BacktraceFrame, PanicInfo, RuntimePanicRecord}; impl fmt::Display for PanicInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -45,7 +42,7 @@ impl PanicInfo { Err(_) => PanicInfo { __kcl_PanicInfo__: true, message: s.to_string(), - err_type_code: crate::ErrType::CompileError_TYPE as i32, + err_type_code: crate::RuntimeErrorType::EvaluationError as i32, ..Default::default() }, } @@ -80,47 +77,24 @@ impl crate::Context { Box::into_raw(Box::new(self)) } - pub fn current_context() -> &'static crate::Context { - unsafe { - let ctx = kclvm_context_current(); - &*ctx - } - } - - pub fn current_context_mut() -> &'static mut crate::Context { - unsafe { - let ctx = kclvm_context_current(); - &mut *ctx + pub fn get_panic_info_json_string(&self) -> Option { + if self.panic_info.__kcl_PanicInfo__ { + Some(self.panic_info.to_json_string()) + } else { + None } } - pub fn main_begin_hook(&mut self) { - // Nothing to do - } - - pub fn main_end_hook( - &mut self, - return_value: *mut kclvm_value_ref_t, - ) -> *mut kclvm_value_ref_t { - self.output.return_value = return_value; - - if self.cfg.list_option_mode { - self.output.return_value = - crate::ValueRef::str(self.list_option_help().as_str()).into_raw(); - // If there is a custom manifests, output them. - } else if let Some(output) = &self.buffer.custom_manifests_output { - self.output.return_value = crate::ValueRef::str(output.as_str()).into_raw(); - } - - self.output.return_value + pub fn set_kcl_pkgpath(&mut self, pkgpath: &str) { + self.panic_info.kcl_pkgpath = pkgpath.to_string(); } - pub fn get_panic_info_json_string(&self) -> String { - self.panic_info.to_json_string() + pub fn set_kcl_module_path(&mut self, module_path: &str) { + self.module_path = module_path.to_string(); } - pub fn set_kcl_pkgpath(&mut self, pkgpath: &str) { - self.panic_info.kcl_pkgpath = pkgpath.to_string(); + pub fn set_kcl_workdir(&mut self, workdir: &str) { + self.workdir = workdir.to_string(); } pub fn set_kcl_filename(&mut self, file: &str) { @@ -176,28 +150,21 @@ impl crate::Context { } } - pub fn set_err_type(&mut self, err_type: &crate::ErrType) { + pub fn set_err_type(&mut self, err_type: &crate::RuntimeErrorType) { self.panic_info.__kcl_PanicInfo__ = true; self.panic_info.err_type_code = *err_type as i32; } - pub fn set_warnning_message(&mut self, msg: &str) { + + pub fn set_warning_message(&mut self, msg: &str) { self.panic_info.__kcl_PanicInfo__ = true; self.panic_info.message = msg.to_string(); self.panic_info.is_warning = true; } - pub fn set_panic_info(&mut self, info: &std::panic::PanicInfo) { + pub(crate) fn set_panic_info(&mut self, record: &RuntimePanicRecord) { self.panic_info.__kcl_PanicInfo__ = true; - self.panic_info.message = if let Some(s) = info.payload().downcast_ref::<&str>() { - s.to_string() - } else if let Some(s) = info.payload().downcast_ref::<&String>() { - (*s).clone() - } else if let Some(s) = info.payload().downcast_ref::() { - (*s).clone() - } else { - "".to_string() - }; + self.panic_info.message = record.message.clone(); if self.cfg.debug_mode { self.panic_info.backtrace = self.backtrace.clone(); self.panic_info.backtrace.push(BacktraceFrame { @@ -207,15 +174,10 @@ impl crate::Context { line: self.panic_info.kcl_line, }); } - if let Some(location) = info.location() { - self.panic_info.rust_file = location.file().to_string(); - self.panic_info.rust_line = location.line() as i32; - self.panic_info.rust_col = location.column() as i32; - } else { - self.panic_info.rust_file = "".to_string(); - self.panic_info.rust_line = 0; - self.panic_info.rust_col = 0; - } + + self.panic_info.rust_file = record.rust_file.clone(); + self.panic_info.rust_line = record.rust_line; + self.panic_info.rust_col = record.rust_col; } } @@ -223,7 +185,7 @@ impl crate::Context { pub fn define_option( &mut self, name: &str, - typ: &str, + ty: &str, required: bool, default_value: Option, help: &str, @@ -231,12 +193,12 @@ impl crate::Context { // check dup for i in 0..self.option_helps.len() { if self.option_helps[i].name == name { - if typ.is_empty() && !required && default_value.is_none() && help.is_empty() { + if ty.is_empty() && !required && default_value.is_none() && help.is_empty() { return; } - if self.option_helps[i].typ.is_empty() { - self.option_helps[i].typ = typ.to_string(); + if self.option_helps[i].ty.is_empty() { + self.option_helps[i].ty = ty.to_string(); } if !self.option_helps[i].required { @@ -255,7 +217,7 @@ impl crate::Context { self.option_helps.push(crate::OptionHelp { name: name.to_string(), - typ: typ.to_string(), + ty: ty.to_string(), required, default_value, help: help.to_string(), @@ -286,12 +248,12 @@ impl crate::Context { // (required) // (str,required) - if !opt.typ.is_empty() || opt.required { - if opt.required && !opt.typ.is_empty() { - let s = format!(" ({},{})", opt.typ, "required"); + if !opt.ty.is_empty() || opt.required { + if opt.required && !opt.ty.is_empty() { + let s = format!(" ({},{})", opt.ty, "required"); msg.push_str(s.as_str()); - } else if !opt.typ.is_empty() { - let s = format!(" ({})", opt.typ); + } else if !opt.ty.is_empty() { + let s = format!(" ({})", opt.ty); msg.push_str(s.as_str()); } else { msg.push_str(" (required)"); diff --git a/kclvm/runtime/src/crypto/crypto.rs b/kclvm/runtime/src/crypto/crypto.rs deleted file mode 100644 index 7be2420c8..000000000 --- a/kclvm/runtime/src/crypto/crypto.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! KCL crypto system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -extern crate md5; -extern crate sha1; -extern crate sha2; - -use sha2::{Digest, Sha224, Sha256, Sha384, Sha512}; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// md5(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_md5( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let hex = format!("{:x}", md5::compute(s)); - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("md5() missing 1 required positional argument: 'value'"); -} - -// sha1(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_sha1( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let hex = sha1::Sha1::from(s).digest().to_string(); - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("sha1() missing 1 required positional argument: 'value'"); -} - -// sha224(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_sha224( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let mut hasher = Sha224::new(); - hasher.update(&s); - let result = hasher.finalize(); - - let mut hex = String::with_capacity(2 * Sha256::output_size()); - use std::fmt::Write; - - for byte in result { - let _ = write!(&mut hex, "{byte:02x}"); - } - - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("sha224() missing 1 required positional argument: 'value'"); -} - -// sha256(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_sha256( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let mut hasher = Sha256::new(); - hasher.update(&s); - let result = hasher.finalize(); - - let mut hex = String::with_capacity(2 * Sha256::output_size()); - use std::fmt::Write; - - for byte in result { - let _ = write!(&mut hex, "{byte:02x}"); - } - - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("sha256() missing 1 required positional argument: 'value'"); -} - -// sha384(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_sha384( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let mut hasher = Sha384::new(); - hasher.update(&s); - let result = hasher.finalize(); - - let mut hex = String::with_capacity(2 * Sha256::output_size()); - use std::fmt::Write; - - for byte in result { - let _ = write!(&mut hex, "{byte:02x}"); - } - - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("sha384() missing 1 required positional argument: 'value'"); -} - -// sha512(value: str, encoding: str = "utf-8") -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_crypto_sha512( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(s) = args.arg_i_str(0, None) { - let mut hasher = Sha512::new(); - hasher.update(&s); - let result = hasher.finalize(); - - let mut hex = String::with_capacity(2 * Sha256::output_size()); - use std::fmt::Write; - - for byte in result { - let _ = write!(&mut hex, "{byte:02x}"); - } - - return ValueRef::str(hex.as_ref()).into_raw(); - } - panic!("sha512() missing 1 required positional argument: 'value'"); -} diff --git a/kclvm/runtime/src/crypto/mod.rs b/kclvm/runtime/src/crypto/mod.rs index 4105751af..53ad9d8bc 100644 --- a/kclvm/runtime/src/crypto/mod.rs +++ b/kclvm/runtime/src/crypto/mod.rs @@ -1,4 +1,217 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod crypto; -pub use self::crypto::*; +extern crate md5; +extern crate sha1; +extern crate sha2; + +use core::panic; +use std::{fs::File, io::Read}; + +use sha2::{Digest, Sha224, Sha256, Sha384, Sha512}; + +use crate::*; +use uuid::Uuid; + +#[allow(non_camel_case_types)] +type kclvm_value_ref_t = ValueRef; + +// md5(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_md5( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(s) = args.arg_i_str(0, None) { + let hex = format!("{:x}", md5::compute(s)); + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("md5() missing 1 required positional argument: 'value'"); +} + +// sha1(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_sha1( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(s) = args.arg_i_str(0, None) { + let hex = sha1::Sha1::from(s).digest().to_string(); + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("sha1() missing 1 required positional argument: 'value'"); +} + +// sha224(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_sha224( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(s) = args.arg_i_str(0, None) { + let mut hasher = Sha224::new(); + hasher.update(&s); + let result = hasher.finalize(); + + let mut hex = String::with_capacity(2 * Sha256::output_size()); + use std::fmt::Write; + + for byte in result { + let _ = write!(&mut hex, "{byte:02x}"); + } + + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("sha224() missing 1 required positional argument: 'value'"); +} + +// sha256(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_sha256( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(s) = args.arg_i_str(0, None) { + let mut hasher = Sha256::new(); + hasher.update(&s); + let result = hasher.finalize(); + + let mut hex = String::with_capacity(2 * Sha256::output_size()); + use std::fmt::Write; + + for byte in result { + let _ = write!(&mut hex, "{byte:02x}"); + } + + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("sha256() missing 1 required positional argument: 'value'"); +} + +// sha384(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_sha384( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(s) = args.arg_i_str(0, None) { + let mut hasher = Sha384::new(); + hasher.update(&s); + let result = hasher.finalize(); + + let mut hex = String::with_capacity(2 * Sha256::output_size()); + use std::fmt::Write; + + for byte in result { + let _ = write!(&mut hex, "{byte:02x}"); + } + + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("sha384() missing 1 required positional argument: 'value'"); +} + +// sha512(value: str, encoding: str = "utf-8") -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_sha512( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(s) = args.arg_i_str(0, None) { + let mut hasher = Sha512::new(); + hasher.update(&s); + let result = hasher.finalize(); + + let mut hex = String::with_capacity(2 * Sha256::output_size()); + use std::fmt::Write; + + for byte in result { + let _ = write!(&mut hex, "{byte:02x}"); + } + + return ValueRef::str(hex.as_ref()).into_raw(ctx); + } + panic!("sha512() missing 1 required positional argument: 'value'"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_uuid( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + return ValueRef::str(Uuid::new_v4().to_string().as_ref()).into_raw(ctx); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_crypto_filesha256( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(filepath) = args.arg_i_str(0, None) { + // Open the file + let mut file = File::open(&filepath) + .unwrap_or_else(|e| panic!("failed to access file '{}': {}", filepath, e)); + + // Create a SHA256 hasher instance + let mut hasher = Sha256::new(); + + // Read the file content and update the hasher + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer) + .unwrap_or_else(|e| panic!("failed to read file '{}': {}", filepath, e)); + hasher.update(&buffer); + + // Compute the SHA256 hash + let hash_result = hasher.finalize(); + + let mut hex = String::with_capacity(2 * Sha256::output_size()); + use std::fmt::Write; + + for byte in hash_result { + let _ = write!(&mut hex, "{byte:02x}"); + } + + return ValueRef::str(hex.as_str()).into_raw(ctx); + } + panic!("filesha256() missing 1 required positional argument: 'filepath'"); +} diff --git a/kclvm/runtime/src/datetime/datetime.rs b/kclvm/runtime/src/datetime/datetime.rs deleted file mode 100644 index ee9378c1a..000000000 --- a/kclvm/runtime/src/datetime/datetime.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! KCL datetime system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -extern crate chrono; - -use chrono::prelude::Local; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// def KMANGLED_today() -> str: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_datetime_today( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let s = Local::now().to_string(); - return ValueRef::str(s.as_ref()).into_raw(); -} - -// def KMANGLED_now() -> str: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_datetime_now( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let s = Local::now().to_string(); - return ValueRef::str(s.as_ref()).into_raw(); -} - -// def KMANGLED_ticks() -> float: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_datetime_ticks( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let x = Local::now().timestamp(); - ValueRef::float(x as f64).into_raw() -} - -// def KMANGLED_date() -> str: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_datetime_date( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let s = Local::now().to_string(); - return ValueRef::str(s.as_ref()).into_raw(); -} diff --git a/kclvm/runtime/src/datetime/mod.rs b/kclvm/runtime/src/datetime/mod.rs index 6aa3369cc..2a7dbe4f7 100644 --- a/kclvm/runtime/src/datetime/mod.rs +++ b/kclvm/runtime/src/datetime/mod.rs @@ -1,4 +1,63 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod datetime; -pub use self::datetime::*; +extern crate chrono; + +use chrono::prelude::Local; + +use crate::*; + +// today() -> str: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_datetime_today( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let s = Local::now().to_string(); + let ctx = mut_ptr_as_ref(ctx); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} + +// now() -> str: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_datetime_now( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let s = Local::now().to_string(); + let ctx = mut_ptr_as_ref(ctx); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} + +// ticks() -> float: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_datetime_ticks( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let x = Local::now().timestamp(); + ValueRef::float(x as f64).into_raw(ctx) +} + +// date() -> str: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_datetime_date( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let s = Local::now().to_string(); + let ctx = mut_ptr_as_ref(ctx); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} diff --git a/kclvm/runtime/src/eval/mod.rs b/kclvm/runtime/src/eval/mod.rs new file mode 100644 index 000000000..5b31a834d --- /dev/null +++ b/kclvm/runtime/src/eval/mod.rs @@ -0,0 +1,122 @@ +use std::{ + mem::transmute_copy, + panic::{RefUnwindSafe, UnwindSafe}, +}; + +use crate::{ + kclvm_context_t, kclvm_eval_scope_t, kclvm_value_ref_t, mut_ptr_as_ref, Context, IndexMap, + ValueRef, +}; + +/// Variable setter function type. fn(ctx: &mut Context, scope: &mut ScopeEval, args: ValueRef, kwargs: ValueRef) -> ValueRef. +pub type SetterFuncType = + unsafe extern "C" fn(*mut kclvm_context_t, *mut kclvm_eval_scope_t) -> *const kclvm_value_ref_t; + +/// LazyEvalScope represents a scope of sequentially independent calculations, where +/// the calculation of values is lazy and only recursively performed through +/// backtracking when needed. +#[derive(PartialEq, Clone, Default, Debug)] +pub struct LazyEvalScope { + /// Temp variable values. + pub vars: IndexMap, + /// Variable value cache. + pub cache: IndexMap, + /// Backtrack levels. + pub levels: IndexMap, + /// Variable setter function pointers. + pub setters: IndexMap>, + /// Calculate times without backtracking. + pub cal_times: IndexMap, +} + +impl LazyEvalScope { + #[inline] + pub fn is_backtracking(&self, key: &str) -> bool { + let level = self.levels.get(key).unwrap_or(&0); + *level > 0 + } + + #[inline] + pub fn setter_len(&self, key: &str) -> usize { + self.setters.get(key).unwrap_or(&vec![]).len() + } + + #[inline] + pub fn cal_increment(&mut self, key: &str) -> bool { + if self.is_backtracking(key) { + false + } else { + let cal_time = *self.cal_times.get(key).unwrap_or(&0); + let next_cal_time = cal_time + 1; + self.cal_times.insert(key.to_string(), next_cal_time); + next_cal_time >= self.setter_len(key) + } + } + + #[inline] + pub fn contains_key(&self, key: &str) -> bool { + self.vars.contains_key(key) + } + + /// Get the value from the context. + pub fn get_value(&mut self, ctx: &mut Context, key: &str, target: &str) -> ValueRef { + let value = match self.vars.get(key) { + Some(value) => value.clone(), + None => ValueRef::undefined(), + }; + // Deal in-place modify and return it self immediately. + if key == target && (!self.is_backtracking(key) || self.setter_len(key) <= 1) { + value + } else { + match self.cache.get(key) { + Some(value) => value.clone(), + None => { + match &self.setters.get(key) { + Some(setters) if !setters.is_empty() => { + // Call all setters function to calculate the value recursively. + let level = *self.levels.get(key).unwrap_or(&0); + let next_level = level + 1; + self.levels.insert(key.to_string(), next_level); + let n = setters.len(); + let index = n - next_level; + if index >= n { + value + } else { + let fn_ptr = setters[index]; + unsafe { + let ctx_ref = mut_ptr_as_ref(ctx); + let panic_info = ctx_ref.panic_info.clone(); + let setter_fn: SetterFuncType = transmute_copy(&fn_ptr); + // Restore the panic info of current schema attribute. + ctx_ref.panic_info = panic_info; + // Call setter functions + setter_fn(ctx, self) + }; + self.levels.insert(key.to_string(), level); + let value = match self.vars.get(key) { + Some(value) => value.clone(), + None => ValueRef::undefined(), + }; + self.cache.insert(key.to_string(), value.clone()); + value + } + } + _ => value, + } + } + } + } + } + + /// Set value to the context. + #[inline] + pub fn set_value(&mut self, key: &str, value: &ValueRef) { + self.vars.insert(key.to_string(), value.clone()); + if self.cal_increment(key) && self.cache.get(key).is_none() { + self.cache.insert(key.to_string(), value.clone()); + } + } +} + +impl UnwindSafe for LazyEvalScope {} +impl RefUnwindSafe for LazyEvalScope {} diff --git a/kclvm/runtime/src/file/mod.rs b/kclvm/runtime/src/file/mod.rs new file mode 100644 index 000000000..c4dae91fc --- /dev/null +++ b/kclvm/runtime/src/file/mod.rs @@ -0,0 +1,74 @@ +use std::fs; + +use crate::*; +use glob::glob; + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_file_read( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(x) = args.arg_i_str(0, None) { + let contents = fs::read_to_string(&x) + .unwrap_or_else(|e| panic!("failed to access the file '{}': {}", x, e)); + + let s = ValueRef::str(contents.as_ref()); + return s.into_raw(ctx); + } + + panic!("read() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_file_glob( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + let pattern = args + .arg_i_str(0, None) + .expect("glob() takes exactly one argument (0 given)"); + + let mut matched_paths = vec![]; + for entry in glob(&pattern).unwrap_or_else(|e| panic!("Failed to read glob pattern: {}", e)) { + match entry { + Ok(path) => matched_paths.push(path.display().to_string()), + Err(e) => panic!("failed to access the file matching '{}': {}", pattern, e), + } + } + + return ValueRef::list_str(matched_paths.as_slice()).into_raw(ctx); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_file_modpath( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let s = ValueRef::str(ctx.module_path.as_ref()); + s.into_raw(ctx) +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_file_workdir( + ctx: *mut kclvm_context_t, + _args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let s = ValueRef::str(ctx.workdir.as_ref()); + s.into_raw(ctx) +} diff --git a/kclvm/runtime/src/json/json.rs b/kclvm/runtime/src/json/json.rs deleted file mode 100644 index 3063ff28e..000000000 --- a/kclvm/runtime/src/json/json.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! KCL json system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// data, sort_keys=False, indent=None, ignore_private=False, ignore_none=False - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_json_encode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - let kwargs = ptr_as_ref(kwargs); - - let mut opt = JsonEncodeOptions::default(); - if let Some(sort_keys) = kwargs.kwarg_bool("sort_keys", None) { - opt.sort_keys = sort_keys; - } - if let Some(indent) = kwargs.kwarg_int("indent", None) { - opt.indent = indent; - } - if let Some(ignore_private) = kwargs.kwarg_bool("ignore_private", None) { - opt.ignore_private = ignore_private; - } - if let Some(ignore_none) = kwargs.kwarg_bool("ignore_none", None) { - opt.ignore_none = ignore_none; - } - - if let Some(arg0) = args.arg_i(0) { - let s = ValueRef::str(arg0.to_json_string_with_option(&opt).as_ref()); - return s.into_raw(); - } - panic!("encode() missing 1 required positional argument: 'value'") -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_json_decode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(arg0) = args.arg_i(0) { - match ValueRef::from_json(arg0.as_str().as_ref()) { - Ok(x) => return x.into_raw(), - Err(err) => panic!("{}", err), - } - } - panic!("decode() missing 1 required positional argument: 'value'") -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_json_dump_to_file( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(data) = args.arg_i(0) { - if let Some(filename) = args.arg_i(0) { - let yaml = data.to_json_string(); - let filename = filename.as_str(); - - std::fs::write(filename, yaml).expect("Unable to write file"); - } - } - panic!("dump_to_file() missing 2 required positional arguments: 'data' and 'filename'") -} diff --git a/kclvm/runtime/src/json/mod.rs b/kclvm/runtime/src/json/mod.rs index 4859bd9cb..e8933c493 100644 --- a/kclvm/runtime/src/json/mod.rs +++ b/kclvm/runtime/src/json/mod.rs @@ -1,4 +1,106 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod json; -pub use self::json::*; +use crate::*; + +// data, sort_keys=False, indent=None, ignore_private=False, ignore_none=False + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_json_encode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + let kwargs = ptr_as_ref(kwargs); + + if let Some(arg0) = args.arg_i(0) { + let s = ValueRef::str( + arg0.to_json_string_with_options(&kwargs_to_opts(kwargs)) + .as_ref(), + ); + return s.into_raw(ctx); + } + panic!("encode() missing 1 required positional argument: 'value'") +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_json_decode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(arg0) = args.arg_i(0) { + match ValueRef::from_json(ctx, arg0.as_str().as_ref()) { + Ok(x) => return x.into_raw(ctx), + Err(err) => panic!("{}", err), + } + } + panic!("decode() missing 1 required positional argument: 'value'") +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_json_validate( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(arg0) = args.arg_i(0) { + match ValueRef::from_json(ctx, arg0.as_str().as_ref()) { + Ok(_) => return kclvm_value_True(ctx), + Err(_) => return kclvm_value_False(ctx), + } + } + panic!("validate() missing 1 required positional argument: 'value'") +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_json_dump_to_file( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + let data = args.arg_i(0).or(kwargs.get_by_key("data")); + let filename = args.arg_i(1).or(kwargs.get_by_key("filename")); + match (data, filename) { + (Some(data), Some(filename)) => { + let filename = filename.as_str(); + let json = data.to_json_string_with_options(&kwargs_to_opts(kwargs)); + std::fs::write(&filename, json) + .unwrap_or_else(|e| panic!("Unable to write file '{}': {}", filename, e)); + kclvm_value_Undefined(ctx) + } + _ => { + panic!("dump_to_file() missing 2 required positional arguments: 'data' and 'filename'") + } + } +} + +fn kwargs_to_opts(kwargs: &ValueRef) -> JsonEncodeOptions { + let mut opts = JsonEncodeOptions::default(); + if let Some(sort_keys) = kwargs.kwarg_bool("sort_keys", None) { + opts.sort_keys = sort_keys; + } + if let Some(indent) = kwargs.kwarg_int("indent", None) { + opts.indent = indent; + } + if let Some(ignore_private) = kwargs.kwarg_bool("ignore_private", None) { + opts.ignore_private = ignore_private; + } + if let Some(ignore_none) = kwargs.kwarg_bool("ignore_none", None) { + opts.ignore_none = ignore_none; + } + opts +} diff --git a/kclvm/runtime/src/lib.rs b/kclvm/runtime/src/lib.rs index 56191b709..0e796d173 100644 --- a/kclvm/runtime/src/lib.rs +++ b/kclvm/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use kclvm_runtime_internal_macros::runtime_fn; @@ -6,6 +6,10 @@ use kclvm_runtime_internal_macros::runtime_fn; // api-spec(c): typedef struct kclvm_context_t kclvm_context_t; // api-spec(llvm): %"kclvm_context_t" = type { i8* } +// api-spec: kclvm_eval_scope_t +// api-spec(c): typedef struct kclvm_eval_scope_t kclvm_eval_scope_t; +// api-spec(llvm): %"kclvm_eval_scope_t" = type { i8* } + // api-spec: kclvm_type_t // api-spec(c): typedef struct kclvm_type_t kclvm_type_t; // api-spec(llvm): %"kclvm_type_t" = type { i8* } @@ -77,6 +81,8 @@ pub use self::collection::*; pub mod crypto; pub use self::crypto::*; +mod eval; + pub mod datetime; pub use self::datetime::*; @@ -98,15 +104,15 @@ pub use self::regex::*; pub mod stdlib; pub use self::stdlib::*; -pub mod testing; -pub use self::testing::*; - pub mod units; pub use self::units::*; pub mod yaml; pub use self::yaml::*; +pub mod file; +pub use self::file::*; + pub mod _kcl_run; pub use self::_kcl_run::*; diff --git a/kclvm/runtime/src/manifests/mod.rs b/kclvm/runtime/src/manifests/mod.rs index b2125e3e5..fd2409fe4 100644 --- a/kclvm/runtime/src/manifests/mod.rs +++ b/kclvm/runtime/src/manifests/mod.rs @@ -51,7 +51,7 @@ type kclvm_value_ref_t = ValueRef; /// TODO: more options on the function `yaml_stream`. #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_manifests_yaml_stream( +pub extern "C" fn kclvm_manifests_yaml_stream( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, @@ -61,26 +61,26 @@ pub unsafe extern "C" fn kclvm_manifests_yaml_stream( let ctx = mut_ptr_as_ref(ctx); // Get the YAML encode options from the second keyword argument `opts`. - let opts = match kwargs.kwarg("opts").or(args.arg_i(1)) { + let opts = match kwargs.kwarg("opts").or_else(|| args.arg_i(1)) { Some(opts) => { if opts.is_config() { // Get options or default. YamlEncodeOptions { sort_keys: opts .get_by_key("sort_keys") - .unwrap_or(ValueRef::bool(false)) + .unwrap_or_else(|| ValueRef::bool(false)) .as_bool(), ignore_private: opts .get_by_key("ignore_private") - .unwrap_or(ValueRef::bool(false)) + .unwrap_or_else(|| ValueRef::bool(false)) .as_bool(), ignore_none: opts .get_by_key("ignore_none") - .unwrap_or(ValueRef::bool(false)) + .unwrap_or_else(|| ValueRef::bool(false)) .as_bool(), sep: opts .get_by_key("sep") - .unwrap_or(ValueRef::str("---")) + .unwrap_or_else(|| ValueRef::str("---")) .as_str(), } } else { diff --git a/kclvm/runtime/src/manifests/tests.rs b/kclvm/runtime/src/manifests/tests.rs index 86625bcdc..aa7923c4b 100644 --- a/kclvm/runtime/src/manifests/tests.rs +++ b/kclvm/runtime/src/manifests/tests.rs @@ -17,7 +17,7 @@ fn test_kclvm_manifests_yaml_stream() { YamlEncodeOptions::default(), ), ( - "a:\n - 1\n - 2\n - 3\nb: s\n", + "a:\n- 1\n- 2\n- 3\nb: s\n", ValueRef::list(Some(&[&ValueRef::dict(Some(&[ ("a", &ValueRef::list_int(&[1, 2, 3])), ("b", &ValueRef::str("s")), @@ -36,7 +36,7 @@ fn test_kclvm_manifests_yaml_stream() { }, ), ( - "a: 1\nb: ~\n", + "a: 1\nb: null\n", ValueRef::list(Some(&[&ValueRef::dict(Some(&[ ("a", &ValueRef::int(1)), ("b", &ValueRef::none()), @@ -69,10 +69,14 @@ fn test_kclvm_manifests_yaml_stream() { let mut args = ValueRef::list(None); args.list_append(&value); let mut kwargs = ValueRef::dict(None); - kwargs.dict_insert("opts", &opts, ConfigEntryOperationKind::Override, -1); - unsafe { - kclvm_manifests_yaml_stream(&mut ctx, &args, &kwargs); - } + kwargs.dict_insert( + &mut ctx, + "opts", + &opts, + ConfigEntryOperationKind::Override, + -1, + ); + kclvm_manifests_yaml_stream(&mut ctx, &args, &kwargs); assert_eq!( Some(yaml_str.to_string()), ctx.buffer.custom_manifests_output @@ -88,34 +92,29 @@ fn test_kclvm_manifests_yaml_stream_invalid() { assert_panic( "yaml_stream() missing 1 required positional argument: 'values'", || { - let ctx = Context::new(); - let args = ValueRef::list(None); - let kwargs = ValueRef::dict(None); - unsafe { - kclvm_manifests_yaml_stream(ctx.into_raw(), args.into_raw(), kwargs.into_raw()); - } + let mut ctx = Context::new(); + let args = ValueRef::list(None).into_raw(&mut ctx); + let kwargs = ValueRef::dict(None).into_raw(&mut ctx); + kclvm_manifests_yaml_stream(ctx.into_raw(), args, kwargs); }, ); assert_panic( "Invalid options arguments in yaml_stream(): expect config, got str", || { - let ctx = Context::new(); - let args = ValueRef::list(None); - let kwargs = ValueRef::dict(Some(&[("opts", &ValueRef::str("invalid_kwarg"))])); - unsafe { - kclvm_manifests_yaml_stream(ctx.into_raw(), args.into_raw(), kwargs.into_raw()); - } + let mut ctx = Context::new(); + let args = ValueRef::list(None).into_raw(&mut ctx); + let kwargs = ValueRef::dict(Some(&[("opts", &ValueRef::str("invalid_kwarg"))])) + .into_raw(&mut ctx); + kclvm_manifests_yaml_stream(ctx.into_raw(), args, kwargs); }, ); assert_panic( "Invalid options arguments in yaml_stream(): expect config, got NoneType", || { - let ctx = Context::new(); - let args = ValueRef::list(None); - let kwargs = ValueRef::dict(Some(&[("opts", &ValueRef::none())])); - unsafe { - kclvm_manifests_yaml_stream(ctx.into_raw(), args.into_raw(), kwargs.into_raw()); - } + let mut ctx = Context::new(); + let args = ValueRef::list(None).into_raw(&mut ctx); + let kwargs = ValueRef::dict(Some(&[("opts", &ValueRef::none())])).into_raw(&mut ctx); + kclvm_manifests_yaml_stream(ctx.into_raw(), args, kwargs); }, ); std::panic::set_hook(prev_hook); diff --git a/kclvm/runtime/src/manifests/yaml.rs b/kclvm/runtime/src/manifests/yaml.rs index 3ef949948..47ee12d63 100644 --- a/kclvm/runtime/src/manifests/yaml.rs +++ b/kclvm/runtime/src/manifests/yaml.rs @@ -39,7 +39,7 @@ mod test_manifests_yaml { YamlEncodeOptions::default(), ), ( - "a:\n - 1\n - 2\n - 3\nb: s\n", + "a:\n- 1\n- 2\n- 3\nb: s\n", ValueRef::list(Some(&[&ValueRef::dict(Some(&[ ("a", &ValueRef::list_int(&[1, 2, 3])), ("b", &ValueRef::str("s")), @@ -58,7 +58,7 @@ mod test_manifests_yaml { }, ), ( - "a: 1\nb: ~\n", + "a: 1\nb: null\n", ValueRef::list(Some(&[&ValueRef::dict(Some(&[ ("a", &ValueRef::int(1)), ("b", &ValueRef::none()), diff --git a/kclvm/runtime/src/math/math.rs b/kclvm/runtime/src/math/math.rs deleted file mode 100644 index 149900a5e..000000000 --- a/kclvm/runtime/src/math/math.rs +++ /dev/null @@ -1,361 +0,0 @@ -//! KCL math system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -extern crate num_integer; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// https://docs.python.org/3/library/math.html -// https://doc.rust-lang.org/std/primitive.f64.html -// https://github.com/RustPython/RustPython/blob/main/stdlib/src/math.rs - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_ceil( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Int(x); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Int(x.ceil() as i64); - } - - panic!("ceil() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_factorial( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - fn factorial(num: i64) -> i64 { - if num >= 21 { - // overflow: 21! = 51090942171709440000 - // MaxInt64: 9223372036854775807 - panic!("factorial() result overflow"); - } - match num { - 0 => 1, - 1 => 1, - _ => factorial(num - 1) * num, - } - } - - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - if x >= 0 { - return kclvm_value_Int(factorial(x)); - } - } - if let Some(x) = args.arg_i_float(0, None) { - if x >= 0.0 && (x as i64 as f64) == x { - return kclvm_value_Float(factorial(x as i64) as f64); - } - } - if args.args_len() > 0 { - panic!("factorial() only accepts integral values") - } - panic!("factorial() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_floor( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Int(x); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.floor()); - } - - panic!("floor() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_gcd( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(a) = args.arg_i_int(0, None) { - if let Some(b) = args.arg_i_int(1, None) { - return kclvm_value_Int(num_integer::gcd(a, b)); - } - } - - panic!( - "gcd() takes exactly two arguments ({} given)", - args.args_len() - ); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_isfinite( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(_x) = args.arg_i_int(0, None) { - return kclvm_value_Bool(true as i8); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Bool(x.is_finite() as i8); - } - - panic!("isfinite() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_isinf( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(_x) = args.arg_i_int(0, None) { - return kclvm_value_Bool(false as i8); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Bool(x.is_infinite() as i8); - } - - panic!("isinf() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_isnan( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(_x) = args.arg_i_int(0, None) { - return kclvm_value_Bool(false as i8); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Bool(x.is_nan() as i8); - } - - panic!("isnan() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_modf( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - let list = ValueRef::list_float(&[0.0, x as f64]); - return list.into_raw(); - } - if let Some(x) = args.arg_i_float(0, None) { - if !x.is_finite() { - if x.is_infinite() { - let list = ValueRef::list_float(&[0.0_f64.copysign(x), x]); - return list.into_raw(); - } else if x.is_nan() { - let list = ValueRef::list_float(&[x, x]); - return list.into_raw(); - } - } - let list = ValueRef::list_float(&[x.fract(), x.trunc()]); - return list.into_raw(); - } - - panic!("modf() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_exp( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Float((x as f64).exp()); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.exp()); - } - panic!("exp() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_expm1( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Float((x as f64).exp_m1()); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.exp_m1()); - } - panic!("expm1() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_log( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - if let Some(base) = args.arg_i_float(1, Some(std::f64::consts::E)) { - return kclvm_value_Int((x as f64).log(base) as i64); - } - } - if let Some(x) = args.arg_i_float(0, None) { - if let Some(base) = args.arg_i_float(1, Some(std::f64::consts::E)) { - return kclvm_value_Float(x.log(base)); - } - } - panic!("log() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_log1p( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Float(((x + 1) as f64).ln_1p()); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float((x + 1.0).ln_1p()); - } - panic!("log1p() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_log2( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Int((x as f64).log2() as i64); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.log2()); - } - panic!("log2() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_log10( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Float((x as f64).log10()); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.log10()); - } - panic!("log10() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_pow( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - if let Some(n) = args.arg_i_int(1, None) { - if n < 0 { - return kclvm_value_Float((x as f64).powf(n as f64)); - } else { - return kclvm_value_Int(x.pow(n as u32)); - } - } - if let Some(n) = args.arg_i_float(1, None) { - return kclvm_value_Float((x as f64).powf(n)); - } - } - if let Some(x) = args.arg_i_float(0, None) { - if let Some(n) = args.arg_i_int(1, None) { - return kclvm_value_Float(x.powi(n as i32)); - } - if let Some(n) = args.arg_i_float(1, None) { - return kclvm_value_Float(x.powf(n)); - } - } - panic!("pow() takes exactly one argument (0 given)"); -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_math_sqrt( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(x) = args.arg_i_int(0, None) { - return kclvm_value_Float((x as f64).sqrt()); - } - if let Some(x) = args.arg_i_float(0, None) { - return kclvm_value_Float(x.sqrt()); - } - panic!("sqrt() takes exactly one argument (0 given)"); -} diff --git a/kclvm/runtime/src/math/mod.rs b/kclvm/runtime/src/math/mod.rs index fb00f12d7..ab0ba6b35 100644 --- a/kclvm/runtime/src/math/mod.rs +++ b/kclvm/runtime/src/math/mod.rs @@ -1,4 +1,363 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod math; -pub use self::math::*; +extern crate num_integer; + +use crate::*; + +// https://docs.python.org/3/library/math.html +// https://doc.rust-lang.org/std/primitive.f64.html +// https://github.com/RustPython/RustPython/blob/main/stdlib/src/math.rs + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_ceil( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Int(ctx, x); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Int(ctx, x.ceil() as i64); + } + + panic!("ceil() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_factorial( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + fn factorial(num: i64) -> i64 { + if num >= 21 { + // overflow: 21! = 51090942171709440000 + // MaxInt64: 9223372036854775807 + panic!("factorial() result overflow"); + } + match num { + 0 => 1, + 1 => 1, + _ => factorial(num - 1) * num, + } + } + + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + if x >= 0 { + return kclvm_value_Int(ctx, factorial(x)); + } + } + if let Some(x) = args.arg_i_float(0, None) { + if x >= 0.0 && (x as i64 as f64) == x { + return kclvm_value_Float(ctx, factorial(x as i64) as f64); + } + } + + if args.args_len() > 0 { + panic!("factorial() only accepts integral values") + } + panic!("factorial() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_floor( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Int(ctx, x); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.floor()); + } + + panic!("floor() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_gcd( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(a) = args.arg_i_int(0, None) { + if let Some(b) = args.arg_i_int(1, None) { + return kclvm_value_Int(ctx, num_integer::gcd(a, b)); + } + } + + panic!( + "gcd() takes exactly two arguments ({} given)", + args.args_len() + ); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_isfinite( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if args.arg_i_int_or_bool(0, None).is_some() { + return kclvm_value_Bool(ctx, true as i8); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Bool(ctx, x.is_finite() as i8); + } + if args.arg_i_bool(0, None).is_some() { + return kclvm_value_Bool(ctx, true as i8); + } + + panic!("isfinite() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_isinf( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if args.arg_i_int_or_bool(0, None).is_some() { + return kclvm_value_Bool(ctx, false as i8); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Bool(ctx, x.is_infinite() as i8); + } + if args.arg_i_bool(0, None).is_some() { + return kclvm_value_Bool(ctx, false as i8); + } + + panic!("isinf() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_isnan( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(_x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Bool(ctx, false as i8); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Bool(ctx, x.is_nan() as i8); + } + + panic!("isnan() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_modf( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + let list = ValueRef::list_float(&[0.0, x as f64]); + return list.into_raw(ctx); + } + if let Some(x) = args.arg_i_float(0, None) { + if !x.is_finite() { + if x.is_infinite() { + let list = ValueRef::list_float(&[0.0_f64.copysign(x), x]); + return list.into_raw(ctx); + } else if x.is_nan() { + let list = ValueRef::list_float(&[x, x]); + return list.into_raw(ctx); + } + } + let list = ValueRef::list_float(&[x.fract(), x.trunc()]); + return list.into_raw(ctx); + } + + panic!("modf() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_exp( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Float(ctx, (x as f64).exp()); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.exp()); + } + panic!("exp() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_expm1( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Float(ctx, (x as f64).exp_m1()); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.exp_m1()); + } + panic!("expm1() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_log( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + if let Some(base) = args.arg_i_float(1, Some(std::f64::consts::E)) { + return kclvm_value_Int(ctx, (x as f64).log(base) as i64); + } + } + if let Some(x) = args.arg_i_float(0, None) { + if let Some(base) = args.arg_i_float(1, Some(std::f64::consts::E)) { + return kclvm_value_Float(ctx, x.log(base)); + } + } + panic!("log() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_log1p( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Float(ctx, ((x + 1) as f64).ln_1p()); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, (x + 1.0).ln_1p()); + } + panic!("log1p() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_log2( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Int(ctx, (x as f64).log2() as i64); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.log2()); + } + panic!("log2() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_log10( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Float(ctx, (x as f64).log10()); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.log10()); + } + panic!("log10() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_pow( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + if let Some(n) = args.arg_i_int_or_bool(1, None) { + if n < 0 { + return kclvm_value_Float(ctx, (x as f64).powf(n as f64)); + } else { + return kclvm_value_Int(ctx, x.pow(n as u32)); + } + } + if let Some(n) = args.arg_i_float(1, None) { + return kclvm_value_Float(ctx, (x as f64).powf(n)); + } + } + if let Some(x) = args.arg_i_float(0, None) { + if let Some(n) = args.arg_i_int_or_bool(1, None) { + return kclvm_value_Float(ctx, x.powi(n as i32)); + } + if let Some(n) = args.arg_i_float(1, None) { + return kclvm_value_Float(ctx, x.powf(n)); + } + } + panic!("pow() takes exactly one argument (0 given)"); +} + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_math_sqrt( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(x) = args.arg_i_int_or_bool(0, None) { + return kclvm_value_Float(ctx, (x as f64).sqrt()); + } + if let Some(x) = args.arg_i_float(0, None) { + return kclvm_value_Float(ctx, x.sqrt()); + } + panic!("sqrt() takes exactly one argument (0 given)"); +} diff --git a/kclvm/runtime/src/net/mod.rs b/kclvm/runtime/src/net/mod.rs index 84dc29eb9..17fb1355b 100644 --- a/kclvm/runtime/src/net/mod.rs +++ b/kclvm/runtime/src/net/mod.rs @@ -1,4 +1,411 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod net; -pub use self::net::*; +use std::net::Ipv4Addr; +use std::net::Ipv6Addr; +use std::str::FromStr; + +use crate::*; + +// split_host_port(ip_end_point: str) -> List[str] + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_split_host_port( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(string) = args.arg_i_str(0, None) { + let mut list = ValueRef::list(None); + for s in string.split(':') { + list.list_append(&ValueRef::str(s)); + } + return list.into_raw(ctx); + } + + panic!("split_host_port() missing 1 required positional argument: 'ip_end_point'"); +} + +// join_host_port(host, port) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_join_host_port( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + + if let Some(host) = args.arg_i_str(0, None) { + if let Some(port) = args.arg_i_int(1, None) { + let s = format!("{host}:{port}"); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + if let Some(port) = args.arg_i_str(1, None) { + let s = format!("{host}:{port}"); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + } + panic!("join_host_port() missing 2 required positional arguments: 'host' and 'port'"); +} + +// fqdn(name: str = '') -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_fqdn( + _ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(_name) = args.arg_i_str(0, Some("".to_string())) { + todo!("todo"); + } + panic!("fqdn() missing 1 required positional argument: 'name'"); +} + +// parse_IP(ip) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_parse_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + kclvm_net_IP_string(ctx, args, kwargs) +} + +// to_IP4(ip) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_to_IP4( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + kclvm_net_IP_string(ctx, args, kwargs) +} + +// to_IP16(ip) -> int + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_to_IP16( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + kclvm_net_IP_string(ctx, args, kwargs) +} + +// IP_string(ip: str) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_IP_string( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let s = format!("{addr}"); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + let s = format!("{addr}"); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + + return ValueRef::str("").into_raw(ctx); + } + + panic!("IP_string() missing 1 required positional argument: 'ip'"); +} + +// is_IPv4(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_IPv4( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(_addr) = Ipv4Addr::from_str(ip.as_ref()) { + return kclvm_value_True(ctx); + } + if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { + return kclvm_value_False(ctx); + } + + return kclvm_value_False(ctx); + } + + panic!("is_IPv4() missing 1 required positional argument: 'ip'"); +} + +// is_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if Ipv4Addr::from_str(ip.as_ref()).is_ok() || Ipv6Addr::from_str(ip.as_ref()).is_ok() { + kclvm_value_True(ctx) + } else { + kclvm_value_False(ctx) + } + } else { + panic!("is_IP() missing 1 required positional argument: 'ip'"); + } +} + +// is_loopback_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_loopback_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let x = addr.is_loopback(); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + let x = addr.is_loopback(); + return kclvm_value_Bool(ctx, x as i8); + } + + return kclvm_value_False(ctx); + } + + panic!("is_loopback_IP() missing 1 required positional argument: 'ip'"); +} + +// is_multicast_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_multicast_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let x = addr.is_multicast(); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + let x = addr.is_multicast(); + return kclvm_value_Bool(ctx, x as i8); + } + + return kclvm_value_False(ctx); + } + + panic!("kclvm_net_is_multicast_IP() missing 1 required positional argument: 'ip'"); +} + +// is_interface_local_multicast_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_interface_local_multicast_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let is_site_local = false; // TODO + let x = is_site_local && addr.is_multicast(); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { + todo!("todo"); + } + + return kclvm_value_False(ctx); + } + + panic!("is_interface_local_multicast_IP() missing 1 required positional argument: 'ip'"); +} + +// is_link_local_multicast_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_link_local_multicast_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let x = addr.is_link_local() && addr.is_multicast(); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + let is_link_local = false; // TODO + let x = is_link_local && addr.is_multicast(); + return kclvm_value_Bool(ctx, x as i8); + } + + return kclvm_value_False(ctx); + } + + panic!("is_link_local_multicast_IP() missing 1 required positional argument: 'ip'"); +} + +// is_link_local_unicast_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_link_local_unicast_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let _kwargs = ptr_as_ref(kwargs); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let x = addr.is_link_local() && (!addr.is_multicast()); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { + let x = Ipv6Addr_is_unicast_link_local(&_addr) && (!_addr.is_multicast()); + return kclvm_value_Bool(ctx, x as i8); + } + return kclvm_value_False(ctx); + } + + panic!("is_link_local_unicast_IP() missing 1 required positional argument: 'ip'"); +} + +#[allow(non_camel_case_types, non_snake_case)] +pub const fn Ipv6Addr_is_unicast_link_local(_self: &Ipv6Addr) -> bool { + (_self.segments()[0] & 0xffc0) == 0xfe80 +} + +// is_global_unicast_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_global_unicast_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + let x = Ipv4Addr_is_global(&addr) && (!addr.is_multicast()); + return kclvm_value_Bool(ctx, x as i8); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + return kclvm_value_Bool(ctx, addr.is_multicast() as i8); + } + + return kclvm_value_False(ctx); + } + + panic!("is_global_unicast_IP() missing 1 required positional argument: 'ip'"); +} + +#[allow(non_camel_case_types, non_snake_case)] +fn Ipv4Addr_is_global(_self: &std::net::Ipv4Addr) -> bool { + // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two + // globally routable addresses in the 192.0.0.0/24 range. + if u32::from_be_bytes(_self.octets()) == 0xc0000009 + || u32::from_be_bytes(_self.octets()) == 0xc000000a + { + return true; + } + !_self.is_private() + && !_self.is_loopback() + && !_self.is_link_local() + && !_self.is_broadcast() + && !_self.is_documentation() + && !Ipv4Addr_is_shared(_self) // _self.is_shared() + && !Ipv4Addr_is_ietf_protocol_assignment(_self) // _self.is_ietf_protocol_assignment() + && !Ipv4Addr_is_reserved(_self) // _self.is_reserved() + && !Ipv4Addr_is_benchmarking(_self) // _self.is_benchmarking() + // Make sure the address is not in 0.0.0.0/8 + && _self.octets()[0] != 0 +} + +#[allow(non_camel_case_types, non_snake_case)] +const fn Ipv4Addr_is_shared(_self: &std::net::Ipv4Addr) -> bool { + _self.octets()[0] == 100 && (_self.octets()[1] & 0b1100_0000 == 0b0100_0000) +} +#[allow(non_camel_case_types, non_snake_case)] +const fn Ipv4Addr_is_ietf_protocol_assignment(_self: &std::net::Ipv4Addr) -> bool { + _self.octets()[0] == 192 && _self.octets()[1] == 0 && _self.octets()[2] == 0 +} +#[allow(non_camel_case_types, non_snake_case)] +const fn Ipv4Addr_is_reserved(_self: &std::net::Ipv4Addr) -> bool { + _self.octets()[0] & 240 == 240 && !_self.is_broadcast() +} +#[allow(non_camel_case_types, non_snake_case)] +const fn Ipv4Addr_is_benchmarking(_self: &std::net::Ipv4Addr) -> bool { + _self.octets()[0] == 198 && (_self.octets()[1] & 0xfe) == 18 +} + +// is_unspecified_IP(ip: str) -> bool + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_net_is_unspecified_IP( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(ip) = args.arg_i_str(0, None) { + if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { + return kclvm_value_Bool(ctx, addr.is_unspecified() as i8); + } + if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { + return kclvm_value_Bool(ctx, addr.is_unspecified() as i8); + } + return kclvm_value_False(ctx); + } + panic!("is_unspecified_IP() missing 1 required positional argument: 'ip'"); +} diff --git a/kclvm/runtime/src/net/net.rs b/kclvm/runtime/src/net/net.rs deleted file mode 100644 index e5fafc248..000000000 --- a/kclvm/runtime/src/net/net.rs +++ /dev/null @@ -1,419 +0,0 @@ -//! KCL net system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use std::net::Ipv4Addr; -use std::net::Ipv6Addr; -use std::str::FromStr; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// split_host_port(ip_end_point: str) -> List[str] - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_split_host_port( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - let mut list = ValueRef::list(None); - for s in string.split(':') { - list.list_append(&ValueRef::str(s)); - } - return list.into_raw(); - } - - panic!("split_host_port() missing 1 required positional argument: 'ip_end_point'"); -} - -// join_host_port(host, port) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_join_host_port( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(host) = args.arg_i_str(0, None) { - if let Some(port) = args.arg_i_int(1, None) { - let s = format!("{host}:{port}"); - return ValueRef::str(s.as_ref()).into_raw(); - } - if let Some(port) = args.arg_i_str(1, None) { - let s = format!("{host}:{port}"); - return ValueRef::str(s.as_ref()).into_raw(); - } - } - panic!("join_host_port() missing 2 required positional arguments: 'host' and 'port'"); -} - -// fqdn(name: str = '') -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_fqdn( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(_name) = args.arg_i_str(0, Some("".to_string())) { - todo!("todo"); - } - panic!("fqdn() missing 1 required positional argument: 'name'"); -} - -// parse_IP(ip) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_parse_IP( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - kclvm_net_IP_string(ctx, args, kwargs) -} - -// to_IP4(ip) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_to_IP4( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - kclvm_net_IP_string(ctx, args, kwargs) -} - -// to_IP16(ip) -> int - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_to_IP16( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - kclvm_net_IP_string(ctx, args, kwargs) -} - -// IP_string(ip: str) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_IP_string( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let s = format!("{addr}"); - return ValueRef::str(s.as_ref()).into_raw(); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - let s = format!("{addr}"); - return ValueRef::str(s.as_ref()).into_raw(); - } - - return kclvm_value_False(); - } - - panic!("IP_string() missing 1 required positional argument: 'ip'"); -} - -// is_IPv4(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_IPv4( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(_addr) = Ipv4Addr::from_str(ip.as_ref()) { - return kclvm_value_True(); - } - if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { - return kclvm_value_False(); - } - - return kclvm_value_False(); - } - - panic!("is_IPv4() missing 1 required positional argument: 'ip'"); -} - -// is_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(..) = Ipv4Addr::from_str(ip.as_ref()) { - return kclvm_value_True(); - } - if let Ok(..) = Ipv6Addr::from_str(ip.as_ref()) { - return kclvm_value_True(); - } - - return kclvm_value_False(); - } - - panic!("is_IP() missing 1 required positional argument: 'ip'"); -} - -// is_loopback_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_loopback_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let x = addr.is_loopback(); - return kclvm_value_Bool(x as i8); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - let x = addr.is_loopback(); - return kclvm_value_Bool(x as i8); - } - - return kclvm_value_False(); - } - - panic!("is_loopback_IP() missing 1 required positional argument: 'ip'"); -} - -// is_multicast_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_multicast_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let x = addr.is_multicast(); - return kclvm_value_Bool(x as i8); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - let x = addr.is_multicast(); - return kclvm_value_Bool(x as i8); - } - - return kclvm_value_False(); - } - - panic!("kclvm_net_is_multicast_IP() missing 1 required positional argument: 'ip'"); -} - -// is_interface_local_multicast_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_interface_local_multicast_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let is_site_local = false; // TODO - let x = is_site_local && addr.is_multicast(); - return kclvm_value_Bool(x as i8); - } - if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { - todo!("todo"); - } - - return kclvm_value_False(); - } - - panic!("is_interface_local_multicast_IP() missing 1 required positional argument: 'ip'"); -} - -// is_link_local_multicast_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_link_local_multicast_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let x = addr.is_link_local() && addr.is_multicast(); - return kclvm_value_Bool(x as i8); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - let is_link_local = false; // TODO - let x = is_link_local && addr.is_multicast(); - return kclvm_value_Bool(x as i8); - } - - return kclvm_value_False(); - } - - panic!("is_link_local_multicast_IP() missing 1 required positional argument: 'ip'"); -} - -// is_link_local_unicast_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_link_local_unicast_IP( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let x = addr.is_link_local() && (!addr.is_multicast()); - return kclvm_value_Bool(x as i8); - } - if let Ok(_addr) = Ipv6Addr::from_str(ip.as_ref()) { - let x = Ipv6Addr_is_unicast_link_local(&_addr) && (!_addr.is_multicast()); - return kclvm_value_Bool(x as i8); - } - return kclvm_value_False(); - } - - panic!("is_link_local_unicast_IP() missing 1 required positional argument: 'ip'"); -} - -#[allow(non_camel_case_types, non_snake_case)] -pub const fn Ipv6Addr_is_unicast_link_local(_self: &Ipv6Addr) -> bool { - (_self.segments()[0] & 0xffc0) == 0xfe80 -} - -// is_global_unicast_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_global_unicast_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - let x = Ipv4Addr_is_global(&addr) && (!addr.is_multicast()); - return kclvm_value_Bool(x as i8); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - return kclvm_value_Bool(addr.is_multicast() as i8); - } - - return kclvm_value_False(); - } - - panic!("is_global_unicast_IP() missing 1 required positional argument: 'ip'"); -} - -#[allow(non_camel_case_types, non_snake_case)] -fn Ipv4Addr_is_global(_self: &std::net::Ipv4Addr) -> bool { - // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two - // globally routable addresses in the 192.0.0.0/24 range. - if u32::from_be_bytes(_self.octets()) == 0xc0000009 - || u32::from_be_bytes(_self.octets()) == 0xc000000a - { - return true; - } - !_self.is_private() - && !_self.is_loopback() - && !_self.is_link_local() - && !_self.is_broadcast() - && !_self.is_documentation() - && !Ipv4Addr_is_shared(_self) // _self.is_shared() - && !Ipv4Addr_is_ietf_protocol_assignment(_self) // _self.is_ietf_protocol_assignment() - && !Ipv4Addr_is_reserved(_self) // _self.is_reserved() - && !Ipv4Addr_is_benchmarking(_self) // _self.is_benchmarking() - // Make sure the address is not in 0.0.0.0/8 - && _self.octets()[0] != 0 -} - -#[allow(non_camel_case_types, non_snake_case)] -const fn Ipv4Addr_is_shared(_self: &std::net::Ipv4Addr) -> bool { - _self.octets()[0] == 100 && (_self.octets()[1] & 0b1100_0000 == 0b0100_0000) -} -#[allow(non_camel_case_types, non_snake_case)] -const fn Ipv4Addr_is_ietf_protocol_assignment(_self: &std::net::Ipv4Addr) -> bool { - _self.octets()[0] == 192 && _self.octets()[1] == 0 && _self.octets()[2] == 0 -} -#[allow(non_camel_case_types, non_snake_case)] -const fn Ipv4Addr_is_reserved(_self: &std::net::Ipv4Addr) -> bool { - _self.octets()[0] & 240 == 240 && !_self.is_broadcast() -} -#[allow(non_camel_case_types, non_snake_case)] -const fn Ipv4Addr_is_benchmarking(_self: &std::net::Ipv4Addr) -> bool { - _self.octets()[0] == 198 && (_self.octets()[1] & 0xfe) == 18 -} - -// is_unspecified_IP(ip: str) -> bool - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_net_is_unspecified_IP( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(ip) = args.arg_i_str(0, None) { - if let Ok(addr) = Ipv4Addr::from_str(ip.as_ref()) { - return kclvm_value_Bool(addr.is_unspecified() as i8); - } - if let Ok(addr) = Ipv6Addr::from_str(ip.as_ref()) { - return kclvm_value_Bool(addr.is_unspecified() as i8); - } - return kclvm_value_False(); - } - panic!("is_unspecified_IP() missing 1 required positional argument: 'ip'"); -} diff --git a/kclvm/runtime/src/regex/mod.rs b/kclvm/runtime/src/regex/mod.rs index 71be7d77c..6192bfaa4 100644 --- a/kclvm/runtime/src/regex/mod.rs +++ b/kclvm/runtime/src/regex/mod.rs @@ -1,4 +1,189 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod regex; -pub use self::regex::*; +extern crate fancy_regex; + +use crate::*; + +// match(string: str, pattern: str) -> bool: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_match( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(string) = args.arg_i_str(0, None) { + if let Some(pattern) = args.arg_i_str(1, None) { + let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); + match re.is_match(string.as_ref()) { + Ok(ok) => { + if ok { + return kclvm_value_Bool(ctx, 1); + } else { + return kclvm_value_Bool(ctx, 0); + } + } + _ => return kclvm_value_Bool(ctx, 0), + } + } + } + + panic!("match() missing 2 required positional arguments: 'string' and 'pattern'") +} + +// replace(string: str, pattern: str, replace: str, count: int = 0): + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_replace( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(string) = args.arg_i_str(0, None) { + if let Some(pattern) = args.arg_i_str(1, None) { + if let Some(replace) = args.arg_i_str(2, None) { + if let Some(count) = args.arg_i_int(3, Some(0)) { + let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); + let s = re.replacen(string.as_ref(), count as usize, replace.as_ref() as &str); + return ValueRef::str(&s).into_raw(ctx); + } + } + } + } + panic!("replace() missing 3 required positional arguments: 'string', 'pattern', and 'replace"); +} + +// compile(pattern: str) -> bool: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_compile( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(pattern) = args.arg_i_str(0, None) { + match fancy_regex::Regex::new(pattern.as_ref()) { + Ok(_) => return kclvm_value_Bool(ctx, 1), + _ => return kclvm_value_Bool(ctx, 0), + } + } + panic!("compile() missing 2 required positional arguments: 'string' and 'pattern'") +} + +// findall(string: str, pattern: str) -> [str]: + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_findall( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(string) = args.arg_i_str(0, None) { + if let Some(pattern) = args.arg_i_str(1, None) { + let mut list = ValueRef::list(None); + + for x in fancy_regex::Regex::new(pattern.as_ref()) + .unwrap() + .captures_iter(string.as_ref()) + .flatten() + { + let len = x.len(); + if len < 3 { + list.list_append(&ValueRef::str(x.get(0).unwrap().as_str())); + } else { + let mut sub_list = ValueRef::list(None); + for i in 1..len { + sub_list.list_append(&ValueRef::str(x.get(i).unwrap().as_str())); + } + list.list_append(&sub_list) + } + } + + return list.into_raw(ctx); + } + } + + panic!("findall() missing 2 required positional arguments: 'string' and 'pattern'") +} + +// search(string: str, pattern: str): + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_search( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + + if let Some(string) = args.arg_i_str(0, None) { + if let Some(pattern) = args.arg_i_str(1, None) { + let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); + + if let Ok(Some(..)) = re.find(string.as_ref()) { + return kclvm_value_Bool(ctx, 1); + } + return kclvm_value_Bool(ctx, 0); + } + } + panic!("search() missing 2 required positional arguments: 'string' and 'pattern'"); +} + +// split(string: str, pattern: str, maxsplit: int = 0): + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_regex_split( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *mut kclvm_value_ref_t { + let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); + if let Some(string) = args.arg_i_str(0, None) { + if let Some(pattern) = args.arg_i_str(1, None) { + if let Some(maxsplit) = args.arg_i_int(2, Some(0)) { + let mut list = ValueRef::list(None); + + let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); + + let mut fields: Vec = Vec::new(); + let mut current_pos = 0; + loop { + let capture = re + .captures_from_pos(string.as_ref(), current_pos) + .map_or(None, |c| c); + if let Some(Some(cap)) = capture.map(|c| c.get(0)) { + fields.push(string[current_pos..cap.start()].to_string()); + if maxsplit > 0 && fields.len() >= (maxsplit as usize) { + break; + } + current_pos = cap.end(); + } else { + fields.push(string[current_pos..].to_string()); + break; + } + } + + for s in fields { + list.list_append(&ValueRef::str(s.as_ref())); + } + return list.into_raw(ctx); + } + } + } + panic!("split() missing 2 required positional arguments: 'string' and 'pattern'"); +} diff --git a/kclvm/runtime/src/regex/regex.rs b/kclvm/runtime/src/regex/regex.rs deleted file mode 100644 index 01ff95903..000000000 --- a/kclvm/runtime/src/regex/regex.rs +++ /dev/null @@ -1,201 +0,0 @@ -//! KCL regex system module -//! regex.match(string: str, pattern: str) -> bool -//! regex.replace(string: str, pattern: str, replace: str, count: int = 0) -> str -//! regex.compile(pattern: str) -> bool -//! regex.findall(string: str, pattern: str) -> [str] -//! regex.search(string: str, pattern: str) -> bool -//! regex.split(string: str, pattern: str, maxsplit: int = 0) -> [str] -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -extern crate fancy_regex; - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// def KMANGLED_match(string: str, pattern: str) -> bool: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_match( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - if let Some(pattern) = args.arg_i_str(1, None) { - let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); - match re.is_match(string.as_ref()) { - Ok(ok) => { - if ok { - return kclvm_value_Bool(1); - } else { - return kclvm_value_Bool(0); - } - } - _ => return kclvm_value_Bool(0), - } - } - } - - panic!("match() missing 2 required positional arguments: 'string' and 'pattern'") -} - -// def KMANGLED_replace(string: str, pattern: str, replace: str, count: int = 0): - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_replace( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - if let Some(pattern) = args.arg_i_str(1, None) { - if let Some(replace) = args.arg_i_str(2, None) { - if let Some(count) = args.arg_i_int(3, Some(0)) { - let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); - let s = re.replacen(string.as_ref(), count as usize, replace.as_ref() as &str); - return ValueRef::str(&s).into_raw(); - } - } - } - } - panic!("replace() missing 3 required positional arguments: 'string', 'pattern', and 'replace"); -} - -// def KMANGLED_compile(pattern: str) -> bool: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_compile( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(pattern) = args.arg_i_str(0, None) { - match fancy_regex::Regex::new(pattern.as_ref()) { - Ok(_) => return kclvm_value_Bool(1), - _ => return kclvm_value_Bool(0), - } - } - panic!("compile() missing 2 required positional arguments: 'string' and 'pattern'") -} - -// def KMANGLED_findall(string: str, pattern: str) -> [str]: - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_findall( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - if let Some(pattern) = args.arg_i_str(1, None) { - let mut list = ValueRef::list(None); - - for x in fancy_regex::Regex::new(pattern.as_ref()) - .unwrap() - .captures_iter(string.as_ref()) - .flatten() - { - let len = x.len(); - if len < 3 { - list.list_append(&ValueRef::str(x.get(0).unwrap().as_str())); - } else { - let mut sub_list = ValueRef::list(None); - for i in 1..len { - sub_list.list_append(&ValueRef::str(x.get(i).unwrap().as_str())); - } - list.list_append(&sub_list) - } - } - - return list.into_raw(); - } - } - - panic!("findall() missing 2 required positional arguments: 'string' and 'pattern'") -} - -// def KMANGLED_search(string: str, pattern: str): - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_search( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - if let Some(pattern) = args.arg_i_str(1, None) { - let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); - - if let Ok(Some(..)) = re.find(string.as_ref()) { - return kclvm_value_Bool(1); - } - return kclvm_value_Bool(0); - } - } - panic!("search() missing 2 required positional arguments: 'string' and 'pattern'"); -} - -// def KMANGLED_split(string: str, pattern: str, maxsplit: int = 0): - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_regex_split( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(string) = args.arg_i_str(0, None) { - if let Some(pattern) = args.arg_i_str(1, None) { - if let Some(maxsplit) = args.arg_i_int(2, Some(0)) { - let mut list = ValueRef::list(None); - - let re = fancy_regex::Regex::new(pattern.as_ref()).unwrap(); - - let mut fields: Vec = Vec::new(); - let mut current_pos = 0; - loop { - let capture = re - .captures_from_pos(string.as_ref(), current_pos) - .map_or(None, |c| c); - if let Some(Some(cap)) = capture.map(|c| c.get(0)) { - fields.push(string[current_pos..cap.start()].to_string()); - if maxsplit > 0 && fields.len() >= (maxsplit as usize) { - break; - } - current_pos = cap.end(); - } else { - fields.push(string[current_pos..].to_string()); - break; - } - } - - for s in fields { - list.list_append(&ValueRef::str(s.as_ref())); - } - return list.into_raw(); - } - } - } - panic!("split() missing 2 required positional arguments: 'string' and 'pattern'"); -} diff --git a/kclvm/runtime/src/stdlib/assert_api.rs b/kclvm/runtime/src/stdlib/assert_api.rs index 798f3d88f..34c6cb007 100644 --- a/kclvm/runtime/src/stdlib/assert_api.rs +++ b/kclvm/runtime/src/stdlib/assert_api.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -7,7 +7,8 @@ type kclvm_value_ref_t = ValueRef; #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_assert( +pub extern "C" fn kclvm_assert( + ctx: *mut kclvm_context_t, value: *const kclvm_value_ref_t, msg: *const kclvm_value_ref_t, ) { @@ -15,8 +16,8 @@ pub unsafe extern "C" fn kclvm_assert( let msg = ptr_as_ref(msg); if !value.is_truthy() { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::AssertionError_TYPE); + let ctx = mut_ptr_as_ref(ctx); + ctx.set_err_type(&RuntimeErrorType::AssertionError); let msg = msg.as_str(); panic!("{}", msg); diff --git a/kclvm/runtime/src/stdlib/builtin.rs b/kclvm/runtime/src/stdlib/builtin.rs index 55005f7a6..cd9f70e1d 100644 --- a/kclvm/runtime/src/stdlib/builtin.rs +++ b/kclvm/runtime/src/stdlib/builtin.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use std::{collections::HashSet, ops::Index}; @@ -6,12 +6,13 @@ use crate::*; impl Context { pub fn builtin_option_init(&mut self, key: &str, value: &str) { - if let Ok(x) = ValueRef::from_json(value) { - self.app_args.insert(key.to_string(), x.into_raw() as u64); + if let Ok(x) = ValueRef::from_json(self, value) { + let addr = x.into_raw(self) as u64; + self.app_args.insert(key.to_string(), addr); return; } - self.app_args - .insert(key.to_string(), ValueRef::str(value).into_raw() as u64); + let addr = ValueRef::str(value).into_raw(self) as u64; + self.app_args.insert(key.to_string(), addr); } pub fn builtin_option_reset(&mut self) { @@ -153,8 +154,7 @@ impl ValueRef { } } - pub fn convert_to_int(&self, base: Option<&ValueRef>) -> ValueRef { - let ctx = crate::Context::current_context_mut(); + pub fn convert_to_int(&self, ctx: &mut Context, base: Option<&ValueRef>) -> ValueRef { let strict_range_check_i32 = ctx.cfg.strict_range_check; let strict_range_check_i64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; @@ -168,14 +168,12 @@ impl ValueRef { if ctx.cfg.debug_mode { if int_32_overflow { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{v_i128}: A 32 bit integer overflow"); } if int_64_overflow { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{v_i128}: A 64 bit integer overflow"); } @@ -194,14 +192,13 @@ impl ValueRef { ValueRef::int(v) } _ => panic!( - "int() argument must be a string, a bytes-like object or a number, not '{}'", + "int() argument must be a string or a number, not '{}'", self.type_str() ), } } - pub fn convert_to_float(&self) -> ValueRef { - let ctx = crate::Context::current_context_mut(); + pub fn convert_to_float(&self, ctx: &mut Context) -> ValueRef { let strict_range_check_i32 = ctx.cfg.strict_range_check; let strict_range_check_i64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; @@ -212,12 +209,12 @@ impl ValueRef { let float64_overflow = strict_range_check_i64 && (*v).is_infinite(); if float32_overflow { - ctx.set_err_type(&ErrType::FloatOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::FloatOverflow); panic!("inf: A 32-bit floating point number overflow"); } if float64_overflow { - ctx.set_err_type(&ErrType::FloatOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::FloatOverflow); panic!("inf: A 64-bit floating point number overflow"); } @@ -232,12 +229,12 @@ impl ValueRef { let float32_overflow = strict_range_check_i32 && (v as f32).is_infinite(); let float64_overflow = strict_range_check_i64 && (v).is_infinite(); if float32_overflow { - ctx.set_err_type(&ErrType::FloatOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::FloatOverflow); panic!("inf: A 32-bit floating point number overflow"); } if float64_overflow { - ctx.set_err_type(&ErrType::FloatOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::FloatOverflow); panic!("inf: A 64-bit floating point number overflow"); } @@ -361,7 +358,7 @@ impl ValueRef { } } - pub fn sum(&self, init_value: &ValueRef) -> ValueRef { + pub fn sum(&self, ctx: &mut Context, init_value: &ValueRef) -> ValueRef { match &*self.rc.borrow() { Value::list_value(list) => { let mut result = match &*init_value.rc.borrow() { @@ -370,7 +367,7 @@ impl ValueRef { }; for val in list.values.iter() { //xx_bin_aug_add() might modify the value of init_value - result = result.bin_add(val) + result = result.bin_add(ctx, val) } result } @@ -451,7 +448,7 @@ pub fn list(iterable: Option<&ValueRef>) -> ValueRef { } } -pub fn dict(iterable: Option<&ValueRef>) -> ValueRef { +pub fn dict(ctx: &mut Context, iterable: Option<&ValueRef>) -> ValueRef { match iterable { Some(val) => { let mut iter = val.iter(); @@ -462,7 +459,7 @@ pub fn dict(iterable: Option<&ValueRef>) -> ValueRef { let k = iter.cur_key.clone(); match &*k.rc.borrow() { Value::str_value(str) => { - result.dict_insert(str.as_str(), &elem, Default::default(), -1); + result.dict_insert(ctx, str.as_str(), &elem, Default::default(), -1); } _ => { let mut elem_iter = elem.iter(); @@ -471,7 +468,7 @@ pub fn dict(iterable: Option<&ValueRef>) -> ValueRef { } let k = elem_iter.next(val).unwrap().to_string(); let v = elem_iter.next(val).unwrap(); - result.dict_insert(k.as_str(), v, Default::default(), -1); + result.dict_insert(ctx, k.as_str(), v, Default::default(), -1); } }; } diff --git a/kclvm/runtime/src/stdlib/builtin_api.rs b/kclvm/runtime/src/stdlib/builtin_api.rs index a52216d5d..5a977f53c 100644 --- a/kclvm/runtime/src/stdlib/builtin_api.rs +++ b/kclvm/runtime/src/stdlib/builtin_api.rs @@ -1,6 +1,8 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #![allow(clippy::missing_safety_doc)] +use std::os::raw::c_char; + use crate::*; #[allow(non_camel_case_types)] @@ -10,8 +12,8 @@ type kclvm_value_ref_t = ValueRef; #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_option_init( ctx: *mut kclvm_context_t, - key: *const i8, - value: *const i8, + key: *const c_char, + value: *const c_char, ) { let ctx = mut_ptr_as_ref(ctx); ctx.builtin_option_init(c2str(key), c2str(value)); @@ -24,10 +26,10 @@ pub unsafe extern "C" fn kclvm_builtin_option_reset( _args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); - ctx.builtin_option_reset(); - kclvm_value_Undefined() + ctx_ref.builtin_option_reset(); + kclvm_value_Undefined(ctx) } // def kcl_option(name: str, *, type="", required=False, default=None, help="", file="", line=0) -> typing.Any: @@ -39,13 +41,13 @@ pub unsafe extern "C" fn kclvm_builtin_option( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); let mut list_option_mode = false; - if ctx.cfg.list_option_mode { + if ctx_ref.cfg.list_option_mode { list_option_mode = true; let name = args.arg_i_str(0, Some("?".to_string())).unwrap(); @@ -58,7 +60,7 @@ pub unsafe extern "C" fn kclvm_builtin_option( default_value = Some(x.to_string()); } - ctx.define_option( + ctx_ref.define_option( name.as_str(), typ.as_str(), required, @@ -213,30 +215,31 @@ pub unsafe extern "C" fn kclvm_builtin_option( } if let Some(arg0) = args.arg_0() { - if let Some(x) = ctx.app_args.get(&arg0.as_str()) { + if let Some(x) = ctx_ref.app_args.get(&arg0.as_str()) { if *x == 0 { - return kclvm_value_Undefined(); + return kclvm_value_Undefined(ctx); } let opt_value = mut_ptr_as_ref((*x) as *mut kclvm_value_ref_t); if let Some(kwarg_type) = kwargs.kwarg_str("type", None) { - return _value_to_type(opt_value, kwarg_type, ctx.cfg.list_option_mode).into_raw(); + return _value_to_type(opt_value, kwarg_type, ctx_ref.cfg.list_option_mode) + .into_raw(ctx_ref); } return (*x) as *mut kclvm_value_ref_t; } else if let Some(kwarg_default) = kwargs.kwarg("default") { if let Some(kwarg_type) = kwargs.kwarg_str("type", None) { - return _value_to_type(&kwarg_default, kwarg_type, ctx.cfg.list_option_mode) - .into_raw(); + return _value_to_type(&kwarg_default, kwarg_type, ctx_ref.cfg.list_option_mode) + .into_raw(ctx_ref); } - return kwarg_default.into_raw(); + return kwarg_default.into_raw(ctx_ref); } } if list_option_mode { - return kclvm_value_None(); + return kclvm_value_None(ctx); } let required = kwargs.kwarg_bool("required", Some(false)).unwrap(); @@ -245,7 +248,7 @@ pub unsafe extern "C" fn kclvm_builtin_option( panic!("option('{name}') must be initialized, try '-D {name}=?' argument"); } - kclvm_value_None() + kclvm_value_None(ctx) } #[no_mangle] @@ -255,36 +258,34 @@ pub unsafe extern "C" fn kclvm_builtin_print( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); + let ctx_ref = mut_ptr_as_ref(ctx); // args let list = args.as_list_ref(); let values: Vec = list.values.iter().map(|v| v.to_string()).collect(); - print!("{}", values.join(" ")); + ctx_ref.log_message.push_str(&values.join(" ")); let dict = kwargs.as_dict_ref(); // kwargs: end if let Some(c) = dict.values.get("end") { - print!("{c}"); - use std::io::Write; - let _ = std::io::stdout().flush(); + ctx_ref.log_message.push_str(&format!("{c}")); } else { - println!(); + ctx_ref.log_message.push('\n'); } - kclvm_value_None() + kclvm_value_None(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_len( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(arg) = args.arg_0() { - return kclvm_value_Int(arg.len() as i64); + return kclvm_value_Int(ctx, arg.len() as i64); } panic!("len() takes exactly one argument (0 given)"); } @@ -296,14 +297,13 @@ pub unsafe extern "C" fn kclvm_builtin_any_true( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return kclvm_value_Bool(arg0.any_true() as i8); + return kclvm_value_Bool(ctx, arg0.any_true() as i8); } - kclvm_value_Bool(0) + kclvm_value_Bool(ctx, 0) } #[no_mangle] @@ -311,16 +311,14 @@ pub unsafe extern "C" fn kclvm_builtin_any_true( pub unsafe extern "C" fn kclvm_builtin_isunique( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return kclvm_value_Bool(arg0.isunique() as i8); + return kclvm_value_Bool(ctx, arg0.isunique() as i8); } - kclvm_value_Bool(0) + kclvm_value_Bool(ctx, 0) } #[no_mangle] @@ -330,13 +328,13 @@ pub unsafe extern "C" fn kclvm_builtin_sorted( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { let reverse = kwargs.kwarg("reverse"); - return arg0.sorted(reverse.as_ref()).into_raw(); + return arg0.sorted(reverse.as_ref()).into_raw(ctx); } panic!("sorted() takes exactly one argument (0 given)"); } @@ -348,13 +346,13 @@ pub unsafe extern "C" fn kclvm_builtin_int( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { let base = args.arg_i(1).or_else(|| kwargs.kwarg("base")); - return arg0.convert_to_int(base.as_ref()).into_raw(); + return arg0.convert_to_int(ctx, base.as_ref()).into_raw(ctx); } panic!("int() takes exactly one argument (0 given)"); } @@ -366,12 +364,12 @@ pub unsafe extern "C" fn kclvm_builtin_float( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.convert_to_float().into_raw(); + return arg0.convert_to_float(ctx).into_raw(ctx); } panic!("float() takes exactly one argument (0 given)"); } @@ -379,14 +377,15 @@ pub unsafe extern "C" fn kclvm_builtin_float( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_bool( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); if let Some(arg0) = args.arg_0() { - return ValueRef::bool(arg0.is_truthy()).into_raw(); + return ValueRef::bool(arg0.is_truthy()).into_raw(ctx); } panic!("bool() takes exactly one argument (0 given)"); } @@ -394,16 +393,17 @@ pub unsafe extern "C" fn kclvm_builtin_bool( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); + let ctx = mut_ptr_as_ref(ctx); if let Some(arg0) = args.arg_0() { - return ValueRef::str(&arg0.to_string()).into_raw(); + return ValueRef::str(&arg0.to_string()).into_raw(ctx); } - ValueRef::str("").into_raw() + ValueRef::str("").into_raw(ctx) } #[no_mangle] @@ -411,16 +411,15 @@ pub unsafe extern "C" fn kclvm_builtin_str( pub unsafe extern "C" fn kclvm_builtin_max( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if args.args_len() > 1 { - return args.max_value().into_raw(); + return args.max_value().into_raw(ctx); } if let Some(arg0) = args.arg_0() { - return arg0.max_value().into_raw(); + return arg0.max_value().into_raw(ctx); } panic!("max() takes exactly one argument (0 given)"); } @@ -430,16 +429,15 @@ pub unsafe extern "C" fn kclvm_builtin_max( pub unsafe extern "C" fn kclvm_builtin_min( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if args.args_len() > 1 { - return args.min_value().into_raw(); + return args.min_value().into_raw(ctx); } if let Some(arg0) = args.arg_0() { - return arg0.min_value().into_raw(); + return arg0.min_value().into_raw(ctx); } panic!("min() takes exactly one argument (0 given)"); } @@ -449,13 +447,12 @@ pub unsafe extern "C" fn kclvm_builtin_min( pub unsafe extern "C" fn kclvm_builtin_multiplyof( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let (Some(arg0), Some(arg1)) = (args.arg_i(0), args.arg_i(1)) { - return builtin::multiplyof(&arg0, &arg1).into_raw(); + return builtin::multiplyof(&arg0, &arg1).into_raw(ctx); } panic!( "multiplyof() takes exactly two argument ({} given)", @@ -468,13 +465,12 @@ pub unsafe extern "C" fn kclvm_builtin_multiplyof( pub unsafe extern "C" fn kclvm_builtin_abs( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.abs().into_raw(); + return arg0.abs().into_raw(ctx); } panic!("abs() takes exactly one argument (0 given)"); } @@ -484,15 +480,13 @@ pub unsafe extern "C" fn kclvm_builtin_abs( pub unsafe extern "C" fn kclvm_builtin_all_true( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return kclvm_value_Bool(arg0.all_true() as i8); + return kclvm_value_Bool(ctx, arg0.all_true() as i8); } - kclvm_value_Bool(0) + kclvm_value_Bool(ctx, 0) } #[no_mangle] @@ -500,13 +494,12 @@ pub unsafe extern "C" fn kclvm_builtin_all_true( pub unsafe extern "C" fn kclvm_builtin_hex( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.hex().into_raw(); + return arg0.hex().into_raw(ctx); } panic!("hex() takes exactly one argument (0 given)"); } @@ -516,17 +509,16 @@ pub unsafe extern "C" fn kclvm_builtin_hex( pub unsafe extern "C" fn kclvm_builtin_sum( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); match args.arg_i(0) { Some(arg0) => match args.arg_i(1) { - Some(arg1) => arg0.sum(&arg1).into_raw(), - _ => arg0.sum(&ValueRef::int(0)).into_raw(), + Some(arg1) => arg0.sum(ctx_ref, &arg1).into_raw(ctx_ref), + _ => arg0.sum(ctx_ref, &ValueRef::int(0)).into_raw(ctx_ref), }, - _ => kclvm_value_Undefined(), + _ => kclvm_value_Undefined(ctx), } } @@ -535,17 +527,16 @@ pub unsafe extern "C" fn kclvm_builtin_sum( pub unsafe extern "C" fn kclvm_builtin_pow( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); match (args.arg_i(0), args.arg_i(1)) { (Some(arg0), Some(arg1)) => match args.arg_i(2) { - Some(arg2) => builtin::pow(&arg0, &arg1, &arg2).into_raw(), - _ => builtin::pow(&arg0, &arg1, &ValueRef::none()).into_raw(), + Some(arg2) => builtin::pow(&arg0, &arg1, &arg2).into_raw(ctx_ref), + _ => builtin::pow(&arg0, &arg1, &ValueRef::none()).into_raw(ctx_ref), }, - _ => kclvm_value_Undefined(), + _ => kclvm_value_Undefined(ctx), } } @@ -554,17 +545,16 @@ pub unsafe extern "C" fn kclvm_builtin_pow( pub unsafe extern "C" fn kclvm_builtin_round( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); match args.arg_i(0) { Some(arg0) => match args.arg_i(1) { - Some(arg1) => builtin::round(&arg0, &arg1).into_raw(), - _ => builtin::round(&arg0, &ValueRef::none()).into_raw(), + Some(arg1) => builtin::round(&arg0, &arg1).into_raw(ctx_ref), + _ => builtin::round(&arg0, &ValueRef::none()).into_raw(ctx_ref), }, - _ => kclvm_value_Undefined(), + _ => kclvm_value_Undefined(ctx), } } @@ -573,12 +563,11 @@ pub unsafe extern "C" fn kclvm_builtin_round( pub unsafe extern "C" fn kclvm_builtin_zip( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - args.zip().into_raw() + args.zip().into_raw(ctx) } #[no_mangle] @@ -586,18 +575,17 @@ pub unsafe extern "C" fn kclvm_builtin_zip( pub unsafe extern "C" fn kclvm_builtin_list( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if args.args_len() > 0 { if let Some(arg0) = args.arg_0() { - return builtin::list(Some(&arg0)).into_raw(); + return builtin::list(Some(&arg0)).into_raw(ctx); } panic!("invalid arguments in list() function"); } else { - builtin::list(None).into_raw() + builtin::list(None).into_raw(ctx) } } @@ -608,15 +596,17 @@ pub unsafe extern "C" fn kclvm_builtin_dict( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); let mut dict = ValueRef::dict(None); if let Some(arg0) = args.arg_0() { - dict.dict_insert_unpack(&builtin::dict(Some(&arg0))); + let v = builtin::dict(ctx, Some(&arg0)); + dict.dict_insert_unpack(ctx, &v); } - dict.dict_insert_unpack(&builtin::dict(Some(kwargs))); - dict.into_raw() + let v = builtin::dict(ctx, Some(kwargs)); + dict.dict_insert_unpack(ctx, &v); + dict.into_raw(ctx) } #[no_mangle] @@ -626,14 +616,14 @@ pub unsafe extern "C" fn kclvm_builtin_typeof( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { if let Some(full_name) = kwargs.kwarg("full_name") { - return builtin::type_of(&arg0, &full_name).into_raw(); + return builtin::type_of(&arg0, &full_name).into_raw(ctx); } - return builtin::type_of(&arg0, &ValueRef::bool(false)).into_raw(); + return builtin::type_of(&arg0, &ValueRef::bool(false)).into_raw(ctx); } panic!("typeof() missing 1 required positional argument: 'x'"); @@ -644,13 +634,12 @@ pub unsafe extern "C" fn kclvm_builtin_typeof( pub unsafe extern "C" fn kclvm_builtin_bin( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.bin().into_raw(); + return arg0.bin().into_raw(ctx); } panic!("bin() takes exactly one argument (0 given)"); } @@ -660,13 +649,12 @@ pub unsafe extern "C" fn kclvm_builtin_bin( pub unsafe extern "C" fn kclvm_builtin_oct( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.oct().into_raw(); + return arg0.oct().into_raw(ctx); } panic!("oct() takes exactly one argument (0 given)"); } @@ -676,16 +664,12 @@ pub unsafe extern "C" fn kclvm_builtin_oct( pub unsafe extern "C" fn kclvm_builtin_ord( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - let _ctx = mut_ptr_as_ref(ctx); + let ctx = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); if let Some(arg0) = args.arg_0() { - return arg0.ord().into_raw(); + return arg0.ord().into_raw(ctx); } panic!("ord() takes exactly one argument (0 given)"); } @@ -695,19 +679,18 @@ pub unsafe extern "C" fn kclvm_builtin_ord( pub unsafe extern "C" fn kclvm_builtin_range( ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); match args.arg_i(0) { Some(arg0) => match args.arg_i(1) { Some(arg1) => match args.arg_i(2) { - Some(arg2) => builtin::range(&arg0, &arg1, &arg2).into_raw(), - _ => builtin::range(&arg0, &arg1, &ValueRef::int(1)).into_raw(), + Some(arg2) => builtin::range(&arg0, &arg1, &arg2).into_raw(ctx_ref), + _ => builtin::range(&arg0, &arg1, &ValueRef::int(1)).into_raw(ctx_ref), }, - _ => builtin::range(&ValueRef::int(0), &arg0, &ValueRef::int(1)).into_raw(), + _ => builtin::range(&ValueRef::int(0), &arg0, &ValueRef::int(1)).into_raw(ctx_ref), }, - _ => kclvm_value_Undefined(), + _ => kclvm_value_Undefined(ctx), } } diff --git a/kclvm/runtime/src/stdlib/mod.rs b/kclvm/runtime/src/stdlib/mod.rs index 74325147a..1b30846d6 100644 --- a/kclvm/runtime/src/stdlib/mod.rs +++ b/kclvm/runtime/src/stdlib/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod assert_api; pub use assert_api::*; diff --git a/kclvm/runtime/src/stdlib/plugin.rs b/kclvm/runtime/src/stdlib/plugin.rs index 93cd1375b..5e70586bb 100644 --- a/kclvm/runtime/src/stdlib/plugin.rs +++ b/kclvm/runtime/src/stdlib/plugin.rs @@ -1,4 +1,5 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. + #![allow(clippy::missing_safety_doc)] use crate::*; @@ -23,19 +24,20 @@ pub extern "C" fn kclvm_plugin_init( } // import kcl_plugin.hello -// hello.SayHello() +// hello.say_hello() // -// => return kclvm_plugin_invoke("kcl_plugin.hello.SayHello", args, kwarge) +// => return kclvm_plugin_invoke("kcl_plugin.hello.say_hello", args, kwargs) #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_plugin_invoke( - method: *const i8, + ctx: *mut kclvm_context_t, + method: *const c_char, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let args_s = kclvm_value_to_json_value_with_null(args); - let kwargs_s = kclvm_value_to_json_value_with_null(kwargs); + let args_s = kclvm_value_to_json_value_with_null(ctx, args); + let kwargs_s = kclvm_value_to_json_value_with_null(ctx, kwargs); let args_json = kclvm_value_Str_ptr(args_s); let kwargs_json = kclvm_value_Str_ptr(kwargs_s); @@ -46,11 +48,11 @@ pub unsafe extern "C" fn kclvm_plugin_invoke( // kclvm_value_delete(args_s); // kclvm_value_delete(kwargs_s); - let ptr = kclvm_value_from_json(result_json); + let ptr = kclvm_value_from_json(ctx, result_json); { if let Some(msg) = ptr_as_ref(ptr).dict_get_value("__kcl_PanicInfo__") { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::EvaluationError_TYPE); + let ctx = mut_ptr_as_ref(ctx); + ctx.set_err_type(&RuntimeErrorType::EvaluationError); panic!("{}", msg.as_str()); } @@ -63,7 +65,7 @@ pub unsafe extern "C" fn kclvm_plugin_invoke( #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_plugin_invoke_json( - method: *const i8, + method: *const c_char, args: *const c_char, kwargs: *const c_char, ) -> *const c_char { @@ -74,7 +76,7 @@ pub extern "C" fn kclvm_plugin_invoke_json( let ptr = (&_plugin_handler_fn_ptr as *const u64) as *const () as *const extern "C" fn( - method: *const i8, + method: *const c_char, args: *const c_char, kwargs: *const c_char, ) -> *const c_char; diff --git a/kclvm/runtime/src/testing/mod.rs b/kclvm/runtime/src/testing/mod.rs deleted file mode 100644 index c4034afa8..000000000 --- a/kclvm/runtime/src/testing/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -pub mod testing; -pub use self::testing::*; diff --git a/kclvm/runtime/src/testing/testing.rs b/kclvm/runtime/src/testing/testing.rs deleted file mode 100644 index 3a16ad538..000000000 --- a/kclvm/runtime/src/testing/testing.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! KCL testing system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_testing_arguments( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) { - // Nothing to do -} - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_testing_setting_file( - _ctx: *mut kclvm_context_t, - _args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) { - // Nothing to do -} diff --git a/kclvm/runtime/src/types/api.rs b/kclvm/runtime/src/types/api.rs deleted file mode 100644 index c8e27f7cc..000000000 --- a/kclvm/runtime/src/types/api.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use crate::*; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_context_t = Context; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_kind_t = Kind; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_type_t = Type; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_value_t = Value; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_char_t = i8; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_size_t = i32; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_bool_t = i8; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_int_t = i64; - -#[allow(dead_code, non_camel_case_types)] -type kclvm_float_t = f64; - -// ---------------------------------------------------------------------------- -// delete -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_delete(p: *mut kclvm_type_t) { - free_mut_ptr(p); -} - -// ---------------------------------------------------------------------------- -// kind -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_kind(p: *const kclvm_type_t) -> kclvm_kind_t { - let p = ptr_as_ref(p); - - p.kind() -} - -// ---------------------------------------------------------------------------- -// type_str -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_str(p: *const kclvm_type_t) -> kclvm_kind_t { - let p = ptr_as_ref(p); - - p.kind() -} - -// ---------------------------------------------------------------------------- -// lit value -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_BoolLit_value(p: *const kclvm_type_t) -> kclvm_bool_t { - match ptr_as_ref(p) { - Type::bool_lit_type(ref v) => *v as kclvm_bool_t, - _ => 0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_IntLit_value(p: *const kclvm_type_t) -> i64 { - let p = ptr_as_ref(p); - match p { - Type::int_lit_type(ref v) => *v, - _ => 0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_FloatLit_value(p: *const kclvm_type_t) -> f64 { - let p = ptr_as_ref(p); - match p { - Type::float_lit_type(ref v) => *v, - _ => 0.0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_StrLit_value(p: *const kclvm_type_t) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - match p { - Type::str_lit_type(ref v) => v.as_ptr() as *const kclvm_char_t, - _ => std::ptr::null(), - } -} - -// ---------------------------------------------------------------------------- -// list/dict type -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_key_type(p: *const kclvm_type_t) -> *const kclvm_type_t { - let p = ptr_as_ref(p); - match p { - Type::dict_type(ref v) => { - return v.key_type.as_ref() as *const Type; - } - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_elem_type(p: *const kclvm_type_t) -> *const kclvm_type_t { - let p = ptr_as_ref(p); - match p { - Type::list_type(ref v) => { - return v.elem_type.as_ref() as *const Type; - } - Type::dict_type(ref v) => { - return v.elem_type.as_ref() as *const Type; - } - _ => std::ptr::null(), - } -} - -// ---------------------------------------------------------------------------- -// schema -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_name(p: *const kclvm_type_t) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(ref v) => v.name.as_ptr() as *const kclvm_char_t, - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_parent_name( - p: *const kclvm_type_t, -) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(ref v) => v.parent_name.as_ptr() as *const kclvm_char_t, - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_relaxed(p: *const kclvm_type_t) -> kclvm_bool_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(..) => false as kclvm_bool_t, - _ => 0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_field_num(p: *const kclvm_type_t) -> kclvm_size_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(ref v) => v.field_names.len() as kclvm_size_t, - _ => 0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_field_name( - p: *const kclvm_type_t, - i: kclvm_size_t, -) -> *const kclvm_char_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(ref v) => v.field_names[i as usize].as_ptr() as *const kclvm_char_t, - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_schema_field_type( - p: *const kclvm_type_t, - i: kclvm_size_t, -) -> *const kclvm_type_t { - let p = ptr_as_ref(p); - match p { - Type::schema_type(ref v) => &v.field_types[i as usize] as *const kclvm_type_t, - _ => std::ptr::null(), - } -} - -// ---------------------------------------------------------------------------- -// func (for plugin) -// ---------------------------------------------------------------------------- - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_arg_num(p: *const kclvm_type_t) -> kclvm_size_t { - let p = ptr_as_ref(p); - match p { - Type::func_type(ref v) => v.args_types.len() as kclvm_size_t, - _ => 0, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_arg_type( - p: *const kclvm_type_t, - i: kclvm_size_t, -) -> *const kclvm_type_t { - let p = ptr_as_ref(p); - match p { - Type::func_type(ref v) => &v.args_types[i as usize] as *const kclvm_type_t, - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_type_return_type(p: *const kclvm_type_t) -> *const kclvm_type_t { - let p = ptr_as_ref(p); - match p { - Type::func_type(ref v) => v.return_type.as_ref() as *const kclvm_type_t, - _ => std::ptr::null(), - } -} - -// ---------------------------------------------------------------------------- -// END -// ---------------------------------------------------------------------------- diff --git a/kclvm/runtime/src/types/typ_new.rs b/kclvm/runtime/src/types/constructor.rs similarity index 50% rename from kclvm/runtime/src/types/typ_new.rs rename to kclvm/runtime/src/types/constructor.rs index d679698b2..47b73921b 100644 --- a/kclvm/runtime/src/types/typ_new.rs +++ b/kclvm/runtime/src/types/constructor.rs @@ -1,88 +1,94 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; impl Type { + #[inline] pub fn any() -> Self { - Type::any_type + Type::Any } + #[inline] pub fn func() -> Self { - Type::func_type(Default::default()) + Type::Func(Default::default()) } + #[inline] pub fn bool() -> Self { - Type::bool_type + Type::Bool } + #[inline] pub fn bool_lit(v: bool) -> Self { - Type::bool_lit_type(v) + Type::BoolLit(v) } + #[inline] pub fn int() -> Self { - Type::int_type + Type::Int } + #[inline] pub fn int_lit(v: i64) -> Self { - Type::int_lit_type(v) + Type::IntLit(v) } + #[inline] pub fn float() -> Self { - Type::float_type + Type::Float } + #[inline] pub fn float_lit(v: f64) -> Self { - Type::float_lit_type(v) + Type::FloatLit(v) } + #[inline] pub fn str() -> Self { - Type::str_type + Type::Str } + #[inline] pub fn str_lit(s: &str) -> Self { - Type::str_lit_type(s.to_string()) + Type::StrLit(s.to_string()) } + #[inline] pub fn list(elem_type: &Self) -> Self { - Type::list_type(ListType { + Type::List(ListType { elem_type: Box::new(elem_type.clone()), }) } + #[inline] pub fn dict(key_type: &Self, elem_type: &Self) -> Self { - Type::dict_type(DictType { + Type::Dict(DictType { key_type: Box::new(key_type.clone()), elem_type: Box::new(elem_type.clone()), }) } + #[inline] pub fn union(elem_types: &[&Self]) -> Self { let mut ut: UnionType = Default::default(); for typ in elem_types { ut.elem_types.push((*typ).clone()); } - Type::union_type(ut) + Type::Union(ut) } + #[inline] pub fn schema( - name: &str, - parent_name: &str, - field_names: &[&str], - field_types: &[&Self], + name: String, + attrs: IndexMap, + has_index_signature: bool, + func: ValueRef, ) -> Self { - let mut st = SchemaType { - name: name.to_string(), - parent_name: parent_name.to_string(), - ..Default::default() - }; - - for name in field_names { - st.field_names.push((*name).to_string()); - } - for typ in field_types { - st.field_types.push((*typ).clone()); - } - - Type::schema_type(st) + Type::Schema(SchemaType { + name, + attrs, + has_index_signature, + func, + }) } } diff --git a/kclvm/runtime/src/types/kind.rs b/kclvm/runtime/src/types/kind.rs new file mode 100644 index 000000000..6526a624e --- /dev/null +++ b/kclvm/runtime/src/types/kind.rs @@ -0,0 +1,24 @@ +//! Copyright The KCL Authors. All rights reserved. + +use crate::*; + +impl Type { + pub fn kind(&self) -> Kind { + match self { + Type::Any => Kind::Any, + Type::Bool => Kind::Bool, + Type::BoolLit(..) => Kind::BoolLit, + Type::Int => Kind::Int, + Type::IntLit(..) => Kind::IntLit, + Type::Float => Kind::Float, + Type::FloatLit(..) => Kind::FloatLit, + Type::Str => Kind::Str, + Type::StrLit(..) => Kind::StrLit, + Type::List(..) => Kind::List, + Type::Dict(..) => Kind::Dict, + Type::Union(..) => Kind::Union, + Type::Schema(..) => Kind::Schema, + Type::Func(..) => Kind::Func, + } + } +} diff --git a/kclvm/runtime/src/types/mod.rs b/kclvm/runtime/src/types/mod.rs index 7f1db4c8b..851a5e286 100644 --- a/kclvm/runtime/src/types/mod.rs +++ b/kclvm/runtime/src/types/mod.rs @@ -1,13 +1,5 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod api; -pub use api::*; - -pub mod typ_kind; -pub use typ_kind::*; - -pub mod typ_new; -pub use typ_new::*; - -pub mod typ_type_str; -pub use typ_type_str::*; +pub mod constructor; +pub mod kind; +pub mod str; diff --git a/kclvm/runtime/src/types/str.rs b/kclvm/runtime/src/types/str.rs new file mode 100644 index 000000000..cbfd7f0b6 --- /dev/null +++ b/kclvm/runtime/src/types/str.rs @@ -0,0 +1,34 @@ +//! Copyright The KCL Authors. All rights reserved. + +use crate::*; + +impl Type { + pub fn type_str(&self) -> String { + match self { + Type::Any => KCL_TYPE_ANY.to_string(), + Type::Bool => BUILTIN_TYPE_BOOL.to_string(), + Type::BoolLit(ref v) => format!("{BUILTIN_TYPE_BOOL}({v})"), + Type::Int => BUILTIN_TYPE_INT.to_string(), + Type::IntLit(ref v) => format!("{BUILTIN_TYPE_INT}({v})"), + Type::Float => BUILTIN_TYPE_FLOAT.to_string(), + Type::FloatLit(ref v) => format!("{BUILTIN_TYPE_FLOAT}({v})"), + Type::Str => BUILTIN_TYPE_STR.to_string(), + Type::StrLit(ref v) => format!("{BUILTIN_TYPE_STR}({v})"), + Type::List(ref v) => format!("[{}]", v.elem_type.type_str()), + Type::Dict(ref v) => { + format!("{{{}:{}}}", v.key_type.type_str(), v.elem_type.type_str()) + } + Type::Union(ref v) => match v.elem_types.len() { + 0 => String::new(), + 1 => v.elem_types[0].type_str(), + _ => { + let mut types = Vec::new(); + let _ = v.elem_types.iter().map(|e| types.push(e.type_str())); + types.join(" | ") + } + }, + Type::Schema(ref v) => v.name.to_string(), + Type::Func(ref _v) => "func".to_string(), + } + } +} diff --git a/kclvm/runtime/src/types/typ_kind.rs b/kclvm/runtime/src/types/typ_kind.rs deleted file mode 100644 index 3c11d8fa2..000000000 --- a/kclvm/runtime/src/types/typ_kind.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -use crate::*; - -impl Type { - pub fn kind(&self) -> Kind { - match self { - Type::any_type => Kind::Any, - Type::bool_type => Kind::Bool, - Type::bool_lit_type(..) => Kind::BoolLit, - Type::int_type => Kind::Int, - Type::int_lit_type(..) => Kind::IntLit, - Type::float_type => Kind::Float, - Type::float_lit_type(..) => Kind::FloatLit, - Type::str_type => Kind::Str, - Type::str_lit_type(..) => Kind::StrLit, - Type::list_type(..) => Kind::List, - Type::dict_type(..) => Kind::Dict, - Type::union_type(..) => Kind::Union, - Type::schema_type(..) => Kind::Schema, - Type::func_type(..) => Kind::Func, - } - } -} diff --git a/kclvm/runtime/src/types/typ_type_str.rs b/kclvm/runtime/src/types/typ_type_str.rs deleted file mode 100644 index 81d668d90..000000000 --- a/kclvm/runtime/src/types/typ_type_str.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -use crate::*; - -impl Type { - pub fn type_str(&self) -> String { - match self { - Type::any_type => KCL_TYPE_ANY.to_string(), - Type::bool_type => BUILTIN_TYPE_BOOL.to_string(), - Type::bool_lit_type(ref v) => format!("{BUILTIN_TYPE_BOOL}({v})"), - Type::int_type => BUILTIN_TYPE_INT.to_string(), - Type::int_lit_type(ref v) => format!("{BUILTIN_TYPE_INT}({v})"), - Type::float_type => BUILTIN_TYPE_FLOAT.to_string(), - Type::float_lit_type(ref v) => format!("{BUILTIN_TYPE_FLOAT}({v})"), - Type::str_type => BUILTIN_TYPE_STR.to_string(), - Type::str_lit_type(ref v) => format!("{BUILTIN_TYPE_STR}({v})"), - Type::list_type(ref v) => format!("[{}]", v.elem_type.type_str()), - Type::dict_type(ref v) => { - format!("{{{}:{}}}", v.key_type.type_str(), v.elem_type.type_str()) - } - Type::union_type(ref v) => match v.elem_types.len() { - 0 => String::new(), - 1 => v.elem_types[0].type_str(), - _ => { - let mut types = Vec::new(); - let _ = v.elem_types.iter().map(|e| types.push(e.type_str())); - types.join("|") - } - }, - Type::schema_type(ref v) => v.name.to_string(), - Type::func_type(ref _v) => "func".to_string(), - } - } -} diff --git a/kclvm/runtime/src/unification/mod.rs b/kclvm/runtime/src/unification/mod.rs index ff06983fc..55d8d4141 100644 --- a/kclvm/runtime/src/unification/mod.rs +++ b/kclvm/runtime/src/unification/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod subsume; pub use subsume::*; diff --git a/kclvm/runtime/src/unification/subsume.rs b/kclvm/runtime/src/unification/subsume.rs index 94b7c150b..25140be6c 100644 --- a/kclvm/runtime/src/unification/subsume.rs +++ b/kclvm/runtime/src/unification/subsume.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/units/mod.rs b/kclvm/runtime/src/units/mod.rs index c0a05d119..2dc4091bc 100644 --- a/kclvm/runtime/src/units/mod.rs +++ b/kclvm/runtime/src/units/mod.rs @@ -1,4 +1,422 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. -pub mod units; -pub use self::units::*; +use crate::*; + +#[derive(Debug)] +#[allow(non_camel_case_types, dead_code)] +enum to_unit_suffix { + n, + u, + m, + k, + K, + M, + G, + T, + P, + Ki, + Mi, + Gi, + Ti, + Pi, +} + +use phf::{phf_map, Map}; + +pub const IEC_SUFFIX: &str = "i"; +pub const EXPONENTS: Map<&str, i8> = phf_map! { + "n" => -3, + "u" => -2, + "m" => -1, + "k" => 1, + "K" => 1, + "M" => 2, + "G" => 3, + "T" => 4, + "P" => 5, +}; +pub const INVALID_UNITS: [&str; 4] = ["ni", "ui", "mi", "ki"]; + +// to_n(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_n( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + let num = args.arg_0().unwrap().convert_to_float(ctx).as_float(); + let s = to_unit(num, to_unit_suffix::n); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} + +// to_u(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_u( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + let num = args.arg_0().unwrap().convert_to_float(ctx).as_float(); + let s = to_unit(num, to_unit_suffix::u); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} + +// to_m(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_m( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + let num = args.arg_0().unwrap().convert_to_float(ctx).as_float(); + let s = to_unit(num, to_unit_suffix::m); + return ValueRef::str(s.as_ref()).into_raw(ctx); +} + +// to_K(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_K( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::K); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_K() missing 1 required positional argument: 'num'"); +} + +// to_M(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_M( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + let _kwargs = ptr_as_ref(kwargs); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::M); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_M() missing 1 required positional argument: 'num'"); +} + +// to_G(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_G( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::G); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_G() missing 1 required positional argument: 'num'"); +} + +// to_T(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_T( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::T); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_T() missing 1 required positional argument: 'num'"); +} + +// to_P(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_P( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::P); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_P() missing 1 required positional argument: 'num'"); +} + +// to_Ki(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_Ki( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::Ki); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_Ki() missing 1 required positional argument: 'num'"); +} + +// to_Mi(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_Mi( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::Mi); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_Mi() missing 1 required positional argument: 'num'"); +} + +// to_Gi(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_Gi( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::Gi); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_Gi() missing 1 required positional argument: 'num'"); +} + +// to_Ti(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_Ti( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::Ti); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_Ti() missing 1 required positional argument: 'num'"); +} + +// to_Pi(num: int) -> str + +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_units_to_Pi( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + let args = ptr_as_ref(args); + + if let Some(num) = args.arg_i_num(0, None) { + let s = to_unit(num, to_unit_suffix::Pi); + return ValueRef::str(s.as_ref()).into_raw(ctx); + } + panic!("to_Pi() missing 1 required positional argument: 'num'"); +} + +fn to_unit(num: f64, suffix: to_unit_suffix) -> String { + match suffix { + to_unit_suffix::n => format!("{}{:?}", (num / 1e-09) as i64, suffix), + to_unit_suffix::u => format!("{}{:?}", (num / 1e-06) as i64, suffix), + to_unit_suffix::m => format!("{}{:?}", (num / 0.001) as i64, suffix), + to_unit_suffix::k => format!("{}{:?}", (num / 1_000.0) as i64, suffix), + to_unit_suffix::K => format!("{}{:?}", (num / 1_000.0) as i64, suffix), + to_unit_suffix::M => format!("{}{:?}", (num / 1_000_000.0) as i64, suffix), + to_unit_suffix::G => format!("{}{:?}", (num / 1_000_000_000.0) as i64, suffix), + to_unit_suffix::T => format!("{}{:?}", (num / 1_000_000_000_000.0) as i64, suffix), + to_unit_suffix::P => format!("{}{:?}", (num / 1_000_000_000_000_000.0) as i64, suffix), + to_unit_suffix::Ki => format!("{}{:?}", (num / 1024.0) as i64, suffix), + to_unit_suffix::Mi => format!("{}{:?}", (num / (1024.0 * 1024.0)) as i64, suffix), + to_unit_suffix::Gi => format!("{}{:?}", (num / (1024.0 * 1024.0 * 1024.0)) as i64, suffix), + to_unit_suffix::Ti => format!( + "{}{:?}", + (num / (1024.0 * 1024.0 * 1024.0 * 1024.0)) as i64, + suffix + ), + to_unit_suffix::Pi => format!( + "{}{:?}", + (num / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) as i64, + suffix + ), + } +} + +/// Parse and return number based on input quantity. +/// +/// Supported suffixes: +/// SI: n | u | m | k | K | M | G | T | P +/// IEC: Ki | Mi | Gi | Ti | Pi +/// +/// Input: +/// quantity: &str. +/// +/// Returns: +/// result: i64 +pub fn to_quantity(quantity: &str) -> i64 { + let quantity_len = quantity.len(); + let mut number = quantity; + let mut suffix: Option<&str> = None; + if quantity_len >= 2 && &quantity[quantity_len - 1..] == IEC_SUFFIX { + if EXPONENTS.contains_key(&quantity[quantity_len - 2..quantity_len - 1]) { + number = &quantity[..quantity_len - 2]; + suffix = Some(&quantity[quantity_len - 2..]); + } + } else if quantity_len >= 1 && EXPONENTS.contains_key(&quantity[quantity_len - 1..]) { + number = &quantity[..quantity_len - 1]; + suffix = Some(&quantity[quantity_len - 1..]); + } + if number.is_empty() { + panic!("number can't be empty") + } + let number: i64 = number.parse().unwrap(); + if suffix.is_none() { + return number; + } + let suffix = suffix.unwrap(); + validate_unit(&suffix[0..1]); + let base: i64 = if suffix.ends_with(IEC_SUFFIX) { + 1024 + } else { + 1000 + }; + let exponent = EXPONENTS.get(&suffix[0..1]).unwrap(); + number * (base.pow(*exponent as u32)) +} + +/// Calculate number based on value and binary suffix. +/// +/// Supported suffixes: +/// SI: n | u | m | k | K | M | G | T | P +/// IEC: Ki | Mi | Gi | Ti | Pi +/// +/// Input: +/// value: int. +/// suffix: str. +/// +/// Returns: +/// int +/// +/// Raises: +/// ValueError on invalid or unknown suffix +pub fn cal_num(value: i64, unit: &str) -> f64 { + validate_unit(unit); + let mut base: f64 = 1000.0; + let mut unit = unit; + if unit.len() > 1 && &unit[1..2] == IEC_SUFFIX { + base = 1024.0; + unit = &unit[0..1]; + } + let exponent = EXPONENTS + .get(unit) + .unwrap_or_else(|| panic!("invalid unit {unit}")); + value as f64 * base.powf(*exponent as f64) +} + +#[inline] +pub fn real_uint_value(raw: i64, unit: &str) -> i128 { + (raw as i128) * (u64_unit_value(unit) as i128) +} + +/// Validate the unit is valid +pub fn validate_unit(unit: &str) { + if unit.is_empty() || unit.len() > 2 { + panic!("Invalid suffix {unit}"); + } + if INVALID_UNITS.contains(&unit) { + panic!("Invalid suffix {unit}"); + } + if !EXPONENTS.contains_key(&unit[..1]) { + panic!("Invalid suffix {unit}"); + } +} + +pub fn f64_unit_value(unit: &str) -> f64 { + match unit { + "n" => 1e-09, + "u" => 1e-06, + "m" => 0.001, + _ => 1_f64, + } +} + +pub fn u64_unit_value(unit: &str) -> u64 { + match unit { + "k" => 1_000, + "K" => 1_000, + "M" => 1_000_000, + "G" => 1_000_000_000, + "T" => 1_000_000_000_000, + "P" => 1_000_000_000_000_000, + "Ki" => 1024, + "Mi" => 1048576, + "Gi" => 1073741824, + "Ti" => 1099511627776, + "Pi" => 1125899906842624, + _ => 1_u64, + } +} diff --git a/kclvm/runtime/src/units/units.rs b/kclvm/runtime/src/units/units.rs deleted file mode 100644 index e9a791268..000000000 --- a/kclvm/runtime/src/units/units.rs +++ /dev/null @@ -1,440 +0,0 @@ -//! KCL units system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -#[derive(Debug)] -#[allow(dead_code, non_camel_case_types)] -enum to_unit_suffix { - n, - u, - m, - k, - K, - M, - G, - T, - P, - Ki, - Mi, - Gi, - Ti, - Pi, -} - -use phf::{phf_map, Map}; - -pub const IEC_SUFFIX: &str = "i"; -pub const EXPONENTS: Map<&str, i8> = phf_map! { - "n" => -3, - "u" => -2, - "m" => -1, - "k" => 1, - "K" => 1, - "M" => 2, - "G" => 3, - "T" => 4, - "P" => 5, -}; -pub const INVALID_UNITS: [&str; 4] = ["ni", "ui", "mi", "ki"]; - -// to_n(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_n( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - let num = args.arg_0().unwrap().convert_to_float().as_float(); - let s = to_unit(num, to_unit_suffix::n); - return ValueRef::str(s.as_ref()).into_raw(); -} - -// to_u(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_u( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - let num = args.arg_0().unwrap().convert_to_float().as_float(); - let s = to_unit(num, to_unit_suffix::u); - return ValueRef::str(s.as_ref()).into_raw(); -} - -// to_m(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_m( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - let num = args.arg_0().unwrap().convert_to_float().as_float(); - let s = to_unit(num, to_unit_suffix::m); - return ValueRef::str(s.as_ref()).into_raw(); -} - -// to_K(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_K( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::K); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_K() missing 1 required positional argument: 'num'"); -} - -// to_M(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_M( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::M); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_M() missing 1 required positional argument: 'num'"); -} - -// to_G(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_G( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::G); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_G() missing 1 required positional argument: 'num'"); -} - -// to_T(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_T( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::T); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_T() missing 1 required positional argument: 'num'"); -} - -// to_P(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_P( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::P); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_P() missing 1 required positional argument: 'num'"); -} - -// to_Ki(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_Ki( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::Ki); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_Ki() missing 1 required positional argument: 'num'"); -} - -// to_Mi(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_Mi( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::Mi); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_Mi() missing 1 required positional argument: 'num'"); -} - -// to_Gi(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_Gi( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::Gi); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_Gi() missing 1 required positional argument: 'num'"); -} - -// to_Ti(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_Ti( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::Ti); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_Ti() missing 1 required positional argument: 'num'"); -} - -// to_Pi(num: int) -> str - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_units_to_Pi( - ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let _ctx = mut_ptr_as_ref(ctx); - let args = ptr_as_ref(args); - let _kwargs = ptr_as_ref(kwargs); - - if let Some(num) = args.arg_i_num(0, None) { - let s = to_unit(num, to_unit_suffix::Pi); - return ValueRef::str(s.as_ref()).into_raw(); - } - panic!("to_Pi() missing 1 required positional argument: 'num'"); -} - -fn to_unit(num: f64, suffix: to_unit_suffix) -> String { - match suffix { - to_unit_suffix::n => format!("{}{:?}", (num / 1e-09) as i64, suffix), - to_unit_suffix::u => format!("{}{:?}", (num / 1e-06) as i64, suffix), - to_unit_suffix::m => format!("{}{:?}", (num / 0.001) as i64, suffix), - to_unit_suffix::k => format!("{}{:?}", (num / 1_000.0) as i64, suffix), - to_unit_suffix::K => format!("{}{:?}", (num / 1_000.0) as i64, suffix), - to_unit_suffix::M => format!("{}{:?}", (num / 1_000_000.0) as i64, suffix), - to_unit_suffix::G => format!("{}{:?}", (num / 1_000_000_000.0) as i64, suffix), - to_unit_suffix::T => format!("{}{:?}", (num / 1_000_000_000_000.0) as i64, suffix), - to_unit_suffix::P => format!("{}{:?}", (num / 1_000_000_000_000_000.0) as i64, suffix), - to_unit_suffix::Ki => format!("{}{:?}", (num / 1024.0) as i64, suffix), - to_unit_suffix::Mi => format!("{}{:?}", (num / (1024.0 * 1024.0)) as i64, suffix), - to_unit_suffix::Gi => format!("{}{:?}", (num / (1024.0 * 1024.0 * 1024.0)) as i64, suffix), - to_unit_suffix::Ti => format!( - "{}{:?}", - (num / (1024.0 * 1024.0 * 1024.0 * 1024.0)) as i64, - suffix - ), - to_unit_suffix::Pi => format!( - "{}{:?}", - (num / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) as i64, - suffix - ), - } -} - -/// Parse and return number based on input quantity. -/// -/// Supported suffixes: -/// SI: n | u | m | k | K | M | G | T | P -/// IEC: Ki | Mi | Gi | Ti | Pi -/// -/// Input: -/// quantity: &str. -/// -/// Returns: -/// result: i64 -pub fn to_quantity(quantity: &str) -> i64 { - let quantity_len = quantity.len(); - let mut number = quantity; - let mut suffix: Option<&str> = None; - if quantity_len >= 2 && &quantity[quantity_len - 1..] == IEC_SUFFIX { - if EXPONENTS.contains_key(&quantity[quantity_len - 2..quantity_len - 1]) { - number = &quantity[..quantity_len - 2]; - suffix = Some(&quantity[quantity_len - 2..]); - } - } else if quantity_len >= 1 && EXPONENTS.contains_key(&quantity[quantity_len - 1..]) { - number = &quantity[..quantity_len - 1]; - suffix = Some(&quantity[quantity_len - 1..]); - } - if number.is_empty() { - panic!("number can't be empty") - } - let number: i64 = number.parse().unwrap(); - if suffix.is_none() { - return number; - } - let suffix = suffix.unwrap(); - validate_unit(&suffix[0..1]); - let base: i64 = if suffix.ends_with(IEC_SUFFIX) { - 1024 - } else { - 1000 - }; - let exponent = EXPONENTS.get(&suffix[0..1]).unwrap(); - number * (base.pow(*exponent as u32)) -} - -/// Calculate number based on value and binary suffix. -/// -/// Supported suffixes: -/// SI: n | u | m | k | K | M | G | T | P -/// IEC: Ki | Mi | Gi | Ti | Pi -/// -/// Input: -/// value: int. -/// suffix: str. -/// -/// Returns: -/// int -/// -/// Raises: -/// ValueError on invalid or unknown suffix -pub fn cal_num(value: i64, unit: &str) -> f64 { - validate_unit(unit); - let mut base: f64 = 1000.0; - let mut unit = unit; - if unit.len() > 1 && &unit[1..2] == IEC_SUFFIX { - base = 1024.0; - unit = &unit[0..1]; - } - let exponent = EXPONENTS - .get(unit) - .unwrap_or_else(|| panic!("invalid unit {unit}")); - value as f64 * base.powf(*exponent as f64) -} - -#[inline] -pub fn real_uint_value(raw: i64, unit: &str) -> i128 { - (raw as i128) * (u64_unit_value(unit) as i128) -} - -/// Validate the unit is valid -pub fn validate_unit(unit: &str) { - if unit.is_empty() || unit.len() > 2 { - panic!("Invalid suffix {unit}"); - } - if INVALID_UNITS.contains(&unit) { - panic!("Invalid suffix {unit}"); - } - if !EXPONENTS.contains_key(&unit[..1]) { - panic!("Invalid suffix {unit}"); - } -} - -pub fn f64_unit_value(unit: &str) -> f64 { - match unit { - "n" => 1e-09, - "u" => 1e-06, - "m" => 0.001, - _ => 1_f64, - } -} - -pub fn u64_unit_value(unit: &str) -> u64 { - match unit { - "k" => 1_000, - "K" => 1_000, - "M" => 1_000_000, - "G" => 1_000_000_000, - "T" => 1_000_000_000_000, - "P" => 1_000_000_000_000_000, - "Ki" => 1024, - "Mi" => 1048576, - "Gi" => 1073741824, - "Ti" => 1099511627776, - "Pi" => 1125899906842624, - _ => 1_u64, - } -} diff --git a/kclvm/runtime/src/value/api.rs b/kclvm/runtime/src/value/api.rs index 60ab95eaf..a1cf4f210 100644 --- a/kclvm/runtime/src/value/api.rs +++ b/kclvm/runtime/src/value/api.rs @@ -1,16 +1,18 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #![allow(clippy::missing_safety_doc)] -use std::mem::transmute_copy; +use std::{mem::transmute_copy, os::raw::c_char}; use crate::*; -#[allow(non_camel_case_types)] -pub type kclvm_buffer_t = Buffer; +use self::{eval::LazyEvalScope, walker::walk_value_mut}; #[allow(non_camel_case_types)] pub type kclvm_context_t = Context; +#[allow(non_camel_case_types)] +pub type kclvm_eval_scope_t = LazyEvalScope; + #[allow(non_camel_case_types)] pub type kclvm_decorator_value_t = DecoratorValue; @@ -27,7 +29,7 @@ pub type kclvm_value_ref_t = ValueRef; pub type kclvm_iterator_t = ValueIterator; #[allow(non_camel_case_types)] -pub type kclvm_char_t = i8; +pub type kclvm_char_t = c_char; #[allow(non_camel_case_types)] pub type kclvm_size_t = i32; @@ -89,42 +91,50 @@ static mut kclvm_value_Float_0_obj: usize = 0; #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_Undefined() -> *mut kclvm_value_ref_t { - new_mut_ptr(ValueRef::undefined()) +pub extern "C" fn kclvm_value_Undefined(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::undefined()) } #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_None() -> *mut kclvm_value_ref_t { - new_mut_ptr(ValueRef::none()) +pub extern "C" fn kclvm_value_None(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::none()) } // bool/int/float/str #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_True() -> *mut kclvm_value_ref_t { - kclvm_value_Bool(1) +pub extern "C" fn kclvm_value_True(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + kclvm_value_Bool(ctx, 1) } #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_False() -> *mut kclvm_value_ref_t { - kclvm_value_Bool(0) +pub extern "C" fn kclvm_value_False(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + kclvm_value_Bool(ctx, 0) } #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_Bool(v: kclvm_bool_t) -> *mut kclvm_value_ref_t { +pub extern "C" fn kclvm_value_Bool( + ctx: *mut kclvm_context_t, + v: kclvm_bool_t, +) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); unsafe { if v != 0 { if kclvm_value_Bool_true_obj == 0 { - kclvm_value_Bool_true_obj = new_mut_ptr(ValueRef::bool(true)) as usize; + kclvm_value_Bool_true_obj = new_mut_ptr(ctx, ValueRef::bool(true)) as usize; } kclvm_value_Bool_true_obj as *mut kclvm_value_ref_t } else { if kclvm_value_Bool_false_obj == 0 { - kclvm_value_Bool_false_obj = new_mut_ptr(ValueRef::bool(false)) as usize; + kclvm_value_Bool_false_obj = new_mut_ptr(ctx, ValueRef::bool(false)) as usize; } kclvm_value_Bool_false_obj as *mut kclvm_value_ref_t } @@ -133,65 +143,81 @@ pub extern "C" fn kclvm_value_Bool(v: kclvm_bool_t) -> *mut kclvm_value_ref_t { #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_Int(v: kclvm_int_t) -> *mut kclvm_value_ref_t { +pub extern "C" fn kclvm_value_Int( + ctx: *mut kclvm_context_t, + v: kclvm_int_t, +) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); if v == 0 { unsafe { if kclvm_value_Int_0_obj == 0 { - kclvm_value_Int_0_obj = new_mut_ptr(ValueRef::int(0)) as usize; + kclvm_value_Int_0_obj = new_mut_ptr(ctx, ValueRef::int(0)) as usize; } return kclvm_value_Int_0_obj as *mut kclvm_value_ref_t; } } - new_mut_ptr(ValueRef::int(v)) + new_mut_ptr(ctx, ValueRef::int(v)) } #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_Float(v: kclvm_float_t) -> *mut kclvm_value_ref_t { +pub extern "C" fn kclvm_value_Float( + ctx: *mut kclvm_context_t, + v: kclvm_float_t, +) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); if v == 0.0 { unsafe { if kclvm_value_Float_0_obj == 0 { - kclvm_value_Float_0_obj = new_mut_ptr(ValueRef::float(0.0)) as usize; + kclvm_value_Float_0_obj = new_mut_ptr(ctx, ValueRef::float(0.0)) as usize; } return kclvm_value_Float_0_obj as *mut kclvm_value_ref_t; } } - new_mut_ptr(ValueRef::float(v)) + new_mut_ptr(ctx, ValueRef::float(v)) } #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_value_Unit( + ctx: *mut kclvm_context_t, v: kclvm_float_t, raw: kclvm_int_t, unit: *const kclvm_char_t, ) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let unit = c2str(unit); - new_mut_ptr(ValueRef::unit(v, raw, unit)) + new_mut_ptr(ctx, ValueRef::unit(v, raw, unit)) } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Str(v: *const kclvm_char_t) -> *mut kclvm_value_ref_t { +pub unsafe extern "C" fn kclvm_value_Str( + ctx: *mut kclvm_context_t, + v: *const kclvm_char_t, +) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); unsafe { - if v.is_null() || *v == '\0' as i8 { - return new_mut_ptr(ValueRef::str("")); + if v.is_null() || *v == '\0' as c_char { + return new_mut_ptr(ctx, ValueRef::str("")); } } - return new_mut_ptr(ValueRef::str(c2str(v))); + return new_mut_ptr(ctx, ValueRef::str(c2str(v))); } // list/dict/schema #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_List() -> *mut kclvm_value_ref_t { - new_mut_ptr(ValueRef::list(None)) +pub extern "C" fn kclvm_value_List(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::list(None)) } #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_value_List6( + ctx: *mut kclvm_context_t, v1: *const kclvm_value_ref_t, v2: *const kclvm_value_ref_t, v3: *const kclvm_value_ref_t, @@ -199,16 +225,18 @@ pub extern "C" fn kclvm_value_List6( v5: *const kclvm_value_ref_t, v6: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let values: Vec<&ValueRef> = vec![v1, v2, v3, v4, v5, v6] .into_iter() .map(ptr_as_ref) .collect(); - new_mut_ptr(ValueRef::list(Some(values.as_slice()))) + new_mut_ptr(ctx, ValueRef::list(Some(values.as_slice()))) } #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_value_List10( + ctx: *mut kclvm_context_t, v1: *const kclvm_value_ref_t, v2: *const kclvm_value_ref_t, v3: *const kclvm_value_ref_t, @@ -220,46 +248,32 @@ pub extern "C" fn kclvm_value_List10( v9: *const kclvm_value_ref_t, v10: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let values: Vec<&ValueRef> = vec![v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] .into_iter() .map(ptr_as_ref) .collect(); - new_mut_ptr(ValueRef::list(Some(values.as_slice()))) + new_mut_ptr(ctx, ValueRef::list(Some(values.as_slice()))) } #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_value_ListN( - n: kclvm_int_t, - elem_values: *const *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let mut list = ListValue::default(); - - unsafe { - for xi in std::slice::from_raw_parts(elem_values, n as usize).iter() { - let v: &ValueRef = ptr_as_ref(*xi); - list.values.push(v.clone()); - } - - ValueRef::from(Value::list_value(Box::new(list))).into_raw() - } +pub extern "C" fn kclvm_value_Dict(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::dict(None)) } #[no_mangle] #[runtime_fn] -pub extern "C" fn kclvm_value_Dict() -> *mut kclvm_value_ref_t { - new_mut_ptr(ValueRef::dict(None)) -} - -#[no_mangle] -#[runtime_fn] -pub extern "C" fn kclvm_value_Schema() -> *mut kclvm_value_ref_t { - new_mut_ptr(ValueRef::schema()) +pub extern "C" fn kclvm_value_Schema(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::schema()) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_schema_with_config( + ctx: *mut kclvm_context_t, schema_dict: *const kclvm_value_ref_t, config: *const kclvm_value_ref_t, config_meta: *const kclvm_value_ref_t, @@ -269,18 +283,15 @@ pub unsafe extern "C" fn kclvm_value_schema_with_config( record_instance: *const kclvm_value_ref_t, instance_pkgpath: *const kclvm_value_ref_t, optional_mapping: *const kclvm_value_ref_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let schema_dict = ptr_as_ref(schema_dict); // Config dict let config = ptr_as_ref(config); let config_meta = ptr_as_ref(config_meta); - let config_keys: Vec = config - .as_dict_ref() - .values - .keys() - .into_iter() - .cloned() - .collect(); + let config_keys: Vec = config.as_dict_ref().values.keys().cloned().collect(); // Schema meta let name = c2str(name); let pkgpath = c2str(pkgpath); @@ -290,76 +301,88 @@ pub unsafe extern "C" fn kclvm_value_schema_with_config( let instance_pkgpath = ptr_as_ref(instance_pkgpath); let instance_pkgpath = instance_pkgpath.as_str(); let optional_mapping = ptr_as_ref(optional_mapping); - let schema = - schema_dict.dict_to_schema(name, pkgpath, &config_keys, config_meta, optional_mapping); - // Runtime context - let ctx = Context::current_context(); + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + let schema = schema_dict.dict_to_schema( + name, + pkgpath, + &config_keys, + config_meta, + optional_mapping, + Some(args.clone()), + Some(kwargs.clone()), + ); if record_instance.is_truthy() && (instance_pkgpath.is_empty() || instance_pkgpath == MAIN_PKG_PATH) { // Record schema instance in the context - let mut instance_map = ctx.instances.borrow_mut(); - if !instance_map.contains_key(&runtime_type) { - instance_map.insert(runtime_type.clone(), vec![]); + if !ctx.instances.contains_key(&runtime_type) { + ctx.instances.insert(runtime_type.clone(), vec![]); } - instance_map + ctx.instances .get_mut(&runtime_type) .unwrap() .push(schema_dict.clone()); } // Dict to schema if is_sub_schema.is_truthy() { - schema.into_raw() + schema.into_raw(ctx) } else { - schema_dict.clone().into_raw() + schema_dict.clone().into_raw(ctx) } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_Function( + ctx: *mut kclvm_context_t, fn_ptr: *const u64, closure: *const kclvm_value_ref_t, name: *const kclvm_char_t, is_external: kclvm_bool_t, ) -> *mut kclvm_value_ref_t { + let ctx = mut_ptr_as_ref(ctx); let closure = ptr_as_ref(closure); let name = c2str(name); - new_mut_ptr(ValueRef::func( - fn_ptr as u64, - 0, - closure.clone(), - name, - "", - is_external != 0, - )) + new_mut_ptr( + ctx, + ValueRef::func( + fn_ptr as u64, + 0, + closure.clone(), + name, + "", + is_external != 0, + ), + ) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_Function_using_ptr( + ctx: *mut kclvm_context_t, fn_ptr: *const u64, name: *const kclvm_char_t, ) -> *mut kclvm_value_ref_t { let name = c2str(name); - new_mut_ptr(ValueRef::func( - fn_ptr as u64, - 0, - ValueRef::none(), - name, - "", - false, - )) + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr( + ctx, + ValueRef::func(fn_ptr as u64, 0, ValueRef::none(), name, "", false), + ) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_schema_function( + ctx: *mut kclvm_context_t, fn_ptr: *const u64, check_fn_ptr: *const u64, + attr_map: *const kclvm_value_ref_t, tpe: *const kclvm_char_t, ) -> *mut kclvm_value_ref_t { // Schema function closures + let ctx = mut_ptr_as_ref(ctx); let is_sub_schema = ValueRef::bool(false); let config_meta = ValueRef::dict(None); let config = ValueRef::dict(None); @@ -394,10 +417,20 @@ pub unsafe extern "C" fn kclvm_value_schema_function( runtime_type, false, ); - let ctx = Context::current_context_mut(); - let mut all_schemas = ctx.all_schemas.borrow_mut(); - all_schemas.insert(runtime_type.to_string(), schema_func.clone()); - new_mut_ptr(schema_func) + let attr_map = ptr_as_ref(attr_map); + let attr_dict = attr_map.as_dict_ref(); + let schema_ty = SchemaType { + name: runtime_type.to_string(), + attrs: attr_dict + .values + .iter() + .map(|(k, _)| (k.to_string(), Type::any())) // TODO: store schema attr type in the runtime. + .collect(), + has_index_signature: attr_dict.attr_map.contains_key(CAL_MAP_INDEX_SIGNATURE), + func: schema_func.clone(), + }; + ctx.all_schemas.insert(runtime_type.to_string(), schema_ty); + new_mut_ptr(ctx, schema_func) } // ---------------------------------------------------------------------------- @@ -406,167 +439,135 @@ pub unsafe extern "C" fn kclvm_value_schema_function( #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_value_from_json(s: *const kclvm_char_t) -> *mut kclvm_value_ref_t { +pub unsafe extern "C" fn kclvm_value_from_json( + ctx: *mut kclvm_context_t, + s: *const kclvm_char_t, +) -> *mut kclvm_value_ref_t { + let ctx_ref = mut_ptr_as_ref(ctx); if s.is_null() { - return kclvm_value_Undefined(); + return kclvm_value_Undefined(ctx); } - match ValueRef::from_json(c2str(s)) { - Ok(x) => x.into_raw(), - _ => kclvm_value_Undefined(), + match ValueRef::from_json(ctx_ref, c2str(s)) { + Ok(x) => x.into_raw(ctx_ref), + _ => kclvm_value_Undefined(ctx), } } -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_to_json(p: *const kclvm_value_ref_t) -> *mut kclvm_buffer_t { - let p = ptr_as_ref(p); - let x = p.to_json(); - let buf = Buffer::new_with_buf(&x); - buf.into_raw() -} - #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_to_json_value( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if p.is_null() { - return kclvm_value_Str(std::ptr::null()); + return kclvm_value_Str(ctx, std::ptr::null()); } let p = ptr_as_ref(p); let s = p.to_json_string(); - - return new_mut_ptr(ValueRef::str(s.as_ref())); + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::str(s.as_ref())) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_to_json_value_with_null( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if p.is_null() { - return kclvm_value_Str(std::ptr::null()); + return kclvm_value_Str(ctx, std::ptr::null()); } let p = ptr_as_ref(p); let s = p.to_json_string_with_null(); - - return new_mut_ptr(ValueRef::str(s.as_ref())); + let ctx = mut_ptr_as_ref(ctx); + new_mut_ptr(ctx, ValueRef::str(s.as_ref())) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_plan_to_json( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let p = ptr_as_ref(p); - let s = p.plan_to_json_string(); - - return new_mut_ptr(ValueRef::str(s.as_ref())); + let ctx: &mut Context = mut_ptr_as_ref(ctx); + let value = match ctx.buffer.custom_manifests_output.clone() { + Some(output) => ValueRef::from_yaml_stream(ctx, &output).unwrap(), + None => p.clone(), + }; + let (json_string, yaml_string) = value.plan(ctx); + ctx.json_result = json_string.clone(); + ctx.yaml_result = yaml_string.clone(); + new_mut_ptr(ctx, ValueRef::str(&json_string)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_plan_to_yaml( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let p = ptr_as_ref(p); - let s = p.plan_to_yaml_string(); - - return new_mut_ptr(ValueRef::str(s.as_ref())); + let ctx = mut_ptr_as_ref(ctx); + let value = match ctx.buffer.custom_manifests_output.clone() { + Some(output) => ValueRef::from_yaml_stream(ctx, &output).unwrap(), + None => p.clone(), + }; + let (json_string, yaml_string) = value.plan(ctx); + ctx.json_result = json_string.clone(); + ctx.yaml_result = yaml_string.clone(); + new_mut_ptr(ctx, ValueRef::str(&yaml_string)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_to_yaml_value( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if p.is_null() { - return kclvm_value_Str(std::ptr::null()); + return kclvm_value_Str(ctx, std::ptr::null()); } - + let ctx = mut_ptr_as_ref(ctx); let p = ptr_as_ref(p); let s = p.to_yaml_string(); - return new_mut_ptr(ValueRef::str(s.as_ref())); + new_mut_ptr(ctx, ValueRef::str(s.as_ref())) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_to_str_value( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if p.is_null() { - return kclvm_value_Str(std::ptr::null()); + return kclvm_value_Str(ctx, std::ptr::null()); } + let ctx = mut_ptr_as_ref(ctx); let p = ptr_as_ref(p); let s = p.to_string(); - return new_mut_ptr(ValueRef::str(s.as_ref())); + new_mut_ptr(ctx, ValueRef::str(s.as_ref())) } // ---------------------------------------------------------------------------- // values: value pointer // ---------------------------------------------------------------------------- -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Bool_ptr(p: *const kclvm_value_ref_t) -> *const kclvm_bool_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::bool_value(ref v) => v as *const bool as *const kclvm_bool_t, // sizeof(bool) == sizeof(i8) - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Int_ptr(p: *const kclvm_value_ref_t) -> *const kclvm_int_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::int_value(ref v) => v as *const kclvm_int_t, - _ => std::ptr::null(), - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Float_ptr( - p: *const kclvm_value_ref_t, -) -> *const kclvm_float_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::float_value(ref v) => v as *const kclvm_float_t, - _ => std::ptr::null(), - } -} - #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_Str_ptr(p: *const kclvm_value_ref_t) -> *const kclvm_char_t { let p = ptr_as_ref(p); match &*p.rc.borrow() { - Value::str_value(ref v) => v.as_ptr() as *const i8, + Value::str_value(ref v) => v.as_ptr() as *const c_char, _ => std::ptr::null(), } } -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Str_len(p: *const kclvm_value_ref_t) -> kclvm_size_t { - let p = ptr_as_ref(p); - p.str_len() as kclvm_size_t -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_Str_resize(p: *mut kclvm_value_ref_t, n: kclvm_size_t) { - let p = mut_ptr_as_ref(p); - p.str_resize(n as usize) -} - #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_function_ptr(p: *const kclvm_value_ref_t) -> *const u64 { @@ -587,35 +588,6 @@ pub unsafe extern "C" fn kclvm_value_check_function_ptr(p: *const kclvm_value_re } } -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_function_is_external( - p: *const kclvm_value_ref_t, -) -> kclvm_bool_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::func_value(ref v) => v.is_external as kclvm_bool_t, - _ => false as kclvm_bool_t, - } -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_function_external_invoke( - p: *const kclvm_value_ref_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::func_value(ref v) => { - let name = format!("{}\0", v.name); - kclvm_plugin_invoke(name.as_ptr() as *const i8, args, kwargs) - } - _ => kclvm_value_None(), - } -} - #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_function_invoke( @@ -654,7 +626,7 @@ pub unsafe extern "C" fn kclvm_value_function_invoke( let record_instance_index = closure.len() - 2; let instance_pkgpath_index = closure.len() - 1; args_ref.list_append_unpack(closure); - let args = args_ref.clone().into_raw(); + let args = args_ref.clone().into_raw(ctx_ref); call_fn(ctx, args, kwargs); let cal_map = closure.list_get(cal_map_index).unwrap(); // is sub schema @@ -673,20 +645,20 @@ pub unsafe extern "C" fn kclvm_value_function_invoke( ); closure_new.list_set(config_meta_index as usize, &config_meta); args_new.list_append_unpack(&closure_new); - call_fn(ctx, args_new.into_raw(), kwargs) + call_fn(ctx, args_new.into_raw(ctx_ref), kwargs) // Normal kcl function, call directly } else if func.is_external { let name = format!("{}\0", func.name); - kclvm_plugin_invoke(name.as_ptr() as *const i8, args, kwargs) + kclvm_plugin_invoke(ctx, name.as_ptr() as *const c_char, args, kwargs) } else { args_ref.list_append_unpack_first(closure); - let args = args_ref.clone().into_raw(); + let args = args_ref.clone().into_raw(ctx_ref); call_fn(ctx, args, kwargs) }; let is_in_schema = ptr_as_ref(is_in_schema); if is_schema && !is_in_schema.is_truthy() { let schema_value = ptr_as_ref(value); - schema_value.schema_check_attr_optional(true); + schema_value.schema_check_attr_optional(ctx_ref, true); } if ctx_ref.cfg.debug_mode { ctx_ref.backtrace.pop(); @@ -695,44 +667,24 @@ pub unsafe extern "C" fn kclvm_value_function_invoke( return value; }; } - kclvm_value_None() -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_function_get_closure( - p: *const kclvm_value_ref_t, -) -> *mut kclvm_value_ref_t { - let p = ptr_as_ref(p); - match &*p.rc.borrow() { - Value::func_value(ref v) => v.closure.deep_copy().into_raw(), - Value::none | Value::undefined => kclvm_value_None(), - _ => panic!("invalid value of function self value function"), - } + kclvm_value_None(ctx) } // ---------------------------------------------------------------------------- // values: method // ---------------------------------------------------------------------------- -// kind - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_value_kind(p: *const kclvm_value_ref_t) -> kclvm_kind_t { - let p = ptr_as_ref(p); - p.kind() -} - // clone #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_deep_copy( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let p = ptr_as_ref(p); - p.deep_copy().into_raw() + let ctx = mut_ptr_as_ref(ctx); + p.deep_copy().into_raw(ctx) } // delete @@ -861,20 +813,23 @@ pub unsafe extern "C" fn kclvm_list_clear(p: *mut kclvm_value_ref_t) { #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_list_count( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, item: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let item = ptr_as_ref(item); let count = p.list_count(item); + let ctx = mut_ptr_as_ref(ctx); let count_value = ValueRef::int(count as i64); - count_value.into_raw() + count_value.into_raw(ctx) } /// Return first index of the list value. Panic if the value is not present. #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_list_find( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, item: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -882,7 +837,8 @@ pub unsafe extern "C" fn kclvm_list_find( let item = ptr_as_ref(item); let index = p.list_find(item); let index_value = ValueRef::int(index as i64); - index_value.into_raw() + let ctx = mut_ptr_as_ref(ctx); + index_value.into_raw(ctx) } /// Insert object before index of the list value. @@ -902,12 +858,14 @@ pub unsafe extern "C" fn kclvm_list_insert( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_list_get( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, i: kclvm_size_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); + let ctx = mut_ptr_as_ref(ctx); match p.list_get(i as isize) { - Some(x) => x.into_raw(), + Some(x) => x.into_raw(ctx), _ => panic!("list index out of range"), } } @@ -915,13 +873,15 @@ pub unsafe extern "C" fn kclvm_list_get( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_list_get_option( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, i: kclvm_size_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); + match p.list_get_option(i as isize) { - Some(x) => x.into_raw(), - _ => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + _ => kclvm_value_Undefined(ctx), } } @@ -939,23 +899,28 @@ pub unsafe extern "C" fn kclvm_list_set( #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_list_pop(p: *mut kclvm_value_ref_t) -> *const kclvm_value_ref_t { +pub unsafe extern "C" fn kclvm_list_pop( + ctx: *mut kclvm_context_t, + p: *mut kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { let p = mut_ptr_as_ref(p); + match p.list_pop() { - Some(x) => x.into_raw(), - _ => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + _ => kclvm_value_Undefined(ctx), } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_list_pop_first( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let p = mut_ptr_as_ref(p); match p.list_pop_first() { - Some(x) => x.into_raw(), - _ => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + _ => kclvm_value_Undefined(ctx), } } @@ -1037,9 +1002,26 @@ pub unsafe extern "C" fn kclvm_dict_clear(p: *mut kclvm_value_ref_t) { p.dict_clear(); } +#[no_mangle] +#[runtime_fn] +pub unsafe extern "C" fn kclvm_dict_is_override_attr( + p: *const kclvm_value_ref_t, + key: *const kclvm_char_t, +) -> kclvm_bool_t { + let p = ptr_as_ref(p); + let key = c2str(key); + let is_override_op = matches!( + p.dict_get_attr_operator(key), + Some(ConfigEntryOperationKind::Override) + ); + let without_index = matches!(p.dict_get_insert_index(key), Some(-1) | None); + (is_override_op && without_index) as kclvm_bool_t +} + #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_get( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, key: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1047,8 +1029,8 @@ pub unsafe extern "C" fn kclvm_dict_get( let key = ptr_as_ref(key); match p.dict_get(key) { - Some(x) => x.into_raw(), - None => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + None => kclvm_value_Undefined(ctx), } } @@ -1069,48 +1051,52 @@ pub unsafe extern "C" fn kclvm_dict_has_value( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_get_value( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, key: *const kclvm_char_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let key = c2str(key); match p.dict_get_value(key) { - Some(x) => x.into_raw(), - None => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + None => kclvm_value_Undefined(ctx), } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_get_entry( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, key: *const kclvm_char_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let key = c2str(key); match p.dict_get_entry(key) { - Some(x) => x.into_raw(), - None => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + None => kclvm_value_Undefined(ctx), } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_get_value_by_path( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, path: *const kclvm_char_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let path = c2str(path); match p.get_by_path(path) { - Some(x) => x.into_raw(), - None => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + None => kclvm_value_Undefined(ctx), } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_set_value( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, key: *const kclvm_char_t, val: *const kclvm_value_ref_t, @@ -1120,43 +1106,53 @@ pub unsafe extern "C" fn kclvm_dict_set_value( let val = ptr_as_ref(val); if p.is_config() { p.dict_update_key_value(key, val.clone()); - } - if p.is_schema() { - let schema: ValueRef; - { - let schema_value = p.as_schema(); - let mut config_keys = schema_value.config_keys.clone(); - config_keys.push(key.to_string()); - schema = resolve_schema(p, &config_keys); + if p.is_schema() { + let schema: ValueRef; + { + let schema_value = p.as_schema(); + let mut config_keys = schema_value.config_keys.clone(); + config_keys.push(key.to_string()); + schema = resolve_schema(mut_ptr_as_ref(ctx), p, &config_keys); + } + p.schema_update_with_schema(&schema); } - p.schema_update_with_schema(&schema); + } else { + panic!( + "failed to update the dict. An iterable of key-value pairs was expected, but got {}. Check if the syntax for updating the dictionary with the attribute '{}' is correct", + p.type_str(), + key + ); } - /*panic*/ } #[no_mangle] #[runtime_fn] /// Return all dict keys. -pub unsafe extern "C" fn kclvm_dict_keys(p: *const kclvm_value_ref_t) -> *const kclvm_value_ref_t { +pub unsafe extern "C" fn kclvm_dict_keys( + ctx: *mut kclvm_context_t, + p: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let r = p.dict_keys(); - r.into_raw() + r.into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] /// Return all dict values. pub unsafe extern "C" fn kclvm_dict_values( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(p); let r = p.dict_values(); - r.into_raw() + r.into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_insert( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, key: *const kclvm_char_t, v: *const kclvm_value_ref_t, @@ -1166,6 +1162,7 @@ pub unsafe extern "C" fn kclvm_dict_insert( let p = mut_ptr_as_ref(p); let v = ptr_as_ref(v); p.dict_insert( + mut_ptr_as_ref(ctx), c2str(key), v, ConfigEntryOperationKind::from_i32(op), @@ -1176,6 +1173,7 @@ pub unsafe extern "C" fn kclvm_dict_insert( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_merge( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, key: *const kclvm_char_t, v: *const kclvm_value_ref_t, @@ -1185,6 +1183,7 @@ pub unsafe extern "C" fn kclvm_dict_merge( let p = mut_ptr_as_ref(p); let v = ptr_as_ref(v); let key = c2str(key); + let ctx = mut_ptr_as_ref(ctx); let attr_map = { match &*p.rc.borrow() { Value::dict_value(dict) => dict.attr_map.clone(), @@ -1193,21 +1192,29 @@ pub unsafe extern "C" fn kclvm_dict_merge( } }; if attr_map.contains_key(key) { - let v = type_pack_and_check(v, vec![attr_map.get(key).unwrap()]); + let v = type_pack_and_check(ctx, v, vec![attr_map.get(key).unwrap()]); p.dict_merge( + ctx, key, &v, ConfigEntryOperationKind::from_i32(op), insert_index, ); } else { - p.dict_merge(key, v, ConfigEntryOperationKind::from_i32(op), insert_index); + p.dict_merge( + ctx, + key, + v, + ConfigEntryOperationKind::from_i32(op), + insert_index, + ); } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_insert_value( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, key: *const kclvm_value_ref_t, v: *const kclvm_value_ref_t, @@ -1219,6 +1226,7 @@ pub unsafe extern "C" fn kclvm_dict_insert_value( let key = ptr_as_ref(key); let key = key.attr_str(); p.dict_insert( + mut_ptr_as_ref(ctx), key.as_str(), v, ConfigEntryOperationKind::from_i32(op), @@ -1243,6 +1251,7 @@ pub unsafe extern "C" fn kclvm_dict_update_key_value( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_safe_insert( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, key: *const kclvm_char_t, v: *const kclvm_value_ref_t, @@ -1252,18 +1261,20 @@ pub unsafe extern "C" fn kclvm_dict_safe_insert( if p.is_null() || key.is_null() || v.is_null() { return; } - kclvm_dict_insert(p, key, v, op, insert_index); + kclvm_dict_insert(ctx, p, key, v, op, insert_index); } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_dict_insert_unpack( + ctx: *mut kclvm_context_t, p: *mut kclvm_value_ref_t, v: *const kclvm_value_ref_t, ) { let p = mut_ptr_as_ref(p); + let ctx = mut_ptr_as_ref(ctx); let v = ptr_as_ref(v); - p.dict_insert_unpack(v); + p.dict_insert_unpack(ctx, v); } #[no_mangle] @@ -1355,79 +1366,85 @@ pub unsafe extern "C" fn kclvm_value_len(p: *const kclvm_value_ref_t) -> kclvm_s #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_equal_to( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if a == b { - return kclvm_value_Bool(1); + return kclvm_value_Bool(ctx, 1); } let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.cmp_equal(b)).into_raw() + ValueRef::bool(a.cmp_equal(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_not_equal_to( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if a == b { - return kclvm_value_Bool(0); + return kclvm_value_Bool(ctx, 0); } let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(!a.cmp_equal(b)).into_raw() + ValueRef::bool(!a.cmp_equal(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_less_than( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if a == b { - return kclvm_value_Bool(0); + return kclvm_value_Bool(ctx, 0); } let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.cmp_less_than(b)).into_raw() + ValueRef::bool(a.cmp_less_than(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_less_than_or_equal( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.cmp_less_than_or_equal(b)).into_raw() + ValueRef::bool(a.cmp_less_than_or_equal(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_greater_than( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { if a == b { - return kclvm_value_Bool(0); + return kclvm_value_Bool(ctx, 0); } let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.cmp_greater_than(b)).into_raw() + ValueRef::bool(a.cmp_greater_than(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_cmp_greater_than_or_equal( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.cmp_greater_than_or_equal(b)).into_raw() + ValueRef::bool(a.cmp_greater_than_or_equal(b)).into_raw(mut_ptr_as_ref(ctx)) } // is/in @@ -1435,64 +1452,70 @@ pub unsafe extern "C" fn kclvm_value_cmp_greater_than_or_equal( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_is( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); if a == b { - return kclvm_value_Bool(1); + return kclvm_value_Bool(ctx, 1); } - kclvm_value_Bool(0) + kclvm_value_Bool(ctx, 0) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_is_not( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); if a == b { - return kclvm_value_Bool(0); + return kclvm_value_Bool(ctx, 0); } - kclvm_value_Bool(1) + kclvm_value_Bool(ctx, 1) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_in( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.r#in(b)).into_raw() + ValueRef::bool(a.r#in(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_not_in( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.not_in(b)).into_raw() + ValueRef::bool(a.not_in(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_as( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); let ty_str = b.as_str(); - let value = type_pack_and_check(a, vec![ty_str.as_str()]); - value.into_raw() + let ctx = mut_ptr_as_ref(ctx); + let value = type_pack_and_check(ctx, a, vec![ty_str.as_str()]); + value.into_raw(ctx) } // unary-xxx @@ -1500,37 +1523,41 @@ pub unsafe extern "C" fn kclvm_value_as( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_unary_plus( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); - a.unary_plus().into_raw() + a.unary_plus().into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_unary_minus( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); - a.unary_minus().into_raw() + a.unary_minus().into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_unary_not( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); - a.unary_not().into_raw() + a.unary_not().into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_unary_l_not( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); - a.unary_l_not().into_raw() + a.unary_l_not().into_raw(mut_ptr_as_ref(ctx)) } // op-xxx @@ -1538,133 +1565,152 @@ pub unsafe extern "C" fn kclvm_value_unary_l_not( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_add( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_add(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_add(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_sub( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_sub(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_sub(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_mul( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_mul(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_mul(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_div( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_div(b).into_raw() + a.bin_div(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_mod( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_mod(b).into_raw() + a.bin_mod(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_pow( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_pow(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_pow(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_floor_div( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_floor_div(b).into_raw() + a.bin_floor_div(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_bit_lshift( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_bit_lshift(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_bit_lshift(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_bit_rshift( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_bit_rshift(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_bit_rshift(ctx, b).into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_bit_and( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_bit_and(b).into_raw() + a.bin_bit_and(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_bit_xor( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_bit_xor(b).into_raw() + a.bin_bit_xor(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_bit_or( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_bit_or(b).into_raw() + let ctx = mut_ptr_as_ref(ctx); + a.bin_bit_or(ctx, b).into_raw(ctx) } // op-aug-xxx @@ -1672,39 +1718,46 @@ pub unsafe extern "C" fn kclvm_value_op_bit_or( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_add( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - return a.bin_aug_add(b) as *const kclvm_value_ref_t; + let ctx = mut_ptr_as_ref(ctx); + return a.bin_aug_add(ctx, b) as *const kclvm_value_ref_t; } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_sub( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - return a.bin_aug_sub(b) as *const kclvm_value_ref_t; + let ctx = mut_ptr_as_ref(ctx); + return a.bin_aug_sub(ctx, b) as *const kclvm_value_ref_t; } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_mul( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - return a.bin_aug_mul(b) as *const kclvm_value_ref_t; + let ctx = mut_ptr_as_ref(ctx); + return a.bin_aug_mul(ctx, b); } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_div( + _ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1716,6 +1769,7 @@ pub unsafe extern "C" fn kclvm_value_op_aug_div( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_mod( + _ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1727,17 +1781,20 @@ pub unsafe extern "C" fn kclvm_value_op_aug_mod( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_pow( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - return a.bin_aug_pow(b) as *const kclvm_value_ref_t; + let ctx = mut_ptr_as_ref(ctx); + return a.bin_aug_pow(ctx, b) as *const kclvm_value_ref_t; } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_floor_div( + _ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1749,28 +1806,33 @@ pub unsafe extern "C" fn kclvm_value_op_aug_floor_div( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_bit_lshift( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_aug_bit_lshift(b) as *const kclvm_value_ref_t + let ctx = mut_ptr_as_ref(ctx); + a.bin_aug_bit_lshift(ctx, b) as *const kclvm_value_ref_t } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_bit_rshift( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_aug_bit_rshift(b) as *const kclvm_value_ref_t + let ctx = mut_ptr_as_ref(ctx); + a.bin_aug_bit_rshift(ctx, b) as *const kclvm_value_ref_t } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_bit_and( + _ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1782,6 +1844,7 @@ pub unsafe extern "C" fn kclvm_value_op_aug_bit_and( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_bit_xor( + _ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -1793,22 +1856,26 @@ pub unsafe extern "C" fn kclvm_value_op_aug_bit_xor( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_op_aug_bit_or( + ctx: *mut kclvm_context_t, a: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_aug_bit_or(b) as *const kclvm_value_ref_t + let ctx = mut_ptr_as_ref(ctx); + a.bin_aug_bit_or(ctx, b) as *const kclvm_value_ref_t } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_union( + ctx: *mut kclvm_context_t, schema: *mut kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let a = mut_ptr_as_ref(schema); let b = ptr_as_ref(b); + let ctx = mut_ptr_as_ref(ctx); let attr_map = match &*a.rc.borrow() { Value::dict_value(dict) => dict.attr_map.clone(), Value::schema_value(schema) => schema.config.attr_map.clone(), @@ -1823,16 +1890,16 @@ pub unsafe extern "C" fn kclvm_value_union( let dict = b.as_dict_ref(); for k in dict.values.keys() { let entry = b.dict_get_entry(k).unwrap(); - a.union_entry(&entry, true, &opts); + a.union_entry(ctx, &entry, true, &opts); // Has type annotation if let Some(ty) = attr_map.get(k) { let value = a.dict_get_value(k).unwrap(); - a.dict_update_key_value(k, type_pack_and_check(&value, vec![ty])); + a.dict_update_key_value(k, type_pack_and_check(ctx, &value, vec![ty])); } } - a.clone().into_raw() + a.clone().into_raw(ctx) } else { - a.union_entry(b, true, &opts).into_raw() + a.union_entry(ctx, b, true, &opts).into_raw(ctx) } } @@ -1841,71 +1908,71 @@ pub unsafe extern "C" fn kclvm_value_union( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_logic_and( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.logic_and(b)).into_raw() + ValueRef::bool(a.logic_and(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_logic_or( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - ValueRef::bool(a.logic_or(b)).into_raw() + ValueRef::bool(a.logic_or(b)).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_subscr( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_subscr(b).into_raw() + a.bin_subscr(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_subscr_option( + ctx: *mut kclvm_context_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let a = ptr_as_ref(a); let b = ptr_as_ref(b); - a.bin_subscr_option(b).into_raw() + a.bin_subscr_option(b).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_load_attr( + ctx: *mut kclvm_context_t, obj: *const kclvm_value_ref_t, key: *const kclvm_char_t, ) -> *const kclvm_value_ref_t { let p = ptr_as_ref(obj); let key = c2str(key); + let ctx_ref = mut_ptr_as_ref(ctx); // load_attr including str/dict/schema. if p.is_dict() { match p.dict_get_value(key) { - Some(x) => { - return x.into_raw(); - } - None => { - return kclvm_value_Undefined(); - } + Some(x) => x.into_raw(ctx_ref), + None => kclvm_value_Undefined(ctx), } } else if p.is_schema() { let dict = p.schema_to_dict(); match dict.dict_get_value(key) { - Some(x) => { - return x.into_raw(); - } + Some(x) => x.into_raw(ctx_ref), None => panic!("schema '{}' attribute '{}' not found", p.type_str(), key), } } else if p.is_str() { @@ -1942,14 +2009,10 @@ pub unsafe extern "C" fn kclvm_value_load_attr( _ => panic!("str object attr '{key}' not found"), }; let closure = ValueRef::list(Some(&[p])); - return new_mut_ptr(ValueRef::func( - function as usize as u64, - 0, - closure, - "", - "", - false, - )); + new_mut_ptr( + ctx_ref, + ValueRef::func(function as usize as u64, 0, closure, "", "", false), + ) } // schema instance else if p.is_func() { @@ -1958,33 +2021,31 @@ pub unsafe extern "C" fn kclvm_value_load_attr( _ => panic!("schema object attr '{key}' not found"), }; let closure = ValueRef::list(Some(&[p])); - return new_mut_ptr(ValueRef::func( - function as usize as u64, - 0, - closure, - "", - "", - false, - )); + new_mut_ptr( + ctx_ref, + ValueRef::func(function as usize as u64, 0, closure, "", "", false), + ) + } else { + panic!( + "invalid value '{}' to load attribute '{}'", + p.type_str(), + key + ); } - panic!( - "invalid value '{}' to load attribute '{}'", - p.type_str(), - key - ); } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_load_attr_option( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, key: *const kclvm_char_t, ) -> *const kclvm_value_ref_t { let p_ref = ptr_as_ref(p); if p_ref.is_truthy() { - kclvm_value_load_attr(p, key) + kclvm_value_load_attr(ctx, p, key) } else { - kclvm_value_None() + kclvm_value_None(ctx) } } @@ -2008,6 +2069,7 @@ pub unsafe extern "C" fn kclvm_value_remove_item( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_slice( + ctx: *mut kclvm_context_t, x: *const kclvm_value_ref_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, @@ -2017,12 +2079,13 @@ pub unsafe extern "C" fn kclvm_value_slice( let a = ptr_as_ref(a); let b = ptr_as_ref(b); let step = ptr_as_ref(step); - x.list_slice(a, b, step).into_raw() + x.list_slice(a, b, step).into_raw(mut_ptr_as_ref(ctx)) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_slice_option( + ctx: *mut kclvm_context_t, x: *const kclvm_value_ref_t, a: *const kclvm_value_ref_t, b: *const kclvm_value_ref_t, @@ -2030,9 +2093,9 @@ pub unsafe extern "C" fn kclvm_value_slice_option( ) -> *const kclvm_value_ref_t { let value = ptr_as_ref(x); if value.is_truthy() { - kclvm_value_slice(x, a, b, step) + kclvm_value_slice(ctx, x, a, b, step) } else { - kclvm_value_None() + kclvm_value_None(ctx) } } @@ -2043,6 +2106,7 @@ pub unsafe extern "C" fn kclvm_value_slice_option( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_schema_backtrack_cache( + ctx: *mut kclvm_context_t, schema: *const kclvm_value_ref_t, cache: *mut kclvm_value_ref_t, cal_map: *const kclvm_value_ref_t, @@ -2067,7 +2131,8 @@ pub unsafe extern "C" fn kclvm_schema_backtrack_cache( cal_map_meta_line_list.list_get(-1), ) { let runtime_type = ptr_as_ref(runtime_type); - let line = Context::current_context().panic_info.kcl_line as i64; + let ctx = mut_ptr_as_ref(ctx); + let line = ctx.panic_info.kcl_line as i64; let cal_map_meta_line = cal_map_meta_line.as_int(); if runtime_type == &cal_map_runtime_type && line >= cal_map_meta_line { if let Some(value) = schema.dict_get_value(name) { @@ -2086,7 +2151,7 @@ pub unsafe extern "C" fn kclvm_schema_instances( args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { - let ctx = ptr_as_ref(ctx); + let ctx_ref = mut_ptr_as_ref(ctx); let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); if let Some(val) = args.pop_arg_first() { @@ -2098,10 +2163,9 @@ pub unsafe extern "C" fn kclvm_schema_instances( true }; let runtime_type = &function.runtime_type; - let instance_map = ctx.instances.borrow_mut(); - if instance_map.contains_key(runtime_type) { + if ctx_ref.instances.contains_key(runtime_type) { let mut list = ValueRef::list(None); - for v in instance_map.get(runtime_type).unwrap() { + for v in ctx_ref.instances.get(runtime_type).unwrap() { if v.is_schema() { let schema = v.as_schema(); if main_pkg { @@ -2112,14 +2176,9 @@ pub unsafe extern "C" fn kclvm_schema_instances( list.list_append(v) } } else if v.is_dict() { - let runtime_type_attr_path = - format!("{SCHEMA_SETTINGS_ATTR_NAME}.{SETTINGS_SCHEMA_TYPE_KEY}"); - let runtime_type = - if let Some(runtime_type) = v.get_by_path(&runtime_type_attr_path) { - runtime_type.as_str() - } else { - runtime_type.to_string() - }; + let runtime_type = v + .get_potential_schema_type() + .unwrap_or(runtime_type.to_string()); let names: Vec<&str> = runtime_type.rsplit('.').collect(); let name = names[0]; let pkgpath = names[1]; @@ -2129,22 +2188,25 @@ pub unsafe extern "C" fn kclvm_schema_instances( &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); list.list_append(&v); } } - list.into_raw() + list.into_raw(ctx_ref) } else { - kclvm_value_List() + kclvm_value_List(ctx) } } else { - kclvm_value_None() + kclvm_value_None(ctx) } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_schema_value_check( + ctx: *mut kclvm_context_t, schema_value: *mut kclvm_value_ref_t, schema_config: *const kclvm_value_ref_t, _config_meta: *const kclvm_value_ref_t, @@ -2163,7 +2225,7 @@ pub unsafe extern "C" fn kclvm_schema_value_check( let index_key_name = c2str(key_name); let has_index_signature = !key_type.is_empty(); - let ctx = Context::current_context_mut(); + let ctx = mut_ptr_as_ref(ctx); if ctx.cfg.disable_schema_check { return; } @@ -2175,11 +2237,7 @@ pub unsafe extern "C" fn kclvm_schema_value_check( // related to the index signature key name. let should_update = if let Some(index_key_value) = schema_value.dict_get_value(index_key_name) { - if index_key_value.is_str() && key == &index_key_value.as_str() { - true - } else { - false - } + index_key_value.is_str() && key == &index_key_value.as_str() } else { true }; @@ -2194,11 +2252,11 @@ pub unsafe extern "C" fn kclvm_schema_value_check( &ConfigEntryOperationKind::Override, &-1, ); - schema_value.dict_insert(key.as_str(), &value, op.clone(), -1); + schema_value.dict_insert(ctx, key.as_str(), value, op.clone(), -1); let value = schema_value.dict_get_value(key).unwrap(); schema_value.dict_update_key_value( key.as_str(), - type_pack_and_check(&value, vec![value_type]), + type_pack_and_check(ctx, &value, vec![value_type]), ); } } else if !has_index_signature && no_such_attr { @@ -2243,7 +2301,7 @@ pub unsafe extern "C" fn kclvm_schema_do_check_with_index_sign_attr( args.list_append(&cal_map); args.list_append(&backtrack_level_map); args.list_append(&backtrack_cache); - let args = args.clone().into_raw(); + let args = args.clone().into_raw(mut_ptr_as_ref(ctx)); check_fn(ctx, args, kwargs); } } @@ -2253,12 +2311,14 @@ pub unsafe extern "C" fn kclvm_schema_do_check_with_index_sign_attr( #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_schema_optional_check(p: *const kclvm_value_ref_t) { +pub unsafe extern "C" fn kclvm_schema_optional_check( + ctx: *mut kclvm_context_t, + p: *const kclvm_value_ref_t, +) { let p = ptr_as_ref(p); - - let ctx = Context::current_context(); + let ctx = mut_ptr_as_ref(ctx); if !ctx.cfg.disable_schema_check { - p.schema_check_attr_optional(true); + p.schema_check_attr_optional(ctx, true); } } @@ -2266,18 +2326,23 @@ pub unsafe extern "C" fn kclvm_schema_optional_check(p: *const kclvm_value_ref_t #[runtime_fn] pub unsafe extern "C" fn kclvm_schema_default_settings( schema_value: *mut kclvm_value_ref_t, - config_value: *const kclvm_value_ref_t, + _config_value: *const kclvm_value_ref_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, runtime_type: *const kclvm_char_t, ) { let schema_value = mut_ptr_as_ref(schema_value); - let config_value = ptr_as_ref(config_value); + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); let runtime_type = c2str(runtime_type); - schema_value.schema_default_settings(config_value, runtime_type); + schema_value.set_potential_schema_type(runtime_type); + schema_value.set_schema_args(args, kwargs); } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_schema_assert( + ctx: *mut kclvm_context_t, value: *const kclvm_value_ref_t, msg: *const kclvm_value_ref_t, config_meta: *const kclvm_value_ref_t, @@ -2286,8 +2351,8 @@ pub unsafe extern "C" fn kclvm_schema_assert( let msg = ptr_as_ref(msg); let config_meta = ptr_as_ref(config_meta); if !value.is_truthy() { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::SchemaCheckFailure_TYPE); + let ctx = mut_ptr_as_ref(ctx); + ctx.set_err_type(&RuntimeErrorType::SchemaCheckFailure); if let Some(config_meta_file) = config_meta.get_by_key(CONFIG_META_FILENAME) { let config_meta_line = config_meta.get_by_key(CONFIG_META_LINE).unwrap(); let config_meta_column = config_meta.get_by_key(CONFIG_META_COLUMN).unwrap(); @@ -2299,7 +2364,15 @@ pub unsafe extern "C" fn kclvm_schema_assert( ); } - ctx.set_kcl_location_info(Some("Check failed on the condition"), None, None, None); + let arg_msg = format!( + "Check failed on the condition{}", + if msg.is_empty() { + "".to_string() + } else { + format!(": {msg}") + } + ); + ctx.set_kcl_location_info(Some(arg_msg.as_str()), None, None, None); panic!("{}", msg.as_str()); } @@ -2331,28 +2404,28 @@ pub unsafe extern "C" fn kclvm_schema_value_new( let value = unsafe { let org_args = ptr_as_ref(args).deep_copy(); let schema_fn: SchemaTypeFunc = transmute_copy(&schema_fn_ptr); - let cal_map = kclvm_value_Dict(); - let instance_pkgpath = kclvm_value_Str(pkgpath); + let cal_map = kclvm_value_Dict(ctx); + let instance_pkgpath = kclvm_value_Str(ctx, pkgpath); // Schema function closures let values = [ // is_sub_schema - kclvm_value_Bool(0), + kclvm_value_Bool(ctx, 0), // Config meta config_meta, // Config value config, // Schema value - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // optional_mapping - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // cal order map cal_map, // backtrack level map - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // backtrack cache - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // record instance - kclvm_value_Bool(0), + kclvm_value_Bool(ctx, 0), // instance pkgpath instance_pkgpath, ]; @@ -2361,26 +2434,26 @@ pub unsafe extern "C" fn kclvm_schema_value_new( } schema_fn(ctx, args, kwargs); // schema args - let args = org_args.into_raw(); + let args = org_args.into_raw(ctx_ref); let values = [ // is_sub_schema - kclvm_value_Bool(1), + kclvm_value_Bool(ctx, 1), // Config meta config_meta, // Config value config, // Schema value - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // optional_mapping - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // cal order map cal_map, // backtrack level map - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // backtrack cache - kclvm_value_Dict(), + kclvm_value_Dict(ctx), // record instance - kclvm_value_Bool(1), + kclvm_value_Bool(ctx, 1), // instance pkgpath instance_pkgpath, ]; @@ -2396,34 +2469,44 @@ pub unsafe extern "C" fn kclvm_schema_value_new( value } else { let config = ptr_as_ref(config); - let result = - schema_value_or_func - .deep_copy() - .union_entry(config, true, &UnionOptions::default()); - result.into_raw() + let result = schema_value_or_func.deep_copy().union_entry( + mut_ptr_as_ref(ctx), + config, + true, + &UnionOptions::default(), + ); + result.into_raw(mut_ptr_as_ref(ctx)) } } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_convert_collection_value( + ctx: *mut kclvm_context_t, value: *const kclvm_value_ref_t, tpe: *const kclvm_char_t, is_in_schema: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let value = ptr_as_ref(value); + let ctx = mut_ptr_as_ref(ctx); let tpe = c2str(tpe); - let value = type_pack_and_check(value, vec![tpe]); + let value = type_pack_and_check(ctx, value, vec![tpe]); let is_in_schema = ptr_as_ref(is_in_schema); - if value.is_schema() && !is_in_schema.is_truthy() { - value.schema_check_attr_optional(true); + // Schema required attribute validating. + if !is_in_schema.is_truthy() { + walk_value_mut(&value, &mut |value: &ValueRef| { + if value.is_schema() { + value.schema_check_attr_optional(ctx, true); + } + }) } - value.into_raw() + value.into_raw(ctx) } #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_schema_get_value( + ctx: *mut kclvm_context_t, p: *const kclvm_value_ref_t, key: *const kclvm_char_t, config: *const kclvm_value_ref_t, @@ -2452,12 +2535,12 @@ pub unsafe extern "C" fn kclvm_schema_get_value( // Deal in-place modify and return it self immediately if key == target_attr && !is_backtracking { match schema.dict_get_value(key) { - Some(x) => return x.into_raw(), - None => return kclvm_value_Undefined(), + Some(x) => return x.into_raw(mut_ptr_as_ref(ctx)), + None => return kclvm_value_Undefined(ctx), } } if let Some(v) = backtrack_cache.dict_get_value(key) { - return v.into_raw(); + return v.into_raw(mut_ptr_as_ref(ctx)); } if let Some(attr_code) = cal_map.dict_get_value(key) { let now_level = level + 1; @@ -2470,14 +2553,14 @@ pub unsafe extern "C" fn kclvm_schema_get_value( Some(x) => x, None => ValueRef::undefined(), }; - return value.into_raw(); + return value.into_raw(mut_ptr_as_ref(ctx)); } let fn_ptr = &attr_code.values[index]; let fn_ptr = fn_ptr.as_int(); // When we calculate other schema attribute values, we retain // the row and column number information of the current schema attribute. - let ctx = Context::current_context_mut(); - let panic_info = ctx.panic_info.clone(); + let ctx_ref = mut_ptr_as_ref(ctx); + let panic_info = ctx_ref.panic_info.clone(); unsafe { let attr_fn: SchemaTypeFunc = transmute_copy(&fn_ptr); // args_0: config_meta, args_1: config, args_2: schema, args_3: cal_map @@ -2495,13 +2578,12 @@ pub unsafe extern "C" fn kclvm_schema_get_value( args.list_append(cal_map); args.list_append(backtrack_level_map); args.list_append(backtrack_cache); - let args = args.into_raw(); - let kwargs = kwargs.clone().into_raw(); - let ctx = kclvm_context_current(); + let args = args.into_raw(ctx_ref); + let kwargs = kwargs.clone().into_raw(ctx_ref); attr_fn(ctx, args, kwargs); }; // Restore the panic info of current schema attribute. - ctx.panic_info = panic_info; + ctx_ref.panic_info = panic_info; backtrack_level_map.dict_update_key_value(key, ValueRef::int(level)); let value = match schema.dict_get_value(key) { Some(x) => x, @@ -2510,8 +2592,8 @@ pub unsafe extern "C" fn kclvm_schema_get_value( backtrack_cache.dict_update_key_value(key, value); } match schema.dict_get_value(key) { - Some(x) => x.into_raw(), - None => kclvm_value_Undefined(), + Some(x) => x.into_raw(mut_ptr_as_ref(ctx)), + None => kclvm_value_Undefined(ctx), } } @@ -2535,6 +2617,7 @@ pub unsafe extern "C" fn kclvm_config_attr_map( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_value_Decorator( + ctx: *mut kclvm_context_t, name: *const kclvm_char_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, @@ -2552,6 +2635,7 @@ pub unsafe extern "C" fn kclvm_value_Decorator( let is_schema_target = ptr_as_ref(is_schema_target); let decorator = DecoratorValue::new(name, args, kwargs); decorator.run( + mut_ptr_as_ref(ctx), attr_name, is_schema_target.as_bool(), config_value, @@ -2567,13 +2651,13 @@ pub unsafe extern "C" fn kclvm_value_Decorator( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_lower( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_lower().into_raw() + val.str_lower().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_lower"); } @@ -2582,13 +2666,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_lower( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_upper( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_upper().into_raw() + val.str_upper().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_upper"); } @@ -2597,13 +2681,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_upper( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_capitalize( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_capitalize().into_raw() + val.str_capitalize().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_capitalize"); } @@ -2612,7 +2696,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_capitalize( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_count( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2621,7 +2705,8 @@ pub unsafe extern "C" fn kclvm_builtin_str_count( if let Some(sub) = args.arg_0() { let start = args.arg_i(1); let end = args.arg_i(2); - val.str_count(&sub, start.as_ref(), end.as_ref()).into_raw() + val.str_count(&sub, start.as_ref(), end.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("count() takes at least 1 argument (0 given)"); } @@ -2633,7 +2718,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_count( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_endswith( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2643,7 +2728,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_endswith( let start = args.arg_i(1); let end = args.arg_i(2); val.str_endswith(&suffix, start.as_ref(), end.as_ref()) - .into_raw() + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("endswith() takes at least 1 argument (0 given)"); } @@ -2655,7 +2740,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_endswith( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_find( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2664,7 +2749,8 @@ pub unsafe extern "C" fn kclvm_builtin_str_find( if let Some(sub) = args.arg_0() { let start = args.arg_i(1); let end = args.arg_i(2); - val.str_find(&sub, start.as_ref(), end.as_ref()).into_raw() + val.str_find(&sub, start.as_ref(), end.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("find() takes at least 1 argument (0 given)"); } @@ -2676,14 +2762,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_find( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_format( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); let kwargs = ptr_as_ref(kwargs); if let Some(val) = args.pop_arg_first() { - val.str_format(args, kwargs).into_raw() + val.str_format(args, kwargs).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_format"); } @@ -2692,7 +2778,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_format( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_index( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2701,7 +2787,8 @@ pub unsafe extern "C" fn kclvm_builtin_str_index( if let Some(sub) = args.arg_0() { let start = args.arg_i(1); let end = args.arg_i(2); - val.str_index(&sub, start.as_ref(), end.as_ref()).into_raw() + val.str_index(&sub, start.as_ref(), end.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("index() takes at least 1 argument (0 given)"); } @@ -2713,13 +2800,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_index( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_isalnum( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_isalnum().into_raw() + val.str_isalnum().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_isalnum"); } @@ -2728,13 +2815,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_isalnum( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_isalpha( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_isalpha().into_raw() + val.str_isalpha().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_isalpha"); } @@ -2743,13 +2830,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_isalpha( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_isdigit( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_isdigit().into_raw() + val.str_isdigit().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_isdigit"); } @@ -2758,13 +2845,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_isdigit( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_islower( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_islower().into_raw() + val.str_islower().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_islower"); } @@ -2773,13 +2860,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_islower( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_isspace( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_isspace().into_raw() + val.str_isspace().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_isspace"); } @@ -2788,13 +2875,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_isspace( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_istitle( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_istitle().into_raw() + val.str_istitle().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_istitle"); } @@ -2803,13 +2890,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_istitle( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_isupper( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_isupper().into_raw() + val.str_isupper().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_isupper"); } @@ -2818,14 +2905,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_isupper( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_join( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { let iter = args.arg_i(0).unwrap(); - val.str_join(&iter).into_raw() + val.str_join(&iter).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_join"); } @@ -2834,14 +2921,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_join( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_lstrip( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { let chars = args.arg_i(0); - val.str_lstrip(chars.as_ref()).into_raw() + val.str_lstrip(chars.as_ref()).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_lstrip"); } @@ -2850,14 +2937,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_lstrip( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_rstrip( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { let chars = args.arg_i(0); - val.str_rstrip(chars.as_ref()).into_raw() + val.str_rstrip(chars.as_ref()).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_rstrip"); } @@ -2866,16 +2953,17 @@ pub unsafe extern "C" fn kclvm_builtin_str_rstrip( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_replace( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - let old = args.arg_i(0).unwrap(); - let new = args.arg_i(1).unwrap(); + let old = args.arg_i(0).expect("expect 1 argument, found 0"); + let new = args.arg_i(1).expect("expect 2 arguments, found 1"); let count = args.arg_i(2); - val.str_replace(&old, &new, count.as_ref()).into_raw() + val.str_replace(&old, &new, count.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_replace"); } @@ -2886,14 +2974,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_replace( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_removeprefix( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - let prefix = args.arg_i(0).unwrap(); - val.str_removeprefix(&prefix).into_raw() + let prefix = args.arg_i(0).expect("expect 1 argument, found 0"); + val.str_removeprefix(&prefix).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_removeprefix"); } @@ -2904,14 +2992,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_removeprefix( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_removesuffix( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - let suffix = args.arg_i(0).unwrap(); - val.str_removesuffix(&suffix).into_raw() + let suffix = args.arg_i(0).expect("expect 1 argument, found 0"); + val.str_removesuffix(&suffix).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_removesuffix"); } @@ -2920,7 +3008,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_removesuffix( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_rfind( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2929,7 +3017,8 @@ pub unsafe extern "C" fn kclvm_builtin_str_rfind( if let Some(sub) = args.arg_0() { let start = args.arg_i(1); let end = args.arg_i(2); - val.str_rfind(&sub, start.as_ref(), end.as_ref()).into_raw() + val.str_rfind(&sub, start.as_ref(), end.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("rfind() takes at least 1 argument (0 given)"); } @@ -2941,7 +3030,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_rfind( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_rindex( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2951,7 +3040,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_rindex( let start = args.arg_i(1); let end = args.arg_i(2); val.str_rindex(&sub, start.as_ref(), end.as_ref()) - .into_raw() + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("rindex() takes at least 1 argument (0 given)"); } @@ -2963,7 +3052,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_rindex( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_rsplit( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -2980,7 +3069,8 @@ pub unsafe extern "C" fn kclvm_builtin_str_rsplit( } else { kwargs.kwarg("maxsplit") }; - val.str_rsplit(sep.as_ref(), maxsplit.as_ref()).into_raw() + val.str_rsplit(sep.as_ref(), maxsplit.as_ref()) + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_rsplit"); } @@ -2989,7 +3079,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_rsplit( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_split( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -3007,7 +3097,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_split( kwargs.kwarg("maxsplit") }; let x = val.str_split(sep.as_ref(), maxsplit.as_ref()); - x.into_raw() + x.into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_split"); } @@ -3016,7 +3106,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_split( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_splitlines( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -3024,11 +3114,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_splitlines( let kwargs = ptr_as_ref(kwargs); if let Some(val) = args.pop_arg_first() { if let Some(keepends) = args.arg_i(0) { - val.str_splitlines(Some(&keepends)).into_raw() + val.str_splitlines(Some(&keepends)) + .into_raw(mut_ptr_as_ref(ctx)) } else if let Some(keepends) = kwargs.kwarg("keepends") { - val.str_splitlines(Some(&keepends)).into_raw() + val.str_splitlines(Some(&keepends)) + .into_raw(mut_ptr_as_ref(ctx)) } else { - val.str_splitlines(None).into_raw() + val.str_splitlines(None).into_raw(mut_ptr_as_ref(ctx)) } } else { panic!("invalid self value in str_splitlines"); @@ -3038,7 +3130,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_splitlines( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_startswith( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { @@ -3048,7 +3140,7 @@ pub unsafe extern "C" fn kclvm_builtin_str_startswith( let start = args.arg_i(1); let end = args.arg_i(2); val.str_startswith(&suffix, start.as_ref(), end.as_ref()) - .into_raw() + .into_raw(mut_ptr_as_ref(ctx)) } else { panic!("startswith() takes at least 1 argument (0 given)"); } @@ -3060,14 +3152,14 @@ pub unsafe extern "C" fn kclvm_builtin_str_startswith( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_strip( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { let chars = args.arg_i(0); - val.str_strip(chars.as_ref()).into_raw() + val.str_strip(chars.as_ref()).into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_strip"); } @@ -3076,13 +3168,13 @@ pub unsafe extern "C" fn kclvm_builtin_str_strip( #[no_mangle] #[runtime_fn] pub unsafe extern "C" fn kclvm_builtin_str_title( - _ctx: *mut kclvm_context_t, + ctx: *mut kclvm_context_t, args: *const kclvm_value_ref_t, _kwargs: *const kclvm_value_ref_t, ) -> *const kclvm_value_ref_t { let args = ptr_as_ref(args); if let Some(val) = args.pop_arg_first() { - val.str_title().into_raw() + val.str_title().into_raw(mut_ptr_as_ref(ctx)) } else { panic!("invalid self value in str_title"); } diff --git a/kclvm/runtime/src/value/iter.rs b/kclvm/runtime/src/value/iter.rs index 224bab593..2aa5467ca 100644 --- a/kclvm/runtime/src/value/iter.rs +++ b/kclvm/runtime/src/value/iter.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/mod.rs b/kclvm/runtime/src/value/mod.rs index 3ff12728d..009c0b968 100644 --- a/kclvm/runtime/src/value/mod.rs +++ b/kclvm/runtime/src/value/mod.rs @@ -1,7 +1,6 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub mod val_panic; -pub use val_panic::*; pub mod val_overflow; pub use val_overflow::*; @@ -13,49 +12,37 @@ pub mod iter; pub use iter::*; pub mod val; -pub use val::*; pub mod val_len; -pub use val_len::*; pub mod val_args; pub use val_args::*; pub mod val_logic; -pub use val_logic::*; pub mod val_as_val; -pub use val_as_val::*; pub mod val_kind; -pub use val_kind::*; pub mod val_clone; -pub use val_clone::*; pub mod val_cmp; -pub use val_cmp::*; pub mod val_decorator; pub use val_decorator::*; pub mod val_is_in; -pub use val_is_in::*; pub mod val_list; -pub use val_list::*; pub mod val_dict; -pub use val_dict::*; pub mod val_fmt; pub use val_fmt::*; pub mod val_from; -pub use val_from::*; pub mod val_get_set; -pub use val_get_set::*; pub mod val_schema; pub use val_schema::*; @@ -64,19 +51,15 @@ pub mod val_json; pub use val_json::*; pub mod val_bin_aug; -pub use val_bin_aug::*; pub mod val_unary; -pub use val_unary::*; pub mod val_bin; -pub use val_bin::*; pub mod val_plan; pub use val_plan::*; pub mod val_str; -pub use val_str::*; pub mod val_type; pub use val_type::*; @@ -86,3 +69,5 @@ pub use val_union::*; pub mod val_yaml; pub use val_yaml::*; + +pub mod walker; diff --git a/kclvm/runtime/src/value/val.rs b/kclvm/runtime/src/value/val.rs index 958373dc4..7371ced5c 100644 --- a/kclvm/runtime/src/value/val.rs +++ b/kclvm/runtime/src/value/val.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_args.rs b/kclvm/runtime/src/value/val_args.rs index b70bf4253..2e9a83169 100644 --- a/kclvm/runtime/src/value/val_args.rs +++ b/kclvm/runtime/src/value/val_args.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -89,6 +89,18 @@ impl ValueRef { default } + pub fn arg_i_int_or_bool(&self, i: usize, default: Option) -> Option { + if let Some(x) = self.arg_i(i) { + match *x.rc.borrow() { + Value::bool_value(v) => return Some(v as i64), + Value::int_value(v) => return Some(v), + Value::none => return default, + _ => return None, + } + } + default + } + pub fn arg_i_float(&self, i: usize, default: Option) -> Option { if let Some(x) = self.arg_i(i) { match *x.rc.borrow() { diff --git a/kclvm/runtime/src/value/val_as_val.rs b/kclvm/runtime/src/value/val_as_val.rs index 73ffd66dc..a6cdeb92e 100644 --- a/kclvm/runtime/src/value/val_as_val.rs +++ b/kclvm/runtime/src/value/val_as_val.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; use std::cell::Ref; diff --git a/kclvm/runtime/src/value/val_bin.rs b/kclvm/runtime/src/value/val_bin.rs index 441538190..fe2e07767 100644 --- a/kclvm/runtime/src/value/val_bin.rs +++ b/kclvm/runtime/src/value/val_bin.rs @@ -1,39 +1,38 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; impl ValueRef { - pub fn bin_add(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_add(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_add(*a, *b) { - panic_i32_overflow!(*a as i128 + *b as i128); + panic_i32_overflow!(ctx, *a as i128 + *b as i128); } if strict_range_check_64 && is_i64_overflow_add(*a, *b) { - panic_i64_overflow!(*a as i128 + *b as i128); + panic_i64_overflow!(ctx, *a as i128 + *b as i128); } Self::int(*a + *b) } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_add(*a, *b) { - panic_f32_overflow!(*a + *b); + panic_f32_overflow!(ctx, *a + *b); } Self::float(*a + *b) } (Value::int_value(a), Value::float_value(b)) => { if is_f32_overflow_add(*a as f64, *b) { - panic_f32_overflow!(*a as f64 + *b); + panic_f32_overflow!(ctx, *a as f64 + *b); } Self::float(*a as f64 + *b) } (Value::float_value(a), Value::int_value(b)) => { if is_f32_overflow_add(*a, *b as f64) { - panic_f32_overflow!(*a + *b as f64); + panic_f32_overflow!(ctx, *a + *b as f64); } Self::float(*a + *b as f64) } @@ -61,36 +60,35 @@ impl ValueRef { } } - pub fn bin_sub(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_sub(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_sub(*a, *b) { - panic_i32_overflow!(*a as i128 - *b as i128); + panic_i32_overflow!(ctx, *a as i128 - *b as i128); } if strict_range_check_64 && is_i64_overflow_sub(*a, *b) { - panic_i32_overflow!(*a as i128 - *b as i128); + panic_i32_overflow!(ctx, *a as i128 - *b as i128); } Self::int(*a - *b) } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a, *b) { - panic_f32_overflow!(*a - *b); + panic_f32_overflow!(ctx, *a - *b); } Self::float(*a - *b) } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a as f64, *b) { - panic_f32_overflow!(*a as f64 - *b); + panic_f32_overflow!(ctx, *a as f64 - *b); } Self::float(*a as f64 - *b) } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a, *b as f64) { - panic_f32_overflow!(*a - *b as f64); + panic_f32_overflow!(ctx, *a - *b as f64); } Self::float(*a - *b as f64) } @@ -98,36 +96,35 @@ impl ValueRef { } } - pub fn bin_mul(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_mul(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_mul(*a, *b) { - panic_i32_overflow!(*a as i128 * *b as i128); + panic_i32_overflow!(ctx, *a as i128 * *b as i128); } if strict_range_check_64 && is_i64_overflow_mul(*a, *b) { - panic_i64_overflow!(*a as i128 * *b as i128); + panic_i64_overflow!(ctx, *a as i128 * *b as i128); } Self::int(*a * *b) } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a, *b) { - panic_f32_overflow!(*a * *b); + panic_f32_overflow!(ctx, *a * *b); } Self::float(*a * *b) } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a as f64, *b) { - panic_f32_overflow!(*a as f64 * *b); + panic_f32_overflow!(ctx, *a as f64 * *b); } Self::float(*a as f64 * *b) } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a, *b as f64) { - panic_f32_overflow!(*a * *b as f64); + panic_f32_overflow!(ctx, *a * *b as f64); } Self::float(*a * *b as f64) } @@ -184,36 +181,35 @@ impl ValueRef { } } - pub fn bin_pow(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_pow(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(ref a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_pow(*a, *b) { - panic_i32_overflow!((*a as i128).pow(*b as u32)); + panic_i32_overflow!(ctx, (*a as i128).pow(*b as u32)); } if strict_range_check_64 && is_i64_overflow_pow(*a, *b) { - panic_i64_overflow!((*a as i128).pow(*b as u32)); + panic_i64_overflow!(ctx, (*a as i128).pow(*b as u32)); } Self::int(a.pow(*b as u32)) } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a, *b) { - panic_f32_overflow!(a.powf(*b)); + panic_f32_overflow!(ctx, a.powf(*b)); } Self::float(a.powf(*b)) } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a as f64, *b) { - panic_f32_overflow!((*a as f64).powf(*b)); + panic_f32_overflow!(ctx, (*a as f64).powf(*b)); } Self::float((*a as f64).powf(*b)) } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a, *b as f64) { - panic_f32_overflow!(a.powf(*b as f64)); + panic_f32_overflow!(ctx, a.powf(*b as f64)); } Self::float(a.powf(*b as f64)) } @@ -239,18 +235,17 @@ impl ValueRef { } } - pub fn bin_bit_lshift(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_bit_lshift(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_shl(*a, *b) { - panic_i32_overflow!((*a as i128) << (*b as u32)); + panic_i32_overflow!(ctx, (*a as i128) << (*b as u32)); } if strict_range_check_64 && is_i64_overflow_shl(*a, *b) { - panic_i64_overflow!((*a as i128) << (*b as u32)); + panic_i64_overflow!(ctx, (*a as i128) << (*b as u32)); } Self::int(*a << *b) } @@ -258,18 +253,17 @@ impl ValueRef { } } - pub fn bin_bit_rshift(&self, x: &Self) -> Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_bit_rshift(&self, ctx: &mut Context, x: &Self) -> Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; match (&*self.rc.borrow(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_shr(*a, *b) { - panic_i32_overflow!((*a as i128) >> (*b as u32)); + panic_i32_overflow!(ctx, (*a as i128) >> (*b as u32)); } if strict_range_check_64 && is_i64_overflow_shr(*a, *b) { - panic_i64_overflow!((*a as i128) >> (*b as u32)); + panic_i64_overflow!(ctx, (*a as i128) >> (*b as u32)); } Self::int(*a >> *b) } @@ -291,12 +285,12 @@ impl ValueRef { } } - pub fn bin_bit_or(&self, x: &Self) -> Self { + pub fn bin_bit_or(&self, ctx: &mut Context, x: &Self) -> Self { if let (Value::int_value(a), Value::int_value(b)) = (&*self.rc.borrow(), &*x.rc.borrow()) { return Self::int(*a | *b); }; self.deep_copy() - .union_entry(x, true, &UnionOptions::default()) + .union_entry(ctx, x, true, &UnionOptions::default()) } pub fn bin_subscr(&self, x: &Self) -> Self { @@ -362,6 +356,7 @@ mod test_value_bin { #[test] fn test_int_bin() { + let mut ctx = Context::new(); let cases = [ (0, 0, "+", 0), (1, 1, "-", 0), @@ -380,17 +375,17 @@ mod test_value_bin { let left = ValueRef::int(left); let right = ValueRef::int(right); let result = match op { - "+" => left.bin_add(&right), - "-" => left.bin_sub(&right), - "*" => left.bin_mul(&right), + "+" => left.bin_add(&mut ctx, &right), + "-" => left.bin_sub(&mut ctx, &right), + "*" => left.bin_mul(&mut ctx, &right), "/" => left.bin_div(&right), "//" => left.bin_floor_div(&right), "%" => left.bin_mod(&right), - "**" => left.bin_pow(&right), - "<<" => left.bin_bit_lshift(&right), - ">>" => left.bin_bit_rshift(&right), + "**" => left.bin_pow(&mut ctx, &right), + "<<" => left.bin_bit_lshift(&mut ctx, &right), + ">>" => left.bin_bit_rshift(&mut ctx, &right), "&" => left.bin_bit_and(&right), - "|" => left.bin_bit_or(&right), + "|" => left.bin_bit_or(&mut ctx, &right), "^" => left.bin_bit_xor(&right), _ => panic!("invalid op {}", op), }; diff --git a/kclvm/runtime/src/value/val_bin_aug.rs b/kclvm/runtime/src/value/val_bin_aug.rs index e70461074..d5e2c4543 100644 --- a/kclvm/runtime/src/value/val_bin_aug.rs +++ b/kclvm/runtime/src/value/val_bin_aug.rs @@ -1,41 +1,40 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; impl ValueRef { - pub fn bin_aug_add(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_add(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_add(*a, *b) { - panic_i32_overflow!(*a as i128 + *b as i128); + panic_i32_overflow!(ctx, *a as i128 + *b as i128); } if strict_range_check_64 && is_i64_overflow_add(*a, *b) { - panic_i64_overflow!(*a as i128 + *b as i128); + panic_i64_overflow!(ctx, *a as i128 + *b as i128); } *a += *b; true } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_add(*a, *b) { - panic_f32_overflow!(*a + *b); + panic_f32_overflow!(ctx, *a + *b); } *a += *b; true } (Value::int_value(a), Value::float_value(b)) => { if is_f32_overflow_add(*a as f64, *b) { - panic_f32_overflow!(*a as f64 + *b); + panic_f32_overflow!(ctx, *a as f64 + *b); } *a += *b as i64; true } (Value::float_value(a), Value::int_value(b)) => { if is_f32_overflow_add(*a, *b as f64) { - panic_f32_overflow!(*a + *b as f64); + panic_f32_overflow!(ctx, *a + *b as f64); } *a += *b as f64; true @@ -61,19 +60,18 @@ impl ValueRef { self } - pub fn bin_aug_sub(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_sub(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_sub(*a, *b) { - panic_i32_overflow!(*a as i128 - *b as i128); + panic_i32_overflow!(ctx, *a as i128 - *b as i128); } if strict_range_check_64 && is_i64_overflow_sub(*a, *b) { { - panic_i32_overflow!(*a as i128 - *b as i128); + panic_i32_overflow!(ctx, *a as i128 - *b as i128); } } *a -= *b; @@ -81,21 +79,21 @@ impl ValueRef { } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a, *b) { - panic_f32_overflow!(*a - *b); + panic_f32_overflow!(ctx, *a - *b); } *a -= *b; true } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a as f64, *b) { - panic_f32_overflow!(*a as f64 - *b); + panic_f32_overflow!(ctx, *a as f64 - *b); } *a -= *b as i64; true } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_sub(*a, *b as f64) { - panic_f32_overflow!(*a - *b as f64); + panic_f32_overflow!(ctx, *a - *b as f64); } *a -= *b as f64; true @@ -108,39 +106,38 @@ impl ValueRef { self } - pub fn bin_aug_mul(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_mul(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_mul(*a, *b) { - panic_i32_overflow!(*a as i128 * *b as i128); + panic_i32_overflow!(ctx, *a as i128 * *b as i128); } if strict_range_check_64 && is_i64_overflow_mul(*a, *b) { - panic_i64_overflow!(*a as i128 * *b as i128); + panic_i64_overflow!(ctx, *a as i128 * *b as i128); } *a *= *b; true } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a, *b) { - panic_f32_overflow!(*a * *b); + panic_f32_overflow!(ctx, *a * *b); } *a *= *b; true } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a as f64, *b) { - panic_f32_overflow!(*a as f64 * *b); + panic_f32_overflow!(ctx, *a as f64 * *b); } *a *= *b as i64; true } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_mul(*a, *b as f64) { - panic_f32_overflow!(*a * *b as f64); + panic_f32_overflow!(ctx, *a * *b as f64); } *a *= *b as f64; true @@ -227,39 +224,38 @@ impl ValueRef { self } - pub fn bin_aug_pow(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_pow(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_pow(*a, *b) { - panic_i32_overflow!((*a as i128).pow(*b as u32)); + panic_i32_overflow!(ctx, (*a as i128).pow(*b as u32)); } if strict_range_check_64 && is_i64_overflow_pow(*a, *b) { - panic_i64_overflow!((*a as i128).pow(*b as u32)); + panic_i64_overflow!(ctx, (*a as i128).pow(*b as u32)); } *a = a.pow(*b as u32); true } (Value::float_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a, *b) { - panic_f32_overflow!(a.powf(*b)); + panic_f32_overflow!(ctx, a.powf(*b)); } *a = a.powf(*b); true } (Value::int_value(a), Value::float_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a as f64, *b) { - panic_f32_overflow!((*a as f64).powf(*b)); + panic_f32_overflow!(ctx, (*a as f64).powf(*b)); } *a = a.pow(*b as u32); true } (Value::float_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_f32_overflow_pow(*a, *b as f64) { - panic_f32_overflow!(a.powf(*b as f64)); + panic_f32_overflow!(ctx, a.powf(*b as f64)); } *a = a.powf(*b as f64); true @@ -304,18 +300,17 @@ impl ValueRef { self } - pub fn bin_aug_bit_lshift(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_bit_lshift(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_shl(*a, *b) { - panic_i32_overflow!((*a as i128) << (*b as u32)); + panic_i32_overflow!(ctx, (*a as i128) << (*b as u32)); } if strict_range_check_64 && is_i64_overflow_shl(*a, *b) { - panic_i64_overflow!((*a as i128) << (*b as u32)); + panic_i64_overflow!(ctx, (*a as i128) << (*b as u32)); } *a <<= *b as usize; true @@ -328,18 +323,17 @@ impl ValueRef { self } - pub fn bin_aug_bit_rshift(&mut self, x: &Self) -> &mut Self { - let ctx = crate::Context::current_context_mut(); + pub fn bin_aug_bit_rshift(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let strict_range_check_32 = ctx.cfg.strict_range_check; let strict_range_check_64 = ctx.cfg.debug_mode || !ctx.cfg.strict_range_check; let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { if strict_range_check_32 && is_i32_overflow_shr(*a, *b) { - panic_i32_overflow!((*a as i128) >> (*b as u32)); + panic_i32_overflow!(ctx, (*a as i128) >> (*b as u32)); } if strict_range_check_64 && is_i64_overflow_shr(*a, *b) { - panic_i64_overflow!((*a as i128) >> (*b as u32)); + panic_i64_overflow!(ctx, (*a as i128) >> (*b as u32)); } *a >>= *b as usize; true @@ -380,7 +374,7 @@ impl ValueRef { self } - pub fn bin_aug_bit_or(&mut self, x: &Self) -> &mut Self { + pub fn bin_aug_bit_or(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { let valid = match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::int_value(a), Value::int_value(b)) => { *a |= *b; @@ -390,7 +384,7 @@ impl ValueRef { }; if !valid { if self.is_list_or_config() || x.is_list_or_config() { - self.union_entry(x, true, &UnionOptions::default()); + self.union_entry(ctx, x, true, &UnionOptions::default()); } else { panic_unsupported_bin_op!("|", self.type_str(), x.type_str()); } @@ -399,8 +393,8 @@ impl ValueRef { } /// Binary aug union a | b - pub fn bin_aug_union_with(&mut self, x: &Self) -> &mut Self { - self.bin_aug_bit_or(x) + pub fn bin_aug_union_with(&mut self, ctx: &mut Context, x: &Self) -> &mut Self { + self.bin_aug_bit_or(ctx, x) } } @@ -424,21 +418,22 @@ mod test_value_bin_aug { (5, 10, "|", 15), (7, 11, "^", 12), ]; + let mut ctx = Context::new(); for (left, right, op, expected) in cases { let mut left = ValueRef::int(left); let right = ValueRef::int(right); let result = match op { - "+" => left.bin_aug_add(&right), - "-" => left.bin_aug_sub(&right), - "*" => left.bin_aug_mul(&right), + "+" => left.bin_aug_add(&mut ctx, &right), + "-" => left.bin_aug_sub(&mut ctx, &right), + "*" => left.bin_aug_mul(&mut ctx, &right), "/" => left.bin_aug_div(&right), "//" => left.bin_aug_floor_div(&right), "%" => left.bin_aug_mod(&right), - "**" => left.bin_aug_pow(&right), - "<<" => left.bin_aug_bit_lshift(&right), - ">>" => left.bin_aug_bit_rshift(&right), + "**" => left.bin_aug_pow(&mut ctx, &right), + "<<" => left.bin_aug_bit_lshift(&mut ctx, &right), + ">>" => left.bin_aug_bit_rshift(&mut ctx, &right), "&" => left.bin_aug_bit_and(&right), - "|" => left.bin_aug_bit_or(&right), + "|" => left.bin_aug_bit_or(&mut ctx, &right), "^" => left.bin_aug_bit_xor(&right), _ => panic!("invalid op {}", op), }; @@ -448,16 +443,19 @@ mod test_value_bin_aug { #[test] fn test_aug_add() { + let mut ctx = Context::new(); // int assert_eq!( - ValueRef::int(1).bin_aug_add(&ValueRef::int(2)).as_int(), + ValueRef::int(1) + .bin_aug_add(&mut ctx, &ValueRef::int(2)) + .as_int(), 1 + 2 ); // float assert_eq!( ValueRef::float(1.5) - .bin_aug_add(&ValueRef::float(2.0)) + .bin_aug_add(&mut ctx, &ValueRef::float(2.0)) .as_float(), 3.5 ); @@ -468,14 +466,16 @@ mod test_value_bin_aug { // int + float => int assert_eq!( - ValueRef::int(1).bin_aug_add(&ValueRef::float(2.5)).as_int(), + ValueRef::int(1) + .bin_aug_add(&mut ctx, &ValueRef::float(2.5)) + .as_int(), 1 + 2 ); // float + int => float assert_eq!( ValueRef::float(1.5) - .bin_aug_add(&ValueRef::int(2)) + .bin_aug_add(&mut ctx, &ValueRef::int(2)) .as_float(), 1.5 + 2.0 ); diff --git a/kclvm/runtime/src/value/val_clone.rs b/kclvm/runtime/src/value/val_clone.rs index c9348d4ad..dd9865b5c 100644 --- a/kclvm/runtime/src/value/val_clone.rs +++ b/kclvm/runtime/src/value/val_clone.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use std::boxed::Box; use std::cell::RefCell; @@ -19,7 +19,13 @@ impl ValueRef { rc: Rc::new(RefCell::new(Value::func_value(Box::new(FuncValue { fn_ptr: v.fn_ptr, check_fn_ptr: v.check_fn_ptr, - closure: v.closure.deep_copy(), + // In KCL, functions are all pure, so we only need a shallow + // copy of the closure of the function. + // In addition, this can avoid stack overflow issues caused + // by deep copies of references to schema `self` held by functions + // within the schema. Because schema also holds a reference to + // the function. + closure: v.closure.clone(), name: v.name.clone(), runtime_type: v.runtime_type.clone(), is_external: v.is_external, @@ -57,10 +63,14 @@ impl ValueRef { &index.clone(), ); } + dict.set_potential_schema_type(&v.potential_schema.clone().unwrap_or_default()); dict } Value::schema_value(ref v) => { let mut dict = ValueRef::from(Value::dict_value(Box::new(DictValue::new(&[])))); + dict.set_potential_schema_type( + &v.config.potential_schema.clone().unwrap_or_default(), + ); for (key, val) in &v.config.values { let op = v .config @@ -86,6 +96,10 @@ impl ValueRef { config_keys: v.config_keys.clone(), config_meta: v.config_meta.clone(), optional_mapping: v.optional_mapping.clone(), + // For KCL, args and kwargs are both immutable within the schema scope, + // so here we only need to clone the references. + args: v.args.clone(), + kwargs: v.kwargs.clone(), })))), }; } diff --git a/kclvm/runtime/src/value/val_cmp.rs b/kclvm/runtime/src/value/val_cmp.rs index 68df1d43e..b4126552d 100644 --- a/kclvm/runtime/src/value/val_cmp.rs +++ b/kclvm/runtime/src/value/val_cmp.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_decorator.rs b/kclvm/runtime/src/value/val_decorator.rs index df0e5ff01..069621d1c 100644 --- a/kclvm/runtime/src/value/val_decorator.rs +++ b/kclvm/runtime/src/value/val_decorator.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -16,6 +16,7 @@ impl DecoratorValue { pub fn run( &self, + ctx: &mut Context, attr_name: &str, is_schema_target: bool, config_value: &ValueRef, @@ -58,12 +59,11 @@ impl DecoratorValue { if !msg.is_empty() { err_msg.push_str(&msg); } - let ctx = Context::current_context_mut(); if let (Some(filename), Some(line)) = (filename, line) { ctx.set_kcl_filename(&filename.as_str()); ctx.panic_info.kcl_line = line.as_int() as i32; } - ctx.set_err_type(&ErrType::Deprecated_TYPE); + ctx.set_err_type(&RuntimeErrorType::Deprecated); panic!("{}", err_msg) } @@ -72,16 +72,12 @@ impl DecoratorValue { if !msg.is_empty() { err_msg.push_str(&msg); } - - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::Deprecated_Warning_TYPE); - - ctx.set_warnning_message(err_msg.as_str()); + ctx.set_err_type(&RuntimeErrorType::DeprecatedWarning); + ctx.set_warning_message(err_msg.as_str()); } else { - let ctx = Context::current_context_mut(); let err_msg = format!("{attr_name} was deprecated "); - ctx.set_err_type(&ErrType::Deprecated_Warning_TYPE); - ctx.set_warnning_message(err_msg.as_str()); + ctx.set_err_type(&RuntimeErrorType::DeprecatedWarning); + ctx.set_warning_message(err_msg.as_str()); } } DEPRECATED_INFO => { /* Nothing to do on Info decorator */ } @@ -101,13 +97,14 @@ impl DecoratorValue { mod test_value_decorator { use crate::*; - fn assert_panic () + std::panic::UnwindSafe>(func: F) { + fn assert_panic(func: F) { let result = std::panic::catch_unwind(func); assert!(result.is_err()) } #[test] fn test_decorator() { + let mut ctx = Context::new(); let args = ValueRef::list(None); let mut kwargs = ValueRef::dict(None); let test_deprecated_decorator = DecoratorValue::new(DEPRECATED_DECORATOR, &args, &kwargs); @@ -115,12 +112,13 @@ mod test_value_decorator { let schema_name = "Data"; let config_meta = ValueRef::dict(None); let config_value = ValueRef::dict_str(&[("key1", "value1")]); - test_deprecated_decorator.run(schema_name, true, &config_value, &config_meta); + test_deprecated_decorator.run(&mut ctx, schema_name, true, &config_value, &config_meta); } #[test] fn test_decorator_invalid() { assert_panic(|| { + let mut ctx = Context::new(); let args = ValueRef::list(None); let kwargs = ValueRef::dict(None); let test_deprecated_decorator = @@ -128,7 +126,7 @@ mod test_value_decorator { let schema_name = "Data"; let config_meta = ValueRef::dict(None); let config_value = ValueRef::dict_str(&[("key1", "value1")]); - test_deprecated_decorator.run(schema_name, true, &config_value, &config_meta); + test_deprecated_decorator.run(&mut ctx, schema_name, true, &config_value, &config_meta); }); } } diff --git a/kclvm/runtime/src/value/val_dict.rs b/kclvm/runtime/src/value/val_dict.rs index 8c7a6a0f9..2ec61c758 100644 --- a/kclvm/runtime/src/value/val_dict.rs +++ b/kclvm/runtime/src/value/val_dict.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; use std::cell::Ref; @@ -116,6 +116,26 @@ impl ValueRef { } } + /// Dict get value e.g., {k1 = v1, k2 = v2}.get_attr_operator(k1) == Some(ConfigEntryOperationKind::Override) + pub fn dict_get_attr_operator(&self, key: &str) -> Option { + match &*self.rc.borrow() { + Value::dict_value(ref dict) => dict.ops.get(key).cloned(), + Value::schema_value(ref schema) => schema.config.ops.get(key).cloned(), + _ => None, + } + } + + /// Dict get value e.g., {k1 = v1, k2 = v2}.get_attr_operator(k1) == Some(ConfigEntryOperationKind::Override) + pub fn dict_get_insert_index(&self, key: &str) -> Option { + match &*self.rc.borrow() { + Value::dict_value(ref dict) => Some(*dict.insert_indexs.get(key).unwrap_or(&-1)), + Value::schema_value(ref schema) => { + Some(*schema.config.insert_indexs.get(key).unwrap_or(&-1)) + } + _ => None, + } + } + /// Dict get entry e.g., {k1: v1, k2, v2}.get_entry(k1) == {k1: v1} pub fn dict_get_entry(&self, key: &str) -> Option { match &*self.rc.borrow() { @@ -134,6 +154,7 @@ impl ValueRef { -1 }; d.dict_update_entry(key, value, op, &index); + d.set_potential_schema_type(&dict.potential_schema.clone().unwrap_or_default()); Some(d) } else { None @@ -154,6 +175,9 @@ impl ValueRef { -1 }; d.dict_update_entry(key, value, op, &index); + d.set_potential_schema_type( + &schema.config.potential_schema.clone().unwrap_or_default(), + ); Some(d) } else { None @@ -180,6 +204,7 @@ impl ValueRef { d.dict_update_entry(key, value, op, index); } } + d.set_potential_schema_type(&dict.potential_schema.clone().unwrap_or_default()); d } Value::schema_value(ref schema) => { @@ -196,6 +221,14 @@ impl ValueRef { d.dict_update_entry(key, value, op, index); } } + d.set_potential_schema_type( + &schema + .config + .potential_schema + .as_ref() + .map(|v| v.to_string()) + .unwrap_or_default(), + ); d } // Panic @@ -213,6 +246,7 @@ impl ValueRef { }; if v.is_config() { let v = v.as_dict_ref(); + dict.potential_schema = v.potential_schema.clone(); for (k, v) in v.values.iter() { dict.values.insert(k.clone(), v.clone()); } @@ -228,7 +262,11 @@ impl ValueRef { Value::schema_value(schema) => { schema.config.values.insert(key.to_string(), val); } - _ => panic!("invalid dict update value: {}", self.type_str()), + _ => panic!( + "failed to update the dict. An iterable of key-value pairs was expected, but got {}. Check if the syntax for updating the dictionary with the attribute '{}' is correct", + self.type_str(), + key + ), } } @@ -254,36 +292,37 @@ impl ValueRef { /// Insert key value pair with the idempotent check pub fn dict_insert( &mut self, + ctx: &mut Context, key: &str, v: &ValueRef, op: ConfigEntryOperationKind, insert_index: i32, ) { - self.dict_merge_key_value_pair(key, v, op, insert_index, true); + self.dict_merge_key_value_pair(ctx, key, v, op, insert_index, true); } /// Merge key value pair without the idempotent check pub fn dict_merge( &mut self, + ctx: &mut Context, key: &str, v: &ValueRef, op: ConfigEntryOperationKind, insert_index: i32, ) { - self.dict_merge_key_value_pair(key, v, op, insert_index, false); + self.dict_merge_key_value_pair(ctx, key, v, op, insert_index, false); } /// Private dict merge key value pair with the idempotent check option fn dict_merge_key_value_pair( &mut self, + ctx: &mut Context, key: &str, v: &ValueRef, op: ConfigEntryOperationKind, insert_index: i32, idempotent_check: bool, ) { - let ctx = crate::Context::current_context_mut(); - if ctx.cfg.debug_mode { if let Value::int_value(ref x) = *v.rc.borrow() { let strict_range_check_i32 = ctx.cfg.strict_range_check; @@ -292,14 +331,12 @@ impl ValueRef { if strict_range_check_i32 { if v_i128 != ((v_i128 as i32) as i128) { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{v_i128}: A 32 bit integer overflow"); } } else if strict_range_check_i64 && v_i128 != ((v_i128 as i64) as i128) { - let ctx = Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{v_i128}: A 64 bit integer overflow"); } @@ -312,6 +349,7 @@ impl ValueRef { dict.ops.insert(key.to_string(), op); dict.insert_indexs.insert(key.to_string(), insert_index); self.union_entry( + ctx, &ValueRef::from(Value::dict_value(Box::new(dict))), true, &UnionOptions { @@ -326,7 +364,7 @@ impl ValueRef { } /// Dict insert unpack value e.g., data = {**v} - pub fn dict_insert_unpack(&mut self, v: &ValueRef) { + pub fn dict_insert_unpack(&mut self, ctx: &mut Context, v: &ValueRef) { let mut union = false; match (&*self.rc.borrow(), &*v.rc.borrow()) { ( @@ -342,7 +380,7 @@ impl ValueRef { _ => panic!("only list, dict and schema object can be used with unpack operators * and **, got {v}"), } if union { - self.bin_aug_bit_or(&v.schema_to_dict().deep_copy()); + self.bin_aug_bit_or(ctx, &v.schema_to_dict().deep_copy()); } } diff --git a/kclvm/runtime/src/value/val_fmt.rs b/kclvm/runtime/src/value/val_fmt.rs index f23f14844..30e3a1e1a 100644 --- a/kclvm/runtime/src/value/val_fmt.rs +++ b/kclvm/runtime/src/value/val_fmt.rs @@ -1,6 +1,6 @@ //! Ref: https://github.com/RustPython/RustPython/blob/main/vm/src/format.rs //! -//! Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use itertools::{Itertools, PeekingNext}; use std::cmp; @@ -420,7 +420,6 @@ impl FormatSpec { .collect::() } - #[allow(dead_code)] fn add_magnitude_separators_for_char( magnitude_string: String, interval: usize, @@ -446,7 +445,6 @@ impl FormatSpec { result } - #[allow(dead_code)] fn get_separator_interval(&self) -> usize { match self.format_type { Some(FormatType::Binary) => 4, @@ -461,7 +459,6 @@ impl FormatSpec { } } - #[allow(dead_code)] fn add_magnitude_separators(&self, magnitude_string: String) -> String { match self.grouping_option { Some(FormatGrouping::Comma) => FormatSpec::add_magnitude_separators_for_char( @@ -601,15 +598,6 @@ impl FormatSpec { self.format_sign_and_align(&magnitude_string, sign_str) } - #[allow(dead_code)] - pub(crate) fn format_string(&self, s: &str) -> Result { - match self.format_type { - Some(FormatType::String) | None => self.format_sign_and_align(s, ""), - _ => Err("Unknown format code for object of type 'str'"), - } - } - - #[allow(dead_code)] fn format_sign_and_align( &self, magnitude_string: &str, @@ -901,7 +889,7 @@ impl FormatString { } FieldType::Keyword(keyword) => kwargs .dict_get_value(keyword.as_str()) - .expect("keyword argument not found") + .unwrap_or_else(|| panic!("keyword argument '{keyword}' not found")) .clone(), }; for name_part in parts { @@ -1061,6 +1049,7 @@ mod test_value_fmt { #[test] fn test_string_format() { + let mut ctx = Context::new(); let cases = [ (r#""{} {}""#, r#"["Hello","World"]"#, "\"Hello World\""), (r#""{:.0f}""#, r#"[1.0]"#, "\"1\""), @@ -1073,7 +1062,7 @@ mod test_value_fmt { ]; for (format_string, args, expected) in cases { let format_string = FormatString::from_str(format_string).unwrap(); - let args = ValueRef::from_json(args).unwrap(); + let args = ValueRef::from_json(&mut ctx, args).unwrap(); let kwargs = ValueRef::dict(None); let result = format_string.format(&args, &kwargs); assert_eq!(&result, expected) diff --git a/kclvm/runtime/src/value/val_from.rs b/kclvm/runtime/src/value/val_from.rs index 331cf4f14..01fa21eba 100644 --- a/kclvm/runtime/src/value/val_from.rs +++ b/kclvm/runtime/src/value/val_from.rs @@ -217,7 +217,7 @@ mod tests_from { fn test_list() { let list = vec![true, false]; - let list_value: ValueRef = ValueRef::from_iter(list.clone().into_iter()); + let list_value: ValueRef = ValueRef::from_iter(list.clone()); assert_eq!(list.len(), list_value.len()); for (i, v) in list.iter().enumerate() { @@ -230,7 +230,7 @@ mod tests_from { fn test_list2() { let list = vec![1, 2, 4, 3]; - let list_value: ValueRef = ValueRef::from_iter(list.clone().into_iter()); + let list_value: ValueRef = ValueRef::from_iter(list.clone()); let list_value: Box = list_value.try_into().unwrap(); assert_eq!( @@ -257,8 +257,8 @@ mod tests_from { }; } - test_try_into!(test_try_into_bool, bool, vec![true, false, true, true]); - test_try_into!(test_try_into_i64, i64, vec![1, 2, 3, -1]); - test_try_into!(test_try_into_f64, f64, vec![1.5, 2.0]); - test_try_into!(test_try_into_str, String, vec!["", "abc"]); + test_try_into!(test_try_into_bool, bool, [true, false, true, true]); + test_try_into!(test_try_into_i64, i64, [1, 2, 3, -1]); + test_try_into!(test_try_into_f64, f64, [1.5, 2.0]); + test_try_into!(test_try_into_str, String, ["", "abc"]); } diff --git a/kclvm/runtime/src/value/val_get_set.rs b/kclvm/runtime/src/value/val_get_set.rs index ca6600ac7..67b3bf377 100644 --- a/kclvm/runtime/src/value/val_get_set.rs +++ b/kclvm/runtime/src/value/val_get_set.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -36,10 +36,22 @@ mod test_value_get { #[test] fn test_get() { let mut list_int = ValueRef::list_int(&[10_i64, 20, 30]); - + let mut ctx = Context::new(); let mut dict = ValueRef::dict(None); - dict.dict_insert("a", &ValueRef::str("a-value"), Default::default(), 0); - dict.dict_insert("b", &ValueRef::str("b-value"), Default::default(), 0); + dict.dict_insert( + &mut ctx, + "a", + &ValueRef::str("a-value"), + Default::default(), + 0, + ); + dict.dict_insert( + &mut ctx, + "b", + &ValueRef::str("b-value"), + Default::default(), + 0, + ); list_int.list_set(1, &dict); list_int.list_set(2, &ValueRef::list_int(&[100_i64, 200, 300])); diff --git a/kclvm/runtime/src/value/val_is_in.rs b/kclvm/runtime/src/value/val_is_in.rs index 7d627b602..86896d016 100644 --- a/kclvm/runtime/src/value/val_is_in.rs +++ b/kclvm/runtime/src/value/val_is_in.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -88,6 +88,19 @@ impl ValueRef { pub fn is_unit(&self) -> bool { matches!(&*self.rc.borrow(), Value::unit_value(..)) } + + #[inline] + pub fn is_scalar(&self) -> bool { + matches!( + &*self.rc.borrow(), + Value::none + | Value::bool_value(_) + | Value::int_value(_) + | Value::float_value(_) + | Value::str_value(_) + | Value::unit_value(..) + ) + } } // in diff --git a/kclvm/runtime/src/value/val_json.rs b/kclvm/runtime/src/value/val_json.rs index 97ee3149e..49983fcba 100644 --- a/kclvm/runtime/src/value/val_json.rs +++ b/kclvm/runtime/src/value/val_json.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use bstr::ByteSlice; use indexmap::IndexMap; @@ -7,7 +7,7 @@ use serde::{ Deserialize, Serialize, }; -use crate::{ConfigEntryOperationKind, ValueRef, KCL_PRIVATE_VAR_PREFIX}; +use crate::{ConfigEntryOperationKind, Context, ValueRef, KCL_PRIVATE_VAR_PREFIX}; macro_rules! tri { ($e:expr $(,)?) => { @@ -356,30 +356,26 @@ where } impl ValueRef { - pub fn from_json(s: &str) -> Result { + pub fn from_json(ctx: &mut Context, s: &str) -> Result { match serde_json::de::from_str::(s) { - Ok(json) => Ok(Self::parse_json(&json)), + Ok(json) => Ok(Self::parse_json(ctx, &json)), Err(err) => Err(err), } } - pub(crate) fn parse_json(json: &JsonValue) -> Self { + pub(crate) fn parse_json(ctx: &mut Context, json: &JsonValue) -> Self { match json { JsonValue::Object(values) => { let mut dict = Self::dict(None); for (name, value) in values { - dict.dict_insert( - name.as_ref(), - &Self::parse_json(value), - ConfigEntryOperationKind::Union, - -1, - ); + let v = Self::parse_json(ctx, value); + dict.dict_insert(ctx, name.as_ref(), &v, ConfigEntryOperationKind::Union, -1); } dict } JsonValue::Array(values) => { let mut list = Self::list(None); for value in values { - list.list_append(&Self::parse_json(value)); + list.list_append(&Self::parse_json(ctx, value)); } list } @@ -423,7 +419,7 @@ impl ValueRef { writer.to_str().unwrap().to_string() } - pub fn to_json_string_with_option(&self, opt: &JsonEncodeOptions) -> String { + pub fn to_json_string_with_options(&self, opt: &JsonEncodeOptions) -> String { let json = self.build_json(opt); let formatter = JsonFormatter::with_indent(opt.indent); let mut writer = Vec::with_capacity(128); @@ -453,7 +449,12 @@ impl ValueRef { Some(n) => JsonValue::Number(n), None => JsonValue::Null, }, - crate::Value::unit_value(..) => JsonValue::String(self.to_string()), + // The number_multiplier is still a number, if we want to get the string form, we can + // use the `str` function e.g. `str(1Mi)` + crate::Value::unit_value(ref v, ..) => match serde_json::Number::from_f64(*v) { + Some(n) => JsonValue::Number(n), + None => JsonValue::Null, + }, crate::Value::str_value(ref v) => JsonValue::String(v.clone()), crate::Value::list_value(ref v) => { @@ -550,6 +551,7 @@ mod test_value_json { #[test] fn test_value_from_correct_json() { + let mut ctx = Context::new(); let cases = [ ( "{\"a\": 1}\n", @@ -569,13 +571,14 @@ mod test_value_json { ("\n{}", ValueRef::dict(Some(&[]))), ]; for (json_str, expected) in cases { - let result = ValueRef::from_json(json_str).unwrap(); + let result = ValueRef::from_json(&mut ctx, json_str).unwrap(); assert_eq!(result, expected); } } #[test] fn test_value_from_err_json() { + let mut ctx = Context::new(); let cases = [ ("{", "EOF while parsing an object at line 1 column 1"), ("{\"a\": 1,}", "trailing comma at line 1 column 9"), @@ -583,7 +586,7 @@ mod test_value_json { ("[}", "expected value at line 1 column 2"), ]; for (json_str, expected) in cases { - let result = ValueRef::from_json(json_str); + let result = ValueRef::from_json(&mut ctx, json_str); assert_eq!(result.err().unwrap().to_string(), expected); } } diff --git a/kclvm/runtime/src/value/val_kind.rs b/kclvm/runtime/src/value/val_kind.rs index 0fb305c22..3e36e83d6 100644 --- a/kclvm/runtime/src/value/val_kind.rs +++ b/kclvm/runtime/src/value/val_kind.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_len.rs b/kclvm/runtime/src/value/val_len.rs index b6a3f72e8..602dc81a4 100644 --- a/kclvm/runtime/src/value/val_len.rs +++ b/kclvm/runtime/src/value/val_len.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; @@ -22,16 +22,19 @@ impl ValueRef { mod test_value_len { use crate::*; - fn assert_panic () + std::panic::UnwindSafe>(func: F) { + fn assert_panic(func: F) { let result = std::panic::catch_unwind(func); assert!(result.is_err()) } #[test] fn test_len() { + let mut ctx = Context::new(); assert_eq!(ValueRef::str("abc").len(), 3); assert_eq!( - ValueRef::str("abc").bin_aug_mul(&ValueRef::int(10)).len(), + ValueRef::str("abc") + .bin_aug_mul(&mut ctx, &ValueRef::int(10)) + .len(), 3 * 10 ); assert_eq!(ValueRef::list_n(10, &ValueRef::undefined()).len(), 10); diff --git a/kclvm/runtime/src/value/val_list.rs b/kclvm/runtime/src/value/val_list.rs index e1d265df8..b1551293b 100644 --- a/kclvm/runtime/src/value/val_list.rs +++ b/kclvm/runtime/src/value/val_list.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_logic.rs b/kclvm/runtime/src/value/val_logic.rs index ea5d0267f..bb9a2179e 100644 --- a/kclvm/runtime/src/value/val_logic.rs +++ b/kclvm/runtime/src/value/val_logic.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_overflow.rs b/kclvm/runtime/src/value/val_overflow.rs index 9fd9cc01e..9d584c978 100644 --- a/kclvm/runtime/src/value/val_overflow.rs +++ b/kclvm/runtime/src/value/val_overflow.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub fn is_i32_overflow(v: i64) -> bool { v > i32::MAX as i64 || v < i32::MIN as i64 diff --git a/kclvm/runtime/src/value/val_panic.rs b/kclvm/runtime/src/value/val_panic.rs index 5874f18c1..541a37ccd 100644 --- a/kclvm/runtime/src/value/val_panic.rs +++ b/kclvm/runtime/src/value/val_panic.rs @@ -1,31 +1,28 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. #[macro_export] macro_rules! panic_i32_overflow { - ($v: expr) => { + ($ctx: expr,$v: expr) => { let v = $v as i128; - let ctx = $crate::Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + $ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{}: A 32 bit integer overflow", v) }; } #[macro_export] macro_rules! panic_i64_overflow { - ($v: expr) => { + ($ctx: expr,$v: expr) => { let v = $v as i128; - let ctx = $crate::Context::current_context_mut(); - ctx.set_err_type(&ErrType::IntOverflow_TYPE); + $ctx.set_err_type(&RuntimeErrorType::IntOverflow); panic!("{}: A 64 bit integer overflow", v) }; } #[macro_export] macro_rules! panic_f32_overflow { - ($v: expr) => { + ($ctx: expr,$v: expr) => { let v = $v as f64; - let ctx = $crate::Context::current_context_mut(); - ctx.set_err_type(&ErrType::FloatOverflow_TYPE); + $ctx.set_err_type(&RuntimeErrorType::FloatOverflow); let mut s = format!("{:e}: A 32-bit floating point number overflow", v); if !s.contains("e-") { diff --git a/kclvm/runtime/src/value/val_plan.rs b/kclvm/runtime/src/value/val_plan.rs index 6aafbcae0..6d6f3d90d 100644 --- a/kclvm/runtime/src/value/val_plan.rs +++ b/kclvm/runtime/src/value/val_plan.rs @@ -1,60 +1,75 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; -use std::boxed::Box; -use std::cell::RefCell; -use std::rc::Rc; pub const KCL_PRIVATE_VAR_PREFIX: &str = "_"; const LIST_DICT_TEMP_KEY: &str = "$"; -const YAML_STREAM_SEP: &str = "\n---\n"; +const SCHEMA_TYPE_META_ATTR: &str = "_type"; -fn filter_results(key_values: &ValueRef) -> Vec { +/// PlanOptions denotes the configuration required to execute the KCL +/// program and the JSON/YAML planning. +#[derive(PartialEq, Clone, Default, Debug)] +pub struct PlanOptions { + /// Sorts the key order in the config. + pub sort_keys: bool, + /// Emit the `_type` attribute in the schema instance. + pub include_schema_type_path: bool, + /// Whether to emit hidden attributes that start with `_` + pub show_hidden: bool, + /// Whether to emit none value in the plan process. + pub disable_none: bool, + /// Whether to emit empty list in the plan process. + pub disable_empty_list: bool, + /// Filter planned value with the path selector. + pub query_paths: Vec, +} + +/// Filter list or config results with context options. +fn filter_results(ctx: &Context, key_values: &ValueRef) -> Vec { let mut results: Vec = vec![]; // Plan list value with the yaml stream format. if key_values.is_list() { let key_values_list = &key_values.as_list_ref().values; for key_values in key_values_list { - results.append(&mut filter_results(key_values)); + if key_values.is_list_or_config() { + results.append(&mut filter_results(ctx, key_values)); + } else if key_values.is_scalar() { + results.push(key_values.clone()); + } } results } // Plan dict value else if key_values.is_config() { - let ctx = Context::current_context(); + let key_values = key_values.as_dict_ref(); // index 0 for in-line keyvalues output, index 1: for standalone keyvalues outputs - let result = ValueRef::dict(None); + let mut result = ValueRef::dict(None); + result.set_potential_schema_type(&key_values.potential_schema.clone().unwrap_or_default()); results.push(result); - let key_values = key_values.as_dict_ref(); for (key, value) in &key_values.values { - if value.is_none() && ctx.cfg.disable_none { + if value.is_none() && ctx.plan_opts.disable_none { continue; } - if key.starts_with(KCL_PRIVATE_VAR_PREFIX) || value.is_undefined() || value.is_func() { + if key.starts_with(KCL_PRIVATE_VAR_PREFIX) && !ctx.plan_opts.show_hidden { continue; - } else if value.is_schema() || value.has_key(SCHEMA_SETTINGS_ATTR_NAME) { - let (filtered, standalone) = handle_schema(value); + } + if value.is_undefined() || value.is_func() { + continue; + } else if value.is_schema() || value.has_potential_schema_type() { + let filtered = handle_schema(ctx, value); if !filtered.is_empty() { - if standalone { - // if the instance is marked as 'STANDALONE', treat it as a separate one and - // extend it and derived STANDALONE instances to results. - for v in filtered { - results.push(v); - } - } else { - // else put it as the value of the key of results - let result = results.get_mut(0).unwrap(); - result.dict_update_key_value(key.as_str(), filtered[0].clone()); - // if the value has derived 'STANDALONE' instances, extend them - if filtered.len() > 1 { - for v in &filtered[1..] { - results.push(v.clone()); - } + // else put it as the value of the key of results + let result = results.get_mut(0).unwrap(); + result.dict_update_key_value(key.as_str(), filtered[0].clone()); + // if the value has derived 'STANDALONE' instances, extend them + if filtered.len() > 1 { + for v in &filtered[1..] { + results.push(v.clone()); } } } } else if value.is_dict() { - let filtered = filter_results(value); + let filtered = filter_results(ctx, value); if !results.is_empty() { let result = results.get_mut(0).unwrap(); if !filtered.is_empty() { @@ -69,34 +84,29 @@ fn filter_results(key_values: &ValueRef) -> Vec { } } else if value.is_list() { let mut filtered_list: Vec = vec![]; - let mut standalone_list: Vec = vec![]; let mut ignore_schema_count = 0; let list_value = value.as_list_ref(); for v in &list_value.values { - if v.is_schema() || v.has_key(SCHEMA_SETTINGS_ATTR_NAME) { - let (filtered, standalone) = handle_schema(v); + if v.is_schema() || v.has_potential_schema_type() { + let filtered = handle_schema(ctx, v); if filtered.is_empty() { ignore_schema_count += 1; continue; - } else if standalone { - for v in filtered { - standalone_list.push(v); - } } else { for v in filtered { filtered_list.push(v); } } } else if v.is_dict() { - let filtered = filter_results(v); + let filtered = filter_results(ctx, v); for v in filtered { filtered_list.push(v); } - } else if v.is_none() && ctx.cfg.disable_none { + } else if v.is_none() && ctx.plan_opts.disable_none { continue; } else if !v.is_undefined() { let list_dict = ValueRef::dict(Some(&[(LIST_DICT_TEMP_KEY, v)])); - let filtered = filter_results(&list_dict); + let filtered = filter_results(ctx, &list_dict); if !filtered.is_empty() { if let Some(v) = filtered[0].get_by_key(LIST_DICT_TEMP_KEY) { filtered_list.push(v.clone()); @@ -109,10 +119,10 @@ fn filter_results(key_values: &ValueRef) -> Vec { } } } - let schema_in_list_count = ignore_schema_count + standalone_list.len(); + let schema_in_list_count = ignore_schema_count; let value = &value.as_list_ref().values; // Plan empty list to values. - if value.is_empty() && ctx.cfg.plan_empty_list { + if value.is_empty() && !ctx.plan_opts.disable_empty_list { let result = results.get_mut(0).unwrap(); result.dict_update_key_value(key.as_str(), ValueRef::list(None)); } @@ -123,113 +133,107 @@ fn filter_results(key_values: &ValueRef) -> Vec { let filtered_list = ValueRef::list(Some(filtered_list)); result.dict_update_key_value(key.as_str(), filtered_list); } - for v in standalone_list { - results.push(v); - } } else { let result = results.get_mut(0).unwrap(); result.dict_update_key_value(key.as_str(), value.clone()); } } - results - .iter() - .enumerate() - .filter(|(index, r)| *index == 0 || !r.is_planned_empty()) - .map(|v| v.1) - .cloned() - .collect() + results.iter().enumerate().map(|v| v.1).cloned().collect() } else { results } } -fn handle_schema(value: &ValueRef) -> (Vec, bool) { - let filtered = filter_results(value); +fn handle_schema(ctx: &Context, value: &ValueRef) -> Vec { + let mut filtered = filter_results(ctx, value); if filtered.is_empty() { - return (filtered, false); + return filtered; } - let settings = SCHEMA_SETTINGS_ATTR_NAME; - let output_type = SETTINGS_OUTPUT_KEY; - let path = format!("{settings}.{output_type}"); - let output_type_option = value.get_by_path(&path); - if let Some(ref output_type) = output_type_option { - if output_type.str_equal(SETTINGS_OUTPUT_IGNORE) { - if filtered.is_empty() { - return (filtered, false); - } else { - return (filtered[1..].to_vec(), true); + // Deal schema type meta attribute and add the attribute with the type string value + // into the planned object. + if ctx.plan_opts.include_schema_type_path { + if let Some(v) = filtered.get_mut(0) { + if v.is_config() { + v.dict_update_key_value( + SCHEMA_TYPE_META_ATTR, + ValueRef::str(&value_type_path(value, true)), + ); } } } - let mut standalone = false; - if let Some(ref output_type) = output_type_option { - if output_type.str_equal(SETTINGS_OUTPUT_STANDALONE) { - standalone = true; - } - } - (filtered, standalone) + filtered } -impl ValueRef { - fn is_planned_empty(&self) -> bool { - (self.is_dict() && !self.is_truthy()) || self.is_undefined() - } - - pub fn plan_to_json_string(&self) -> String { - let result = self.filter_results(); - if result.is_planned_empty() { - return "".to_string(); +/// Returns the type path of the runtime value `v`. +fn value_type_path(v: &ValueRef, full_name: bool) -> String { + match v.get_potential_schema_type() { + Some(ty_str) => { + if full_name { + match ty_str.strip_prefix('@') { + Some(ty_str) => ty_str.to_string(), + None => ty_str.to_string(), + } + } else { + let parts: Vec<&str> = ty_str.rsplit('.').collect(); + match parts.first() { + Some(v) => v.to_string(), + None => type_of(v, full_name), + } + } } - result.to_json_string() - } - - pub fn plan_to_yaml_string(&self) -> String { - let result = self.filter_results(); - result.to_yaml_string() + None => type_of(v, full_name), } +} - /// Plan the value to the YAML string with delimiter `---`. - pub fn plan_to_yaml_string_with_delimiter(&self) -> String { - let results = filter_results(self); - let results = results - .iter() - .map(|r| r.to_yaml_string()) - .collect::>(); - results.join(YAML_STREAM_SEP) - } +/// Returns the type path of the runtime value `v`. +#[inline] +fn type_of(v: &ValueRef, full_name: bool) -> String { + builtin::type_of(v, &ValueRef::bool(full_name)).as_str() +} +impl ValueRef { /// Plan the value to JSON and YAML strings. - pub fn plan(&self, sort_keys: bool) -> (String, String) { - let json_opt = JsonEncodeOptions { - sort_keys, + pub fn plan(&self, ctx: &Context) -> (String, String) { + // Encoding options + let json_opts = JsonEncodeOptions { + sort_keys: ctx.plan_opts.sort_keys, ..Default::default() }; - let yaml_opt = YamlEncodeOptions { - sort_keys, + let yaml_opts = YamlEncodeOptions { + sort_keys: ctx.plan_opts.sort_keys, ..Default::default() }; - if self.is_list_or_config() { - let results = filter_results(self); + // Filter values with query paths + let value = if ctx.plan_opts.query_paths.is_empty() { + self.clone() + } else { + self.filter_by_path(&ctx.plan_opts.query_paths) + .unwrap_or_else(|e| panic!("{e}")) + }; + if value.is_list_or_config() { + let results = filter_results(ctx, &value); + // Plan YAML result let yaml_result = results .iter() .map(|r| { - r.to_yaml_string_with_options(&yaml_opt) + r.to_yaml_string_with_options(&yaml_opts) .strip_suffix('\n') .unwrap() .to_string() }) .collect::>() .join(YAML_STREAM_SEP); - let mut list_result = ValueRef::list(None); - for r in results { - list_result.list_append(&r); - } - let json_result = list_result.to_json_string_with_option(&json_opt); + // Plan JSON result + let json_result = results + .iter() + .map(|r| r.to_json_string_with_options(&json_opts)) + .collect::>() + .join(JSON_STREAM_SEP); (json_result, yaml_result) } else { ( - self.to_json_string_with_option(&json_opt), - self.to_yaml_string_with_options(&yaml_opt), + value.to_json_string_with_options(&json_opts), + value.to_yaml_string_with_options(&yaml_opts), ) } } @@ -241,16 +245,14 @@ impl ValueRef { let path = &path_selector[0]; match self.get_by_path(path) { Some(value) => Ok(value), - None => { - return Err(format!( - "invalid path select operand {path}, value not found" - )) - } + None => Err(format!( + "invalid path select operand {path}, value not found" + )), } } else { let mut values = ValueRef::list(None); for path in path_selector { - let value = match self.get_by_path(&path) { + let value = match self.get_by_path(path) { Some(value) => value, None => { return Err(format!( @@ -266,125 +268,47 @@ impl ValueRef { Ok(self.clone()) } } - - fn filter_results(&self) -> ValueRef { - let ctx = Context::current_context(); - match &*self.rc.borrow() { - Value::undefined => ValueRef { - rc: Rc::new(RefCell::new(Value::undefined)), - }, - Value::none => ValueRef { - rc: Rc::new(RefCell::new(Value::none)), - }, - Value::func_value(ref v) => ValueRef { - rc: Rc::new(RefCell::new(Value::func_value(v.clone()))), - }, - Value::bool_value(ref v) => ValueRef { - rc: Rc::new(RefCell::new(Value::bool_value(*v))), - }, - Value::int_value(ref v) => ValueRef { - rc: Rc::new(RefCell::new(Value::int_value(*v))), - }, - Value::float_value(ref v) => ValueRef { - rc: Rc::new(RefCell::new(Value::float_value(*v))), - }, - Value::unit_value(ref v, _, _) => ValueRef { - rc: Rc::new(RefCell::new(Value::float_value(*v))), - }, - Value::str_value(ref v) => ValueRef { - rc: Rc::new(RefCell::new(Value::str_value(v.to_string()))), - }, - Value::list_value(ref v) => { - let mut list = ValueRef { - rc: Rc::new(RefCell::new(Value::list_value(Box::new(ListValue { - values: vec![], - })))), - }; - for x in v.values.iter() { - if !(x.is_undefined() || x.is_func() || ctx.cfg.disable_none && x.is_none()) { - list.list_append(&x.filter_results()); - } - } - list - } - Value::dict_value(ref v) => { - let mut dict = ValueRef { - rc: Rc::new(RefCell::new(Value::dict_value(Box::new(DictValue { - values: IndexMap::default(), - ops: IndexMap::default(), - insert_indexs: IndexMap::default(), - attr_map: IndexMap::default(), - })))), - }; - for (key, val) in v.values.iter() { - if !(val.is_undefined() - || val.is_func() - || ctx.cfg.disable_none && val.is_none()) - { - dict.dict_insert( - key, - &val.filter_results(), - ConfigEntryOperationKind::Override, - -1, - ); - } - } - dict - } - Value::schema_value(ref v) => { - let mut schema = ValueRef { - rc: Rc::new(RefCell::new(Value::schema_value(Box::new(SchemaValue { - name: v.name.clone(), - pkgpath: v.pkgpath.clone(), - config: Box::new(DictValue { - values: IndexMap::default(), - ops: IndexMap::default(), - insert_indexs: IndexMap::default(), - attr_map: IndexMap::default(), - }), - config_keys: vec![], - config_meta: v.config_meta.clone(), - optional_mapping: v.optional_mapping.clone(), - })))), - }; - for (key, val) in v.config.values.iter() { - if !val.is_undefined() && !val.is_func() { - schema.dict_insert( - key, - &val.filter_results(), - ConfigEntryOperationKind::Union, - -1, - ); - } - } - schema - } - } - } } #[cfg(test)] mod test_value_plan { - use crate::ValueRef; + use crate::{schema_runtime_type, Context, PlanOptions, ValueRef, MAIN_PKG_PATH}; use super::filter_results; + const TEST_SCHEMA_NAME: &str = "Data"; + + fn get_test_schema_value() -> ValueRef { + let mut schema = ValueRef::dict(None).dict_to_schema( + TEST_SCHEMA_NAME, + MAIN_PKG_PATH, + &[], + &ValueRef::dict(None), + &ValueRef::dict(None), + None, + None, + ); + schema.set_potential_schema_type(&schema_runtime_type(TEST_SCHEMA_NAME, MAIN_PKG_PATH)); + schema + } + #[test] fn test_filter_results() { + let ctx = Context::new(); let dict1 = ValueRef::dict_int(&[("k1", 1)]); let dict2 = ValueRef::dict_int(&[("k2", 2)]); let dict3 = ValueRef::dict_int(&[("k3", 3)]); let dict_list = vec![&dict1, &dict2, &dict3]; let list_data = ValueRef::list(Some(&dict_list)); assert_eq!( - filter_results(&list_data), + filter_results(&ctx, &list_data), dict_list .iter() .map(|v| v.deep_copy()) .collect::>() ); for dict in dict_list { - assert_eq!(filter_results(dict), vec![dict.deep_copy()]); + assert_eq!(filter_results(&ctx, dict), vec![dict.deep_copy()]); } } @@ -417,4 +341,54 @@ mod test_value_plan { "invalid path select operand err_path.to, value not found" ); } + + #[test] + fn test_value_plan_with_options() { + let mut ctx = Context::new(); + ctx.plan_opts = PlanOptions::default(); + let schema = get_test_schema_value(); + let mut config = ValueRef::dict(None); + config.dict_update_key_value("data", schema); + config.dict_update_key_value("_hidden", ValueRef::int(1)); + config.dict_update_key_value("vec", ValueRef::list(None)); + config.dict_update_key_value("empty", ValueRef::none()); + let (_, yaml_string) = config.plan(&ctx); + assert_eq!(yaml_string, "data: {}\nvec: []\nempty: null"); + + ctx.plan_opts.include_schema_type_path = true; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!( + yaml_string, + "data:\n _type: __main__.Data\nvec: []\nempty: null" + ); + + ctx.plan_opts.show_hidden = true; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!( + yaml_string, + "data:\n _type: __main__.Data\n_hidden: 1\nvec: []\nempty: null" + ); + + ctx.plan_opts.sort_keys = true; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!( + yaml_string, + "_hidden: 1\ndata:\n _type: __main__.Data\nempty: null\nvec: []" + ); + + ctx.plan_opts.disable_none = true; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!( + yaml_string, + "_hidden: 1\ndata:\n _type: __main__.Data\nvec: []" + ); + + ctx.plan_opts.disable_empty_list = true; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!(yaml_string, "_hidden: 1\ndata:\n _type: __main__.Data"); + + ctx.plan_opts.query_paths = vec!["data".to_string()]; + let (_, yaml_string) = config.plan(&ctx); + assert_eq!(yaml_string, "{}"); + } } diff --git a/kclvm/runtime/src/value/val_schema.rs b/kclvm/runtime/src/value/val_schema.rs index 25a45e82a..3cd44c330 100644 --- a/kclvm/runtime/src/value/val_schema.rs +++ b/kclvm/runtime/src/value/val_schema.rs @@ -1,13 +1,11 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. + +use indexmap::IndexSet; use crate::*; -pub const SETTINGS_OUTPUT_KEY: &str = "output_type"; -pub const SETTINGS_SCHEMA_TYPE_KEY: &str = "__schema_type__"; -pub const SETTINGS_OUTPUT_STANDALONE: &str = "STANDALONE"; -pub const SETTINGS_OUTPUT_INLINE: &str = "INLINE"; -pub const SETTINGS_OUTPUT_IGNORE: &str = "IGNORE"; -pub const SCHEMA_SETTINGS_ATTR_NAME: &str = "__settings__"; +use self::walker::walk_value_mut; + pub const CONFIG_META_FILENAME: &str = "$filename"; pub const CONFIG_META_LINE: &str = "$lineno"; pub const CONFIG_META_COLUMN: &str = "$columnno"; @@ -19,6 +17,7 @@ pub const MAIN_PKG_PATH: &str = "__main__"; pub const PKG_PATH_PREFIX: char = '@'; pub const CAL_MAP_RUNTIME_TYPE: &str = "cal_map_runtime_type"; pub const CAL_MAP_META_LINE: &str = "cal_map_meta_line"; +pub const CAL_MAP_INDEX_SIGNATURE: &str = "$cal_map_index_signature"; /// Get the schema runtime type use the schema name and pkgpath pub fn schema_runtime_type(name: &str, pkgpath: &str) -> String { @@ -43,6 +42,8 @@ impl ValueRef { config_keys: &[String], config_meta: &ValueRef, optional_mapping: &ValueRef, + args: Option, + kwargs: Option, ) -> Self { if self.is_dict() { Self::from(Value::schema_value(Box::new(SchemaValue { @@ -52,6 +53,8 @@ impl ValueRef { config_keys: config_keys.to_owned(), config_meta: config_meta.clone(), optional_mapping: optional_mapping.clone(), + args: args.unwrap_or(ValueRef::list(None)), + kwargs: kwargs.unwrap_or(ValueRef::dict(None)), }))) } else if self.is_schema() { self.clone() @@ -100,13 +103,38 @@ impl ValueRef { } } + /// Set of keys not in the schema. + pub fn keys_not_in_schema(&self, ty: &SchemaType, cal_order: &ValueRef) -> IndexSet { + let mut keys = IndexSet::new(); + if self.is_config() { + let config = self.as_dict_ref(); + for (key, _) in &config.values { + let no_such_attr = ty.attrs.get(key).is_none() + && cal_order.dict_get_value(key).is_none() + && !key.starts_with('_'); + let has_index_signature = ty.has_index_signature + || cal_order.dict_get_value(CAL_MAP_INDEX_SIGNATURE).is_some(); + if !has_index_signature && no_such_attr { + keys.insert(key.to_string()); + } + } + } + keys + } + + /// Check whether the config fits into the schema type. + #[inline] + pub fn is_fit_schema(&self, ty: &SchemaType, cal_order: &ValueRef) -> bool { + self.keys_not_in_schema(ty, cal_order).is_empty() + } + /// Check schema optional attributes. - pub fn schema_check_attr_optional(&self, recursive: bool) { + pub fn schema_check_attr_optional(&self, ctx: &mut Context, recursive: bool) { let binding = self.rc.borrow(); let attr_map = match &*binding { Value::schema_value(schema) => &schema.config.values, Value::dict_value(schema) => &schema.values, - _ => panic!("Invalid schema/dict value, got {}", self.type_str()), + _ => panic!("invalid schema or dict value, got {}", self.type_str()), }; let optional_mapping = self.schema_optional_mapping(); let optional_mapping_ref = optional_mapping.rc.borrow(); @@ -120,7 +148,6 @@ impl ValueRef { if is_required && value.is_none_or_undefined() { let filename = config_meta.get_by_key(CONFIG_META_FILENAME); let line = config_meta.get_by_key(CONFIG_META_LINE); - let ctx = Context::current_context_mut(); if let Some(filename) = filename { ctx.set_kcl_filename(&filename.as_str()); } @@ -137,9 +164,12 @@ impl ValueRef { // Recursive check schema values for every attributes. if recursive { for value in attr_map.values() { - if value.is_schema() { - value.schema_check_attr_optional(recursive); - } + // For composite type structures, we recursively check the schema within them. + walk_value_mut(value, &mut |value: &ValueRef| { + if value.is_schema() { + value.schema_check_attr_optional(ctx, true); + } + }) } } } @@ -150,22 +180,44 @@ impl ValueRef { } } - pub fn schema_default_settings(&mut self, config: &ValueRef, runtime_type: &str) { - let settings = self.dict_get_value(SCHEMA_SETTINGS_ATTR_NAME); - if settings.is_none() || (settings.is_some() && !settings.as_ref().unwrap().is_config()) { - let mut default_settings = ValueRef::dict(None); - default_settings - .dict_update_key_value(SETTINGS_OUTPUT_KEY, ValueRef::str(SETTINGS_OUTPUT_INLINE)); - default_settings - .dict_update_key_value(SETTINGS_SCHEMA_TYPE_KEY, ValueRef::str(runtime_type)); - self.dict_update_key_value(SCHEMA_SETTINGS_ATTR_NAME, default_settings); - } else { - settings - .unwrap() - .dict_update_key_value(SETTINGS_SCHEMA_TYPE_KEY, ValueRef::str(runtime_type)); + /// Set the schema instance value with arguments and keyword arguments. + pub fn set_schema_args(&mut self, args: &ValueRef, kwargs: &ValueRef) { + match &mut *self.rc.borrow_mut() { + Value::schema_value(ref mut schema) => { + schema.args = args.clone(); + schema.kwargs = kwargs.clone(); + } + _ => {} } - if let Some(v) = config.dict_get_value(SCHEMA_SETTINGS_ATTR_NAME) { - self.dict_update_key_value(SCHEMA_SETTINGS_ATTR_NAME, v); + } + + pub fn get_potential_schema_type(&self) -> Option { + match &*self.rc.borrow() { + Value::dict_value(ref dict) => dict.potential_schema.clone(), + Value::schema_value(ref schema) => schema.config.potential_schema.clone(), + _ => None, + } + } + + pub fn set_potential_schema_type(&mut self, runtime_type: &str) { + if !runtime_type.is_empty() { + match &mut *self.rc.borrow_mut() { + Value::dict_value(ref mut dict) => { + dict.potential_schema = Some(runtime_type.to_string()) + } + Value::schema_value(ref mut schema) => { + schema.config.potential_schema = Some(runtime_type.to_string()) + } + _ => {} + } + } + } + + pub fn has_potential_schema_type(&self) -> bool { + match &*self.rc.borrow() { + Value::dict_value(ref dict) => dict.potential_schema.is_some(), + Value::schema_value(ref schema) => schema.config.potential_schema.is_some(), + _ => false, } } @@ -208,6 +260,9 @@ impl ValueRef { let values = &mut schema.config.values; let ops = &mut schema.config.ops; let insert_indexs = &mut schema.config.insert_indexs; + // Reserve config keys for the schema update process. Issue: #785 + schema.config_keys = value.config_keys.clone(); + schema.config.potential_schema = value.config.potential_schema.clone(); for (k, v) in &value.config.values { let op = value .config @@ -230,18 +285,16 @@ mod test_value_schema { const TEST_SCHEMA_NAME: &str = "Data"; fn get_test_schema_value() -> ValueRef { - let config = ValueRef::dict(None); let mut schema = ValueRef::dict(None).dict_to_schema( TEST_SCHEMA_NAME, MAIN_PKG_PATH, &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); - schema.schema_default_settings( - &config, - &schema_runtime_type(TEST_SCHEMA_NAME, MAIN_PKG_PATH), - ); + schema.set_potential_schema_type(&schema_runtime_type(TEST_SCHEMA_NAME, MAIN_PKG_PATH)); schema } @@ -256,6 +309,8 @@ mod test_value_schema { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); assert!(schema.is_schema()); let schema = schema.dict_to_schema( @@ -264,6 +319,8 @@ mod test_value_schema { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); assert!(schema.is_schema()); let dict = schema.schema_to_dict(); @@ -272,6 +329,7 @@ mod test_value_schema { #[test] fn test_schema_check_attr_optional() { + let mut ctx = Context::new(); let dict = ValueRef::dict_str(&[("key", "value")]); let config_meta = ValueRef::dict(None); let optional_mapping = ValueRef::dict_bool(&[("key", true)]); @@ -281,14 +339,17 @@ mod test_value_schema { &[], &config_meta, &optional_mapping, + None, + None, ); - schema.schema_check_attr_optional(true); - schema.schema_check_attr_optional(false); + schema.schema_check_attr_optional(&mut ctx, true); + schema.schema_check_attr_optional(&mut ctx, false); } #[test] fn test_schema_check_attr_optional_invalid() { let err = std::panic::catch_unwind(|| { + let mut ctx = Context::new(); let dict = ValueRef::dict_str(&[("key", "value")]); let config_meta = ValueRef::dict(None); let optional_mapping = ValueRef::dict_bool(&[("another_key", false)]); @@ -298,23 +359,14 @@ mod test_value_schema { &[], &config_meta, &optional_mapping, + None, + None, ); - schema.schema_check_attr_optional(true); + schema.schema_check_attr_optional(&mut ctx, true); }); assert!(err.is_err()) } - #[test] - fn test_schema_default_settings() { - let schema = get_test_schema_value(); - let schema_settings = schema.get_by_key(SCHEMA_SETTINGS_ATTR_NAME).unwrap(); - let output_type = schema_settings - .get_by_key(SETTINGS_OUTPUT_KEY) - .unwrap() - .as_str(); - assert_eq!(output_type, SETTINGS_OUTPUT_INLINE); - } - #[test] fn test_schema_attr_map() { let mut schema = get_test_schema_value(); diff --git a/kclvm/runtime/src/value/val_str.rs b/kclvm/runtime/src/value/val_str.rs index b97591cda..f961adceb 100644 --- a/kclvm/runtime/src/value/val_str.rs +++ b/kclvm/runtime/src/value/val_str.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; use bstr::ByteSlice; diff --git a/kclvm/runtime/src/value/val_type.rs b/kclvm/runtime/src/value/val_type.rs index 52a628521..19f7098bd 100644 --- a/kclvm/runtime/src/value/val_type.rs +++ b/kclvm/runtime/src/value/val_type.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. extern crate fancy_regex; @@ -64,24 +64,17 @@ impl ValueRef { } /// Use the schema instance to build a new schema instance using the schema construct function -pub fn resolve_schema(schema: &ValueRef, keys: &[String]) -> ValueRef { +pub fn resolve_schema(ctx: &mut Context, schema: &ValueRef, keys: &[String]) -> ValueRef { if !schema.is_schema() { return schema.clone(); } let schema_value = schema.as_schema(); let schema_type_name = schema_runtime_type(&schema_value.name, &schema_value.pkgpath); - let ctx = Context::current_context_mut(); let now_meta_info = ctx.panic_info.clone(); - let has_schema_type = { - let all_schemas = ctx.all_schemas.borrow_mut(); - all_schemas.contains_key(&schema_type_name) - }; + let has_schema_type = { ctx.all_schemas.contains_key(&schema_type_name) }; if has_schema_type { - let schema_type = { - let all_schemas = ctx.all_schemas.borrow_mut(); - all_schemas.get(&schema_type_name).unwrap().clone() - }; - let schema_type = schema_type.as_function(); + let schema_type = { ctx.all_schemas.get(&schema_type_name).unwrap().clone() }; + let schema_type = schema_type.func.as_function(); let schema_fn_ptr = schema_type.fn_ptr; let keys = keys.iter().map(|v| v.as_str()).collect(); let config = schema.dict_get_entries(keys); @@ -94,54 +87,59 @@ pub fn resolve_schema(schema: &ValueRef, keys: &[String]) -> ValueRef { let config_meta_new = config_meta.clone(); let value = unsafe { let schema_fn: SchemaTypeFunc = transmute_copy(&schema_fn_ptr); - let ctx = kclvm_context_current(); - let cal_map = kclvm_value_Dict(); - let list = kclvm_value_List(); + let cal_map = kclvm_value_Dict(ctx as *mut Context); + let list = schema_value.args.clone().into_raw(ctx); // Schema function closures // is sub schema - kclvm_list_append(list, ValueRef::bool(false).into_raw()); + kclvm_list_append(list, ValueRef::bool(false).into_raw(ctx)); // config meta - kclvm_list_append(list, config_meta.into_raw()); + kclvm_list_append(list, config_meta.into_raw(ctx)); // schema - kclvm_list_append(list, config.into_raw()); + kclvm_list_append(list, config.into_raw(ctx)); // config - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // optional mapping - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // cal order map kclvm_list_append(list, cal_map); // backtrack level map - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // backtrack cache - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // record instance - kclvm_list_append(list, ValueRef::bool(false).into_raw()); + kclvm_list_append(list, ValueRef::bool(false).into_raw(ctx)); // instance pkgpath - kclvm_list_append(list, ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw()); - let dict = kclvm_value_Dict(); + kclvm_list_append( + list, + ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw(ctx), + ); + let dict = schema_value.kwargs.clone().into_raw(ctx); schema_fn(ctx, list, dict); - let list = kclvm_value_List(); + let list = schema_value.args.clone().into_raw(ctx); // Schema function closures // is sub schema - kclvm_list_append(list, ValueRef::bool(true).into_raw()); + kclvm_list_append(list, ValueRef::bool(true).into_raw(ctx)); // config meta - kclvm_list_append(list, config_meta_new.into_raw()); + kclvm_list_append(list, config_meta_new.into_raw(ctx)); // schema - kclvm_list_append(list, config_new.into_raw()); + kclvm_list_append(list, config_new.into_raw(ctx)); // config - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // optional mapping - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // cal order map kclvm_list_append(list, cal_map); // backtrack level map - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // backtrack cache - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // record instance - kclvm_list_append(list, ValueRef::bool(true).into_raw()); + kclvm_list_append(list, ValueRef::bool(true).into_raw(ctx)); // instance pkgpath - kclvm_list_append(list, ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw()); + kclvm_list_append( + list, + ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw(ctx), + ); let value = schema_fn(ctx, list, dict); ptr_as_ref(value) }; @@ -153,7 +151,11 @@ pub fn resolve_schema(schema: &ValueRef, keys: &[String]) -> ValueRef { } /// Type pack and check ValueRef with the expected type vector -pub fn type_pack_and_check(value: &ValueRef, expected_types: Vec<&str>) -> ValueRef { +pub fn type_pack_and_check( + ctx: &mut Context, + value: &ValueRef, + expected_types: Vec<&str>, +) -> ValueRef { if value.is_none_or_undefined() || expected_types.is_empty() { return value.clone(); } @@ -164,19 +166,19 @@ pub fn type_pack_and_check(value: &ValueRef, expected_types: Vec<&str>) -> Value let expected_type = &expected_types.join(" | ").replace('@', ""); for tpe in expected_types { let tpe = if !tpe.contains('.') { - let ctx = Context::current_context_mut(); match ctx.import_names.get(tpe) { Some(mapping) => mapping.keys().next().unwrap(), None => tpe, } } else { tpe - }; + } + .to_string(); if !is_schema { - converted_value = convert_collection_value(value, tpe); + converted_value = convert_collection_value(ctx, value, &tpe); } // Runtime type check - checked = check_type(&converted_value, tpe); + checked = check_type(&converted_value, &tpe); if checked { break; } @@ -188,34 +190,40 @@ pub fn type_pack_and_check(value: &ValueRef, expected_types: Vec<&str>) -> Value } /// Convert collection value including dict/list to the potential schema -pub fn convert_collection_value(value: &ValueRef, tpe: &str) -> ValueRef { +pub fn convert_collection_value(ctx: &mut Context, value: &ValueRef, tpe: &str) -> ValueRef { // May be a type alias. let tpe = if !tpe.contains('.') { - let ctx = Context::current_context_mut(); match ctx.import_names.get(tpe) { Some(mapping) => mapping.keys().next().unwrap(), None => tpe, } } else { tpe - }; + } + .to_string(); if tpe.is_empty() || tpe == KCL_TYPE_ANY { return value.clone(); } let is_collection = value.is_list() || value.is_dict(); - let invalid_match_dict = is_dict_type(tpe) && !value.is_dict(); - let invalid_match_list = is_list_type(tpe) && !value.is_list(); + let invalid_match_dict = is_dict_type(&tpe) && !value.is_dict(); + let invalid_match_list = is_list_type(&tpe) && !value.is_list(); let invalid_match = invalid_match_dict || invalid_match_list; - if !is_collection || invalid_match || is_type_union(tpe) { + if !is_collection || invalid_match { return value.clone(); } - if is_dict_type(tpe) { + // Convert a vlaue to union types e.g., {a: 1} => A | B + if is_type_union(&tpe) { + let types = split_type_union(&tpe); + convert_collection_value_with_union_types(ctx, value, &types) + } else if is_dict_type(&tpe) { //let (key_tpe, value_tpe) = separate_kv(tpe); - let (_, value_tpe) = separate_kv(&dereference_type(tpe)); + let (_, value_tpe) = separate_kv(&dereference_type(&tpe)); let mut expected_dict = ValueRef::dict(None); let dict_ref = value.as_dict_ref(); + expected_dict + .set_potential_schema_type(&dict_ref.potential_schema.clone().unwrap_or_default()); for (k, v) in &dict_ref.values { - let expected_value = convert_collection_value(v, &value_tpe); + let expected_value = convert_collection_value(ctx, v, &value_tpe); let op = dict_ref .ops .get(k) @@ -224,19 +232,18 @@ pub fn convert_collection_value(value: &ValueRef, tpe: &str) -> ValueRef { expected_dict.dict_update_entry(k, &expected_value, op, index) } expected_dict - } else if is_list_type(tpe) { - let expected_type = dereference_type(tpe); + } else if is_list_type(&tpe) { + let expected_type = dereference_type(&tpe); let mut expected_list = ValueRef::list(None); let list_ref = value.as_list_ref(); for v in &list_ref.values { - let expected_value = convert_collection_value(v, &expected_type); + let expected_value = convert_collection_value(ctx, v, &expected_type); expected_list.list_append(&expected_value) } expected_list - } else if BUILTIN_TYPES.contains(&tpe) { + } else if BUILTIN_TYPES.contains(&tpe.as_str()) { value.clone() } else { - let ctx = Context::current_context_mut(); let now_meta_info = ctx.panic_info.clone(); let mut schema_type_name = if tpe.contains('.') { tpe.to_string() @@ -272,67 +279,72 @@ pub fn convert_collection_value(value: &ValueRef, tpe: &str) -> ValueRef { } } } - let has_schema_type = { - let all_schemas = ctx.all_schemas.borrow_mut(); - all_schemas.contains_key(&schema_type_name) - }; + let has_schema_type = { ctx.all_schemas.contains_key(&schema_type_name) }; if has_schema_type { - let schema_type = { - let all_schemas = ctx.all_schemas.borrow_mut(); - all_schemas.get(&schema_type_name).unwrap().clone() - }; - let schema_type = schema_type.as_function(); - let schema_fn_ptr = schema_type.fn_ptr; + let schema_type = { ctx.all_schemas.get(&schema_type_name).unwrap().clone() }; + let schema_fn = schema_type.func.as_function(); + let schema_fn_ptr = schema_fn.fn_ptr; let value = unsafe { let schema_fn: SchemaTypeFunc = transmute_copy(&schema_fn_ptr); - let ctx = kclvm_context_current(); - let cal_order = kclvm_value_Dict(); - let list = kclvm_value_List(); + let cal_order = kclvm_value_Dict(ctx as *mut Context); + let list = kclvm_value_List(ctx as *mut Context); // Schema function closures // is_sub_schema - kclvm_list_append(list, ValueRef::bool(false).into_raw()); + kclvm_list_append(list, ValueRef::bool(false).into_raw(ctx)); // config meta - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // config - kclvm_list_append(list, value.clone().into_raw()); + kclvm_list_append(list, value.clone().into_raw(ctx)); // schema - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // optional mapping - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // cal order map kclvm_list_append(list, cal_order); // backtrack level map - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // backtrack cache - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // record instance - kclvm_list_append(list, ValueRef::bool(false).into_raw()); + kclvm_list_append(list, ValueRef::bool(false).into_raw(ctx)); // instance pkgpath - kclvm_list_append(list, ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw()); - let dict = kclvm_value_Dict(); + kclvm_list_append( + list, + ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw(ctx), + ); + let dict = kclvm_value_Dict(ctx as *mut Context); schema_fn(ctx, list, dict); - let list = kclvm_value_List(); + let list = kclvm_value_List(ctx as *mut Context); + + // Try convert the config to schema, if failed, return the config + if !value.is_fit_schema(&schema_type, ptr_as_ref(cal_order)) { + return value.clone(); + } + // Schema function closures // is_sub_schema - kclvm_list_append(list, ValueRef::bool(true).into_raw()); + kclvm_list_append(list, ValueRef::bool(true).into_raw(ctx)); // config meta - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // config - kclvm_list_append(list, value.clone().into_raw()); + kclvm_list_append(list, value.clone().into_raw(ctx)); // schema - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // optional mapping - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // cal order map kclvm_list_append(list, cal_order); // backtrack level map - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // backtrack cache - kclvm_list_append(list, kclvm_value_Dict()); + kclvm_list_append(list, kclvm_value_Dict(ctx as *mut Context)); // record instance - kclvm_list_append(list, ValueRef::bool(true).into_raw()); + kclvm_list_append(list, ValueRef::bool(true).into_raw(ctx)); // instance pkgpath - kclvm_list_append(list, ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw()); + kclvm_list_append( + list, + ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw(ctx), + ); let value = schema_fn(ctx, list, dict); ptr_as_ref(value) }; @@ -344,6 +356,26 @@ pub fn convert_collection_value(value: &ValueRef, tpe: &str) -> ValueRef { } } +/// Convert collection value including dict/list to the potential schema and return errors. +pub fn convert_collection_value_with_union_types( + ctx: &mut Context, + value: &ValueRef, + types: &[&str], +) -> ValueRef { + if value.is_schema() { + value.clone() + } else { + for tpe in types { + // Try match every type and convert the value, if matched, return the value. + let value = convert_collection_value(ctx, value, tpe); + if check_type(&value, tpe) { + return value; + } + } + value.clone() + } +} + /// check_type returns the value wether match the given the type string pub fn check_type(value: &ValueRef, tpe: &str) -> bool { if tpe.is_empty() || tpe == KCL_TYPE_ANY { @@ -391,9 +423,10 @@ pub fn check_type(value: &ValueRef, tpe: &str) -> bool { pub fn check_type_union(value: &ValueRef, tpe: &str) -> bool { let expected_types = split_type_union(tpe); if expected_types.len() <= 1 { - return false; + false + } else { + expected_types.iter().any(|tpe| check_type(value, tpe)) } - return expected_types.iter().any(|tpe| check_type(value, tpe)); } /// check_type_literal returns the value wether match the given the literal type string @@ -510,7 +543,7 @@ pub fn is_literal_type(tpe: &str) -> bool { pub fn is_dict_type(tpe: &str) -> bool { let count = tpe.chars().count(); count >= 2 - && matches!(tpe.chars().nth(0), Some('{')) + && matches!(tpe.chars().next(), Some('{')) && matches!(tpe.chars().nth(count - 1), Some('}')) } @@ -519,7 +552,7 @@ pub fn is_dict_type(tpe: &str) -> bool { pub fn is_list_type(tpe: &str) -> bool { let count = tpe.chars().count(); count >= 2 - && matches!(tpe.chars().nth(0), Some('[')) + && matches!(tpe.chars().next(), Some('[')) && matches!(tpe.chars().nth(count - 1), Some(']')) } @@ -578,8 +611,15 @@ fn is_number_multiplier_literal_type(tpe: &str) -> bool { } } +#[inline] +fn ty_str_strip(ty_str: &str) -> &str { + // Empty and tab chars. + let chars = " \t"; + ty_str.trim_matches(|c| chars.contains(c)) +} + /// separate_kv split the union type and do not split '|' in dict and list -/// e.g., "int|str" -> vec!["int", "str"] +/// e.g., "int|str" -> vec!["int", "str"], "int | str" -> vec!["int", "str"] pub fn split_type_union(tpe: &str) -> Vec<&str> { let mut i = 0; let mut s_index = 0; @@ -618,7 +658,8 @@ pub fn split_type_union(tpe: &str) -> Vec<&str> { i += 1; } types.push(&tpe[s_index..]); - types + // Remove empty and tab chars in the type string. + types.iter().map(|ty| ty_str_strip(ty)).collect() } /// separate_kv function separates key_type and value_type in the dictionary type strings, @@ -927,7 +968,9 @@ mod test_value_type { let cases = [ ("", vec![""]), ("str|int", vec!["str", "int"]), + ("str | int", vec!["str", "int"]), ("str|int|bool", vec!["str", "int", "bool"]), + ("str | int | bool", vec!["str", "int", "bool"]), ("str|[str]", vec!["str", "[str]"]), ("str|{str:int}", vec!["str", "{str:int}"]), ("A|B|C", vec!["A", "B", "C"]), diff --git a/kclvm/runtime/src/value/val_unary.rs b/kclvm/runtime/src/value/val_unary.rs index 582f0e2a5..4d964e5c7 100644 --- a/kclvm/runtime/src/value/val_unary.rs +++ b/kclvm/runtime/src/value/val_unary.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::*; diff --git a/kclvm/runtime/src/value/val_union.rs b/kclvm/runtime/src/value/val_union.rs index 09ffeda44..804ac8db3 100644 --- a/kclvm/runtime/src/value/val_union.rs +++ b/kclvm/runtime/src/value/val_union.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. use crate::unification::value_subsume; use crate::*; @@ -37,6 +37,7 @@ impl Default for UnionOptions { impl ValueRef { fn do_union( &mut self, + ctx: &mut Context, x: &Self, opts: &UnionOptions, union_context: &mut UnionContext, @@ -46,6 +47,8 @@ impl ValueRef { } let mut union_fn = |obj: &mut DictValue, delta: &DictValue| { + // Update potential schema type + obj.potential_schema = delta.potential_schema.clone(); // Update attribute map for (k, v) in &delta.ops { obj.ops.insert(k.clone(), v.clone()); @@ -54,6 +57,7 @@ impl ValueRef { for (k, v) in &delta.insert_indexs { obj.insert_indexs.insert(k.clone(), *v); } + // Update values for (k, v) in &delta.values { let operation = if let Some(op) = delta.ops.get(k) { op @@ -91,7 +95,7 @@ impl ValueRef { }; return; } - obj_value.union(v, false, opts, union_context); + obj_value.union(ctx, v, false, opts, union_context); if union_context.conflict { union_context.path_backtrace.push(k.clone()); return; @@ -151,6 +155,8 @@ impl ValueRef { let mut pkgpath: String = "".to_string(); let mut name: String = "".to_string(); let mut common_keys: Vec = vec![]; + let mut args = None; + let mut kwargs = None; let mut valid = true; match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::list_value(obj), Value::list_value(delta)) => { @@ -166,7 +172,13 @@ impl ValueRef { if idx >= obj_len { obj.values.push(delta.values[idx].clone()); } else if idx < delta_len { - obj.values[idx].union(&delta.values[idx], false, opts, union_context); + obj.values[idx].union( + ctx, + &delta.values[idx], + false, + opts, + union_context, + ); if union_context.conflict { union_context.path_backtrace.push(format!("list[{idx}]")); } @@ -183,6 +195,8 @@ impl ValueRef { common_keys = obj.config_keys.clone(); let mut other_keys: Vec = delta.values.keys().cloned().collect(); common_keys.append(&mut other_keys); + args = Some(obj.args.clone()); + kwargs = Some(obj.kwargs.clone()); union_schema = true; } (Value::schema_value(obj), Value::schema_value(delta)) => { @@ -194,6 +208,8 @@ impl ValueRef { common_keys = obj.config_keys.clone(); let mut other_keys: Vec = delta.config_keys.clone(); common_keys.append(&mut other_keys); + args = Some(delta.args.clone()); + kwargs = Some(delta.kwargs.clone()); union_schema = true; } (Value::dict_value(obj), Value::schema_value(delta)) => { @@ -204,6 +220,8 @@ impl ValueRef { common_keys = delta.config_keys.clone(); let mut other_keys: Vec = obj.values.keys().cloned().collect(); common_keys.append(&mut other_keys); + args = Some(delta.args.clone()); + kwargs = Some(delta.kwargs.clone()); union_schema = true; } _ => valid = false, @@ -219,17 +237,27 @@ impl ValueRef { return self.clone(); } if union_schema { - let result = self.clone(); - let optional_mapping = self.schema_optional_mapping(); + // Override schema arguments and keyword arguments. + let mut result = self.clone(); + if let (Some(args), Some(kwargs)) = (&args, &kwargs) { + result.set_schema_args(args, kwargs); + } + let optional_mapping = if self.is_schema() { + self.schema_optional_mapping() + } else { + x.schema_optional_mapping() + }; let schema = result.dict_to_schema( name.as_str(), pkgpath.as_str(), &common_keys, &x.schema_config_meta(), &optional_mapping, + args, + kwargs, ); if opts.config_resolve { - *self = resolve_schema(&schema, &common_keys); + *self = resolve_schema(ctx, &schema, &common_keys); } else { *self = schema; } @@ -238,6 +266,7 @@ impl ValueRef { } fn union( &mut self, + ctx: &mut Context, x: &Self, or_mode: bool, opts: &UnionOptions, @@ -251,7 +280,7 @@ impl ValueRef { return self.clone(); } if self.is_list_or_config() && x.is_list_or_config() { - self.do_union(x, opts, union_context); + self.do_union(ctx, x, opts, union_context); } else if or_mode { if let (Value::int_value(a), Value::int_value(b)) = (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) @@ -270,9 +299,15 @@ impl ValueRef { self.clone() } - pub fn union_entry(&mut self, x: &Self, or_mode: bool, opts: &UnionOptions) -> Self { + pub fn union_entry( + &mut self, + ctx: &mut Context, + x: &Self, + or_mode: bool, + opts: &UnionOptions, + ) -> Self { let mut union_context = UnionContext::default(); - let ret = self.union(x, or_mode, opts, &mut union_context); + let ret = self.union(ctx, x, or_mode, opts, &mut union_context); if union_context.conflict { union_context.path_backtrace.reverse(); let conflict_key = union_context.path_backtrace.last().unwrap(); @@ -317,21 +352,23 @@ mod test_value_union { #[test] fn test_list_union() { + let mut ctx = Context::new(); let cases = [ ("[0]", "[1, 2]", "[1, 2]"), ("[1, 2]", "[2]", "[2, 2]"), ("[0, 0]", "[1, 2]", "[1, 2]"), ]; for (left, right, expected) in cases { - let left_value = ValueRef::from_json(left).unwrap(); - let right_value = ValueRef::from_json(right).unwrap(); - let value = left_value.bin_bit_or(&right_value); + let left_value = ValueRef::from_json(&mut ctx, left).unwrap(); + let right_value = ValueRef::from_json(&mut ctx, right).unwrap(); + let value = left_value.bin_bit_or(&mut ctx, &right_value); assert_eq!(value.to_json_string(), expected); } } #[test] fn test_dict_union() { + let mut ctx = Context::new(); let cases = [ ( vec![("key", "value", ConfigEntryOperationKind::Union, -1)], @@ -392,7 +429,7 @@ mod test_value_union { for (key, val, op, index) in right_entries { right_value.dict_update_entry(key, &ValueRef::str(val), &op, &index); } - let result = left_value.bin_bit_or(&right_value); + let result = left_value.bin_bit_or(&mut ctx, &right_value); for (key, val, op, index) in expected { let result_dict = result.as_dict_ref(); let result_val = result_dict.values.get(key).unwrap().as_str(); @@ -406,6 +443,7 @@ mod test_value_union { } #[test] fn test_dict_union_insert() { + let mut ctx = Context::new(); let cases = [ ( vec![("key", vec![0, 1], ConfigEntryOperationKind::Override, -1)], @@ -442,7 +480,7 @@ mod test_value_union { &index, ); } - let result = left_value.bin_bit_or(&right_value); + let result = left_value.bin_bit_or(&mut ctx, &right_value); for (key, val, op, index) in expected { let result_dict = result.as_dict_ref(); let result_val = result_dict.values.get(key).unwrap(); @@ -457,6 +495,7 @@ mod test_value_union { #[test] fn test_dict_union_same_ref() { + let mut ctx = Context::new(); let cases = [ ( vec![("key1", "value", ConfigEntryOperationKind::Union, -1)], @@ -536,7 +575,7 @@ mod test_value_union { left_value.dict_update_entry(key, &both_val, &op, &index); left_value.dict_update_entry(key, &both_val, &op, &index); } - let result = left_value.bin_bit_or(&right_value); + let result = left_value.bin_bit_or(&mut ctx, &right_value); for (key, val, op, index) in expected { let result_dict = result.as_dict_ref(); let result_val = result_dict.values.get(key).unwrap().as_str(); @@ -637,9 +676,10 @@ try operator '=' to override the attribute, like: ]; for (left, right, expected) in cases { assert_panic(expected, || { - let left_value = ValueRef::from_json(left).unwrap(); - let right_value = ValueRef::from_json(right).unwrap(); - left_value.bin_bit_or(&right_value); + let mut ctx = Context::new(); + let left_value = ValueRef::from_json(&mut ctx, left).unwrap(); + let right_value = ValueRef::from_json(&mut ctx, right).unwrap(); + left_value.bin_bit_or(&mut ctx, &right_value); }); } std::panic::set_hook(pre_hook); diff --git a/kclvm/runtime/src/value/val_yaml.rs b/kclvm/runtime/src/value/val_yaml.rs index 81eaf8896..2125010a0 100644 --- a/kclvm/runtime/src/value/val_yaml.rs +++ b/kclvm/runtime/src/value/val_yaml.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. extern crate serde_json; extern crate serde_yaml; @@ -45,20 +45,20 @@ impl Default for YamlEncodeOptions { impl ValueRef { /// Decode a yaml single document string to a ValueRef. /// Returns [serde_yaml::Error] when decoding fails. - pub fn from_yaml(s: &str) -> Result { + pub fn from_yaml(ctx: &mut Context, s: &str) -> Result { // We use JsonValue to implement the KCL universal serialization object. let json_value: JsonValue = serde_yaml::from_str(s)?; - Ok(Self::from_json(serde_json::to_string(&json_value).unwrap().as_ref()).unwrap()) + Ok(Self::from_json(ctx, serde_json::to_string(&json_value).unwrap().as_ref()).unwrap()) } /// Decode yaml stream string that contains `---` to a ValueRef. /// Returns [serde_yaml::Error] when decoding fails. - pub fn from_yaml_stream(s: &str) -> Result { + pub fn from_yaml_stream(ctx: &mut Context, s: &str) -> Result { let documents = serde_yaml::Deserializer::from_str(s); let mut result = ValueRef::list_value(None); for document in documents { let json_value: JsonValue = JsonValue::deserialize(document)?; - result.list_append(&ValueRef::parse_json(&json_value)) + result.list_append(&ValueRef::parse_json(ctx, &json_value)) } if result.is_empty() { // Empty result returns a empty dict. @@ -100,7 +100,7 @@ impl ValueRef { ignore_private: opt.ignore_private, ignore_none: opt.ignore_none, }; - let json = self.to_json_string_with_option(&json_opt); + let json = self.to_json_string_with_options(&json_opt); let yaml_value: serde_yaml::Value = serde_json::from_str(json.as_ref()).unwrap(); match serde_yaml::to_string(&yaml_value) { Ok(s) => { @@ -118,6 +118,7 @@ mod test_value_yaml { #[test] fn test_value_from_yaml() { + let mut ctx = Context::new(); let cases = [ ("a: 1\n", ValueRef::dict(Some(&[("a", &ValueRef::int(1))]))), ( @@ -142,13 +143,14 @@ mod test_value_yaml { ), ]; for (yaml_str, expected) in cases { - let result = ValueRef::from_yaml(yaml_str); + let result = ValueRef::from_yaml(&mut ctx, yaml_str); assert_eq!(result.unwrap(), expected); } } #[test] fn test_value_from_yaml_fail() { + let mut ctx = Context::new(); let cases = [ ( "a: 1\n b: 2\nc: 3", @@ -156,17 +158,18 @@ mod test_value_yaml { ), ( "a:\n- 1\n -2\n-3", - "while parsing a block mapping, did not find expected key at line 4 column 1", + "could not find expected ':' at line 5 column 1, while scanning a simple key at line 4 column 1", ), ]; for (yaml_str, expected) in cases { - let result = ValueRef::from_yaml(yaml_str); + let result = ValueRef::from_yaml(&mut ctx, yaml_str); assert_eq!(result.err().unwrap().to_string(), expected); } } #[test] fn test_value_from_yaml_stream() { + let mut ctx = Context::new(); let cases = [ ("a: 1\n", ValueRef::dict(Some(&[("a", &ValueRef::int(1))]))), ( @@ -178,13 +181,14 @@ mod test_value_yaml { ), ]; for (yaml_str, expected) in cases { - let result = ValueRef::from_yaml_stream(yaml_str); + let result = ValueRef::from_yaml_stream(&mut ctx, yaml_str); assert_eq!(result.unwrap(), expected); } } #[test] fn test_value_from_yaml_stream_fail() { + let mut ctx = Context::new(); let cases = [ ( "a: 1\n---\na: 1\n b: 2\nc: 3", @@ -192,11 +196,11 @@ mod test_value_yaml { ), ( "b:3\n---\na:\n- 1\n -2\n-3", - "while parsing a block mapping, did not find expected key at line 6 column 1", + "could not find expected ':' at line 7 column 1, while scanning a simple key at line 6 column 1", ), ]; for (yaml_str, expected) in cases { - let result = ValueRef::from_yaml_stream(yaml_str); + let result = ValueRef::from_yaml_stream(&mut ctx, yaml_str); assert_eq!(result.err().unwrap().to_string(), expected); } } @@ -214,7 +218,7 @@ mod test_value_yaml { ("a", &ValueRef::list_int(&[1, 2, 3])), ("b", &ValueRef::str("s")), ])), - "a:\n - 1\n - 2\n - 3\nb: s\n", + "a:\n- 1\n- 2\n- 3\nb: s\n", ), ]; for (value, expected) in cases { @@ -271,7 +275,7 @@ mod test_value_yaml { ("b", &ValueRef::list_int(&[1, 2, 3])), ("a", &ValueRef::str("s")), ])), - "a: s\nb:\n - 1\n - 2\n - 3\n", + "a: s\nb:\n- 1\n- 2\n- 3\n", YamlEncodeOptions { sort_keys: true, ignore_private: false, diff --git a/kclvm/runtime/src/value/walker.rs b/kclvm/runtime/src/value/walker.rs new file mode 100644 index 000000000..f3f233580 --- /dev/null +++ b/kclvm/runtime/src/value/walker.rs @@ -0,0 +1,47 @@ +use crate::{Value, ValueRef}; + +/// Walk the value recursively and deal the type using the `walk_fn` +pub fn walk_value(val: &ValueRef, walk_fn: &impl Fn(&ValueRef)) { + walk_fn(val); + match &*val.rc.borrow() { + Value::list_value(list_value) => { + for v in &list_value.values { + walk_value(v, walk_fn); + } + } + Value::dict_value(dict_value) => { + for (_, v) in &dict_value.values { + walk_value(v, walk_fn); + } + } + Value::schema_value(schema_value) => { + for (_, v) in &schema_value.config.values { + walk_value(v, walk_fn); + } + } + _ => {} + } +} + +/// Walk the value recursively and mutably and deal the type using the `walk_fn` +pub fn walk_value_mut(val: &ValueRef, walk_fn: &mut impl FnMut(&ValueRef)) { + walk_fn(val); + match &*val.rc.borrow() { + Value::list_value(list_value) => { + for v in &list_value.values { + walk_value_mut(v, walk_fn); + } + } + Value::dict_value(dict_value) => { + for (_, v) in &dict_value.values { + walk_value_mut(v, walk_fn); + } + } + Value::schema_value(schema_value) => { + for (_, v) in &schema_value.config.values { + walk_value_mut(v, walk_fn); + } + } + _ => {} + } +} diff --git a/kclvm/runtime/src/yaml/mod.rs b/kclvm/runtime/src/yaml/mod.rs index a6dcac071..acc00e75f 100644 --- a/kclvm/runtime/src/yaml/mod.rs +++ b/kclvm/runtime/src/yaml/mod.rs @@ -1,4 +1,187 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. +use crate::*; -pub mod yaml; -pub use self::yaml::*; +pub const YAML_STREAM_SEP: &str = "\n---\n"; +pub const JSON_STREAM_SEP: &str = "\n"; + +/// encode(data, sort_keys=False, ignore_private=False, ignore_none=False) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_encode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + + if let Some(arg0) = args.arg_i(0) { + let s = ValueRef::str( + arg0.to_yaml_string_with_options(&kwargs_to_opts(kwargs)) + .as_ref(), + ); + return s.into_raw(mut_ptr_as_ref(ctx)); + } + panic!("encode_all() missing 1 required positional argument: 'data'") +} + +/// encode_all(data, sort_keys=False, ignore_private=False, ignore_none=False) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_encode_all( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + + if let Some(arg0) = args.arg_i(0) { + let opts = kwargs_to_opts(kwargs); + let results = arg0 + .as_list_ref() + .values + .iter() + .map(|r| r.to_yaml_string_with_options(&opts)) + .collect::>(); + let s = ValueRef::str(&results.join(YAML_STREAM_SEP)); + return s.into_raw(mut_ptr_as_ref(ctx)); + } + panic!("encode() missing 1 required positional argument: 'data'") +} + +/// decode(value) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_decode( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + let ctx = mut_ptr_as_ref(ctx); + if let Some(arg0) = args.arg_i(0) { + match ValueRef::from_yaml(ctx, arg0.as_str().as_ref()) { + Ok(x) => return x.into_raw(ctx), + Err(err) => panic!("{}", err), + } + } + panic!("decode() missing 1 required positional argument: 'value'") +} + +/// decode_all(value) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_decode_all( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + let ctx = mut_ptr_as_ref(ctx); + if let Some(arg0) = args.arg_i(0) { + match ValueRef::from_yaml_stream(ctx, arg0.as_str().as_ref()) { + Ok(x) => return x.into_raw(ctx), + Err(err) => panic!("{}", err), + } + } + panic!("decode_all() missing 1 required positional argument: 'value'") +} + +/// dump_to_file(data, sort_keys=False, ignore_private=False, ignore_none=False) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_dump_to_file( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + let data = args.arg_i(0).or(kwargs.get_by_key("data")); + let filename = args.arg_i(1).or(kwargs.get_by_key("filename")); + match (data, filename) { + (Some(data), Some(filename)) => { + let filename = filename.as_str(); + + let yaml = data.to_yaml_string_with_options(&kwargs_to_opts(kwargs)); + std::fs::write(&filename, yaml) + .unwrap_or_else(|e| panic!("Unable to write file '{}': {}", filename, e)); + kclvm_value_Undefined(ctx) + } + _ => { + panic!("dump_to_file() missing 2 required positional arguments: 'data' and 'filename'") + } + } +} + +/// dump_all_to_file(data, sort_keys=False, ignore_private=False, ignore_none=False) +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_dump_all_to_file( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + + let data = args.arg_i(0).or(kwargs.get_by_key("data")); + let filename = args.arg_i(1).or(kwargs.get_by_key("filename")); + match (data, filename) { + (Some(data), Some(filename)) => { + let filename = filename.as_str(); + let opts = kwargs_to_opts(kwargs); + let results = data + .as_list_ref() + .values + .iter() + .map(|r| r.to_yaml_string_with_options(&opts)) + .collect::>(); + + std::fs::write(filename, results.join(YAML_STREAM_SEP)).expect("Unable to write file"); + kclvm_value_Undefined(ctx) + } + _ => { + panic!( + "dump_all_to_file() missing 2 required positional arguments: 'data' and 'filename'" + ) + } + } +} + +/// validate(value: str) -> bool +#[no_mangle] +#[runtime_fn] +pub extern "C" fn kclvm_yaml_validate( + ctx: *mut kclvm_context_t, + args: *const kclvm_value_ref_t, + _kwargs: *const kclvm_value_ref_t, +) -> *const kclvm_value_ref_t { + let args = ptr_as_ref(args); + + let ctx = mut_ptr_as_ref(ctx); + if let Some(arg0) = args.arg_i(0) { + match ValueRef::from_yaml_stream(ctx, arg0.as_str().as_ref()) { + Ok(_) => return kclvm_value_True(ctx), + Err(_) => return kclvm_value_False(ctx), + } + } + panic!("validate() missing 1 required positional argument: 'value'") +} + +fn kwargs_to_opts(kwargs: &ValueRef) -> YamlEncodeOptions { + let mut opts = YamlEncodeOptions::default(); + if let Some(sort_keys) = kwargs.kwarg_bool("sort_keys", None) { + opts.sort_keys = sort_keys; + } + if let Some(ignore_private) = kwargs.kwarg_bool("ignore_private", None) { + opts.ignore_private = ignore_private; + } + if let Some(ignore_none) = kwargs.kwarg_bool("ignore_none", None) { + opts.ignore_none = ignore_none; + } + opts +} diff --git a/kclvm/runtime/src/yaml/yaml.rs b/kclvm/runtime/src/yaml/yaml.rs deleted file mode 100644 index 4dbb54165..000000000 --- a/kclvm/runtime/src/yaml/yaml.rs +++ /dev/null @@ -1,77 +0,0 @@ -//! KCL yaml system module -//! -//! Copyright 2021 The KCL Authors. All rights reserved. -#![allow(clippy::missing_safety_doc)] - -use crate::*; - -#[allow(non_camel_case_types)] -type kclvm_value_ref_t = ValueRef; - -// def KMANGLED_encode(data, sort_keys=False, ignore_private=False, ignore_none=False): - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_yaml_encode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - let kwargs = ptr_as_ref(kwargs); - - let mut opt = YamlEncodeOptions::default(); - if let Some(sort_keys) = kwargs.kwarg_bool("sort_keys", None) { - opt.sort_keys = sort_keys; - } - if let Some(ignore_private) = kwargs.kwarg_bool("ignore_private", None) { - opt.ignore_private = ignore_private; - } - if let Some(ignore_none) = kwargs.kwarg_bool("ignore_none", None) { - opt.ignore_none = ignore_none; - } - - if let Some(arg0) = args.arg_i(0) { - let s = ValueRef::str(arg0.to_yaml_string_with_options(&opt).as_ref()); - return s.into_raw(); - } - panic!("encode() missing 1 required positional argument: 'value'") -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_yaml_decode( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(arg0) = args.arg_i(0) { - match ValueRef::from_yaml(arg0.as_str().as_ref()) { - Ok(x) => return x.into_raw(), - Err(err) => panic!("{}", err), - } - } - panic!("decode() missing 1 required positional argument: 'value'") -} - -#[no_mangle] -#[runtime_fn] -pub unsafe extern "C" fn kclvm_yaml_dump_to_file( - _ctx: *mut kclvm_context_t, - args: *const kclvm_value_ref_t, - _kwargs: *const kclvm_value_ref_t, -) -> *const kclvm_value_ref_t { - let args = ptr_as_ref(args); - - if let Some(data) = args.arg_i(0) { - if let Some(filename) = args.arg_i(0) { - let yaml = data.to_yaml_string(); - let filename = filename.as_str(); - - std::fs::write(filename, yaml).expect("Unable to write file"); - } - } - panic!("dump_to_file() missing 2 required positional arguments: 'data' and 'filename'") -} diff --git a/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go b/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go index d1d2c9e11..fdc4ad5fe 100644 --- a/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go +++ b/kclvm/runtime/tools/kclvm-runtime-gen-api/main.go @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. package main @@ -205,7 +205,7 @@ func LoadAllApiSpec(root string) []ApiSpec { const tmplCApi = ` {{$specList := .}} -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -281,7 +281,7 @@ enum kclvm_kind_t { const tmplLLApi = ` {{$specList := .}} -; Copyright 2021 The KCL Authors. All rights reserved. +; Copyright The KCL Authors. All rights reserved. ; Auto generated, DONOT EDIT!!! @@ -294,7 +294,7 @@ const tmplLLApi = ` {{end}} define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* %_b) { - call %kclvm_value_ref_t*() @kclvm_value_None() + call %kclvm_value_ref_t* @kclvm_value_None(%kclvm_context_t* %_b) ret void } ` @@ -304,7 +304,7 @@ define void @__kcl_keep_link_runtime(%kclvm_value_ref_t* %_a, %kclvm_context_t* const tmplRustEnum = ` {{$specList := .}} -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! @@ -356,7 +356,7 @@ impl ApiFunc { const tmplRustAddr = ` {{$specList := .}} -// Copyright 2021 The KCL Authors. All rights reserved. +// Copyright The KCL Authors. All rights reserved. // Auto generated, DONOT EDIT!!! diff --git a/kclvm/runtime/tools/kclvm-runtime-gen-err-type/Makefile b/kclvm/runtime/tools/kclvm-runtime-gen-err-type/Makefile deleted file mode 100644 index 84bc7fbe3..000000000 --- a/kclvm/runtime/tools/kclvm-runtime-gen-err-type/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2021 The KCL Authors. All rights reserved. - -default: - kclvm ./main.py > ../../src/api/err_type.rs - -clean: diff --git a/kclvm/runtime/tools/kclvm-runtime-gen-err-type/main.py b/kclvm/runtime/tools/kclvm-runtime-gen-err-type/main.py deleted file mode 100644 index c527cdbf0..000000000 --- a/kclvm/runtime/tools/kclvm-runtime-gen-err-type/main.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2021 The KCL Authors. All rights reserved. - -import kclvm.kcl.error as kcl_error - -# enum -> code -# kcl_error.ErrType.EvaluationError_TYPE.value[0] - -# code -> type -# x = kcl_error.ErrType((6,)) - -print( - """// Copyright 2021 The KCL Authors. All rights reserved. - -// Auto generated, DONOT EDIT!!! - -// python: kclvm.kcl.error.ErrType - -#[derive(Copy, Clone)] -#[allow(non_camel_case_types)] -pub enum ErrType {""" -) -for x in kcl_error.ErrType: - print(f" {x.name} = {x.value[0]},") -print("}") diff --git a/kclvm/sema/Cargo.toml b/kclvm/sema/Cargo.toml index cb93c4971..d59d3e0a1 100644 --- a/kclvm/sema/Cargo.toml +++ b/kclvm/sema/Cargo.toml @@ -1,11 +1,14 @@ [package] name = "kclvm-sema" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +serde_json = "1.0" +serde = { version = "1", features = ["derive"] } +generational-arena = "0.2.9" phf = { version = "0.9", features = ["macros"] } ahash = "0.7.2" indexmap = "1.0" @@ -17,20 +20,25 @@ unicode_names2 = "0.4" petgraph = "0.6.0" anyhow = "1.0" regex = "1.7.0" -kclvm-ast = {path = "../ast"} -kclvm-runtime = {path = "../runtime"} -kclvm-error = {path = "../error"} -kclvm-span = {path = "../span"} -compiler_base_span = {path = "../../compiler_base/span", version = "0.0.2"} -compiler_base_session = {path = "../../compiler_base/session"} +lazy_static = "1.4.0" +pcre2 = "*" + +kclvm-ast = { path = "../ast" } +kclvm-ast-pretty = { path = "../ast_pretty" } +kclvm-runtime = { path = "../runtime" } +kclvm-error = { path = "../error" } +kclvm-span = { path = "../span" } +kclvm-utils ={ path = "../utils" } +compiler_base_span = { path = "../../compiler_base/span", version = "0.0.2" } +compiler_base_session = { path = "../../compiler_base/session" } compiler_base_macros = "0.0.1" -compiler_base_error = "0.0.8" +compiler_base_error = { path = "../../compiler_base/error" } +suggestions = "0.1.1" [dev-dependencies] -kclvm-parser = {path = "../parser"} +kclvm-parser = { path = "../parser" } criterion = "0.3" [[bench]] name = "my_benchmark" harness = false - diff --git a/kclvm/sema/benches/my_benchmark.rs b/kclvm/sema/benches/my_benchmark.rs index aad5d526e..309d22094 100644 --- a/kclvm/sema/benches/my_benchmark.rs +++ b/kclvm/sema/benches/my_benchmark.rs @@ -1,19 +1,19 @@ -use std::rc::Rc; - use criterion::{criterion_group, criterion_main, Criterion}; use kclvm_sema::ty::*; +use std::sync::Arc; + pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("sup", |b| { b.iter(|| { let types = vec![ - Rc::new(Type::int_lit(1)), - Rc::new(Type::INT), - Rc::new(Type::union(&[ - Rc::new(Type::STR), - Rc::new(Type::dict(Rc::new(Type::STR), Rc::new(Type::STR))), + Arc::new(Type::int_lit(1)), + Arc::new(Type::INT), + Arc::new(Type::union(&[ + Arc::new(Type::STR), + Arc::new(Type::dict(Arc::new(Type::STR), Arc::new(Type::STR))), ])), - Rc::new(Type::dict(Rc::new(Type::ANY), Rc::new(Type::ANY))), + Arc::new(Type::dict(Arc::new(Type::ANY), Arc::new(Type::ANY))), ]; sup(&types); }) diff --git a/kclvm/sema/src/advanced_resolver/mod.rs b/kclvm/sema/src/advanced_resolver/mod.rs new file mode 100644 index 000000000..0f8dbc354 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/mod.rs @@ -0,0 +1,1413 @@ +/* + + core::Namer basic_resolver + │ │ + ▼ ▼ + ┌─────────────────────┐ ┌─────────────────────┐ + │ core::GlobalState │ │ ast_node_type_map │ + └─────────────────────┘ └─────────────────────┘ + │ │ + ▼ ▼ + ┌──────────────────────────────────────────────────────────────────────────────┐ + │ advanced_resolver │ + ├──────────────────────────────────────────────────────────────────────────────┤ + │ ┌─────────────────┐ │ + │ │ ast::Expression │ │ + │ └─────────────────┘ │ + │ │ │ + │ │ resolve_local_value │ + │ ▼ │ + │ ┌─────────────────┐ │ + │ │ ast::Expression │ │ + │ └─────────────────┘ │ + │ │ │ + │ │ resolve_symbol_ref (map Expression to DefinitionSymbols) | + │ ▼ │ + │ ┌─────────────────┐ │ + │ │ ast::Expression │ │ + │ └─────────────────┘ │ + └──────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ build_sema_db (collect symbol locs and analyse scope) + ┌─────────────────────┐ + │ core::GlobalState │ + └─────────────────────┘ +*/ + +use indexmap::IndexSet; +use kclvm_error::Position; + +use crate::{ + core::{ + global_state::GlobalState, + package::ModuleInfo, + scope::{LocalSymbolScope, LocalSymbolScopeKind, RootSymbolScope, ScopeKind, ScopeRef}, + symbol::SymbolRef, + }, + resolver::scope::{NodeKey, NodeTyMap}, +}; + +use kclvm_ast::ast::AstIndex; +use kclvm_ast::ast::Program; +use kclvm_ast::walker::MutSelfTypedResultWalker; +mod node; + +/// AdvancedResolver mainly does two tasks: +/// 1: Traverse AST to parse LocalSymbol and store it in GlobalState, while storing the parsed type in Symbol +/// 2: Establish a mapping between expressions and SymbolRef, specifically injecting symbol information into AST +/// +/// After the work of the advanced resolver is completed, the GlobalState will build the whole semantic database, +/// so that toolchain can query semantic information about the AST +pub struct AdvancedResolver<'ctx> { + pub(crate) ctx: Context<'ctx>, + pub(crate) gs: GlobalState, +} + +pub struct Context<'ctx> { + pub program: &'ctx Program, + node_ty_map: NodeTyMap, + scopes: Vec, + current_pkgpath: Option, + current_filename: Option, + current_schema_symbol: Option, + start_pos: Position, + end_pos: Position, + cur_node: AstIndex, + + // whether the identifier currently being visited may be a definition + // it will only be true when visiting a l-value or parameter, + // which means advanced resolver will will create the corresponding + // ValueSymbol instead of an UnresolvedSymbol + maybe_def: bool, +} + +impl<'ctx> Context<'ctx> { + pub fn get_node_key(&self, id: &AstIndex) -> NodeKey { + NodeKey { + pkgpath: self.current_pkgpath.clone().unwrap(), + id: id.clone(), + } + } +} + +impl<'ctx> AdvancedResolver<'ctx> { + pub fn resolve_program( + program: &'ctx Program, + gs: GlobalState, + node_ty_map: NodeTyMap, + ) -> GlobalState { + let mut advanced_resolver = Self { + gs, + ctx: Context { + program, + node_ty_map, + scopes: vec![], + current_filename: None, + current_pkgpath: None, + current_schema_symbol: None, + start_pos: Position::dummy_pos(), + end_pos: Position::dummy_pos(), + cur_node: AstIndex::default(), + maybe_def: false, + }, + }; + + for (name, modules) in advanced_resolver.ctx.program.pkgs.iter() { + advanced_resolver.ctx.current_pkgpath = Some(name.clone()); + if let Some(pkg_info) = advanced_resolver.gs.get_packages().get_package_info(name) { + if modules.is_empty() { + continue; + } + if !advanced_resolver.ctx.scopes.is_empty() { + advanced_resolver.ctx.scopes.clear(); + } + advanced_resolver.enter_root_scope( + name.clone(), + pkg_info.pkg_filepath.clone(), + pkg_info.kfile_paths.clone(), + ); + for module in modules.iter() { + advanced_resolver.ctx.current_filename = Some(module.filename.clone()); + advanced_resolver.walk_module(module); + } + advanced_resolver.leave_scope() + } + } + + advanced_resolver.gs.build_sema_db(); + advanced_resolver.gs + } + + fn enter_root_scope( + &mut self, + pkgpath: String, + filename: String, + kfile_paths: IndexSet, + ) { + let package_ref = self + .gs + .get_symbols_mut() + .get_symbol_by_fully_qualified_name(&pkgpath) + .unwrap(); + + let root_scope = RootSymbolScope::new(pkgpath, filename, package_ref, kfile_paths); + let scope_ref = self.gs.get_scopes_mut().alloc_root_scope(root_scope); + self.ctx.scopes.push(scope_ref); + } + + fn enter_local_scope( + &mut self, + filepath: &str, + start: Position, + end: Position, + kind: LocalSymbolScopeKind, + ) { + let parent = *self.ctx.scopes.last().unwrap(); + let local_scope = LocalSymbolScope::new(parent, start, end, kind); + let scope_ref = self.gs.get_scopes_mut().alloc_local_scope(local_scope); + + match parent.get_kind() { + ScopeKind::Root => { + self.gs + .get_scopes_mut() + .roots + .get_mut(parent.get_id()) + .unwrap() + .add_child(filepath, scope_ref); + } + ScopeKind::Local => { + self.gs + .get_scopes_mut() + .locals + .get_mut(parent.get_id()) + .unwrap() + .add_child(scope_ref); + } + } + self.ctx.scopes.push(scope_ref); + } + + fn leave_scope(&mut self) { + self.ctx.scopes.pop(); + } + + fn get_current_module_info(&self) -> Option<&ModuleInfo> { + self.gs + .get_packages() + .get_module_info(self.ctx.current_filename.as_ref()?) + } +} + +#[cfg(test)] +mod tests { + use crate::advanced_resolver::AdvancedResolver; + use crate::core::global_state::GlobalState; + use crate::core::symbol::SymbolKind; + use crate::namer::Namer; + use crate::resolver; + + use kclvm_error::Position; + use kclvm_parser::load_program; + use kclvm_parser::ParseSession; + use std::path::Path; + use std::sync::Arc; + + #[cfg(not(target_os = "windows"))] + fn adjust_canonicalization>(p: P) -> String { + p.as_ref().display().to_string() + } + + #[cfg(target_os = "windows")] + fn adjust_canonicalization>(p: P) -> String { + const VERBATIM_PREFIX: &str = r#"\\?\"#; + let p = p.as_ref().display().to_string(); + if p.starts_with(VERBATIM_PREFIX) { + p[VERBATIM_PREFIX.len()..].to_string() + } else { + p + } + } + + #[allow(unused)] + fn print_symbols_info(gs: &GlobalState) { + let base_path = Path::new(".").canonicalize().unwrap(); + let symbols = gs.get_symbols(); + println!("vec!["); + for (key, val) in gs.sema_db.file_sema_map.iter() { + let key_path = Path::new(key) + .strip_prefix(base_path.clone()) + .unwrap_or_else(|_| Path::new(key)) + .to_str() + .unwrap() + .to_string(); + println!(" (\n \"{}\".to_string().replace(\"/\", &std::path::MAIN_SEPARATOR.to_string()),", key_path); + println!(" vec!["); + for symbol_ref in val.symbols.iter() { + let symbol = symbols.get_symbol(*symbol_ref).unwrap(); + let (start, end) = symbol.get_range(); + println!( + " ({},{},{},{},\"{}\".to_string(),SymbolKind::{:?}),", + start.line, + start.column.unwrap_or(0), + end.line, + end.column.unwrap_or(0), + symbol.get_name(), + symbol_ref.get_kind(), + ); + if let SymbolKind::Unresolved = symbol_ref.get_kind() { + let def_symbol_ref = symbol.get_definition().unwrap(); + let def_symbol = symbols.get_symbol(def_symbol_ref).unwrap(); + let (def_start, def_end) = def_symbol.get_range(); + let def_path = Path::new(&def_start.filename) + .strip_prefix(base_path.clone()) + .unwrap_or_else(|_| Path::new(&def_start.filename)) + .to_str() + .unwrap() + .to_string(); + println!( + " ({},{},{},{},\"{}\".to_string().replace(\"/\", &std::path::MAIN_SEPARATOR.to_string()),SymbolKind::{:?}),", + def_start.line, + def_start.column.unwrap_or(0), + def_end.line, + def_end.column.unwrap_or(0), + def_path, + def_symbol_ref.get_kind(), + ); + } + } + println!(" ],\n ),") + } + println!("]"); + } + + #[test] + fn test_look_up_exact_symbol() { + let sess = Arc::new(ParseSession::default()); + + let path = "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()); + let mut program = load_program(sess.clone(), &[&path], None, None) + .unwrap() + .program; + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + + let node_ty_map = resolver::resolve_program_with_opts( + &mut program, + resolver::Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + None, + ) + .node_ty_map; + let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map); + let base_path = Path::new(".").canonicalize().unwrap(); + // print_symbols_info(&gs); + let except_symbols = vec![ + ( + "src/advanced_resolver/test_data/import_test/e.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 7, 1, 16, "UnionType".to_string(), SymbolKind::Schema), + (2, 4, 2, 5, "a".to_string(), SymbolKind::Attribute), + ], + ), + ( + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 0, 1, 2, "_a".to_string(), SymbolKind::Value), + (2, 7, 2, 11, "Name".to_string(), SymbolKind::Schema), + (3, 4, 3, 13, "firstName".to_string(), SymbolKind::Attribute), + (4, 4, 4, 12, "lastName".to_string(), SymbolKind::Attribute), + (6, 7, 6, 13, "Person".to_string(), SymbolKind::Schema), + (7, 4, 7, 8, "name".to_string(), SymbolKind::Attribute), + (7, 10, 7, 14, "Name".to_string(), SymbolKind::Unresolved), + ( + 2, + 7, + 2, + 11, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (8, 4, 8, 7, "age".to_string(), SymbolKind::Attribute), + (10, 0, 10, 7, "_person".to_string(), SymbolKind::Value), + (10, 10, 10, 16, "Person".to_string(), SymbolKind::Unresolved), + ( + 6, + 7, + 6, + 13, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (11, 4, 11, 8, "name".to_string(), SymbolKind::Unresolved), + ( + 7, + 4, + 7, + 8, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (11, 11, 11, 15, "Name".to_string(), SymbolKind::Unresolved), + ( + 2, + 7, + 2, + 11, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + ( + 12, + 8, + 12, + 17, + "firstName".to_string(), + SymbolKind::Unresolved, + ), + ( + 3, + 4, + 3, + 13, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + ( + 13, + 8, + 13, + 16, + "lastName".to_string(), + SymbolKind::Unresolved, + ), + ( + 4, + 4, + 4, + 12, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (15, 4, 15, 7, "age".to_string(), SymbolKind::Unresolved), + ( + 8, + 4, + 8, + 7, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + ], + ), + ( + "src/advanced_resolver/test_data/import_test/d.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 7, 1, 13, "Parent".to_string(), SymbolKind::Schema), + (2, 4, 2, 8, "age1".to_string(), SymbolKind::Attribute), + ], + ), + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + ( + 1, + 7, + 1, + 20, + "import_test.a".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 2, + 7, + 2, + 20, + "import_test.b".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/b" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 3, + 7, + 3, + 20, + "import_test.c".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/c" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 4, + 7, + 4, + 20, + "import_test.d".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/d" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 5, + 7, + 5, + 20, + "import_test.e".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/e" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 6, + 24, + 6, + 25, + "import_test.f".to_string(), + SymbolKind::Unresolved, + ), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/f" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (7, 7, 7, 10, "pkg".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/pkg" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (8, 7, 8, 12, "regex".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 0, + "".to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (10, 7, 10, 11, "Main".to_string(), SymbolKind::Schema), + (10, 12, 10, 13, "d".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/d" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (10, 14, 10, 20, "Parent".to_string(), SymbolKind::Unresolved), + ( + 1, + 7, + 1, + 13, + "src/advanced_resolver/test_data/import_test/d.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (11, 11, 11, 12, "c".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/c" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 11, + 13, + 11, + 24, + "TestOfMixin".to_string(), + SymbolKind::Unresolved, + ), + ( + 1, + 7, + 1, + 18, + "src/advanced_resolver/test_data/import_test/c.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (12, 4, 12, 8, "name".to_string(), SymbolKind::Attribute), + (13, 4, 13, 7, "age".to_string(), SymbolKind::Attribute), + (14, 4, 14, 10, "person".to_string(), SymbolKind::Attribute), + (14, 13, 14, 14, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (14, 15, 14, 21, "Person".to_string(), SymbolKind::Unresolved), + ( + 6, + 7, + 6, + 13, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + ( + 15, + 4, + 15, + 19, + "list_union_type".to_string(), + SymbolKind::Attribute, + ), + (15, 23, 15, 24, "e".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/e" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 15, + 25, + 15, + 34, + "UnionType".to_string(), + SymbolKind::Unresolved, + ), + ( + 1, + 7, + 1, + 16, + "src/advanced_resolver/test_data/import_test/e.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + ( + 16, + 4, + 16, + 19, + "dict_union_type".to_string(), + SymbolKind::Attribute, + ), + (16, 23, 16, 24, "g".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/f" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 16, + 25, + 16, + 34, + "UnionType".to_string(), + SymbolKind::Unresolved, + ), + ( + 1, + 7, + 1, + 16, + "src/advanced_resolver/test_data/import_test/f.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (19, 8, 19, 13, "regex".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 0, + "".to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (19, 14, 19, 19, "match".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 0, + "".to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (19, 20, 19, 24, "name".to_string(), SymbolKind::Unresolved), + ( + 12, + 4, + 12, + 8, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (19, 97, 19, 101, "name".to_string(), SymbolKind::Unresolved), + ( + 12, + 4, + 12, + 8, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (21, 3, 21, 4, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (21, 5, 21, 7, "_a".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 2, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (22, 4, 22, 6, "_c".to_string(), SymbolKind::Value), + (23, 5, 23, 6, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (23, 7, 23, 9, "_a".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 2, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (24, 4, 24, 6, "_c".to_string(), SymbolKind::Unresolved), + ( + 22, + 4, + 22, + 6, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (26, 4, 26, 6, "_c".to_string(), SymbolKind::Unresolved), + ( + 22, + 4, + 22, + 6, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (28, 0, 28, 1, "p".to_string(), SymbolKind::Value), + (28, 4, 28, 8, "Main".to_string(), SymbolKind::Unresolved), + ( + 10, + 7, + 10, + 11, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (29, 4, 29, 8, "name".to_string(), SymbolKind::Unresolved), + ( + 12, + 4, + 12, + 8, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (29, 11, 29, 12, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 29, + 13, + 29, + 20, + "_person".to_string(), + SymbolKind::Unresolved, + ), + ( + 10, + 0, + 10, + 7, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (29, 21, 29, 25, "name".to_string(), SymbolKind::Unresolved), + ( + 7, + 4, + 7, + 8, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + ( + 29, + 26, + 29, + 35, + "firstName".to_string(), + SymbolKind::Unresolved, + ), + ( + 3, + 4, + 3, + 13, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (29, 45, 29, 46, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 29, + 47, + 29, + 54, + "_person".to_string(), + SymbolKind::Unresolved, + ), + ( + 10, + 0, + 10, + 7, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (29, 56, 29, 60, "name".to_string(), SymbolKind::Unresolved), + ( + 7, + 4, + 7, + 8, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + ( + 29, + 61, + 29, + 69, + "lastName".to_string(), + SymbolKind::Unresolved, + ), + ( + 4, + 4, + 4, + 12, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (30, 4, 30, 7, "age".to_string(), SymbolKind::Unresolved), + ( + 13, + 4, + 13, + 7, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (30, 10, 30, 11, "b".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/b" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (30, 12, 30, 14, "_b".to_string(), SymbolKind::Unresolved), + ( + 1, + 0, + 1, + 2, + "src/advanced_resolver/test_data/import_test/b.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (30, 17, 30, 18, "a".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/import_test/a" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + ( + 30, + 19, + 30, + 26, + "_person".to_string(), + SymbolKind::Unresolved, + ), + ( + 10, + 0, + 10, + 7, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + (30, 28, 30, 31, "age".to_string(), SymbolKind::Unresolved), + ( + 8, + 4, + 8, + 7, + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (33, 0, 33, 6, "person".to_string(), SymbolKind::Value), + (33, 9, 33, 12, "pkg".to_string(), SymbolKind::Unresolved), + ( + 0, + 0, + 0, + 0, + "src/advanced_resolver/test_data/pkg" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Package, + ), + (33, 13, 33, 19, "Person".to_string(), SymbolKind::Unresolved), + ( + 4, + 7, + 4, + 13, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (34, 4, 34, 8, "name".to_string(), SymbolKind::Unresolved), + ( + 5, + 4, + 5, + 8, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (34, 9, 34, 13, "name".to_string(), SymbolKind::Unresolved), + ( + 2, + 4, + 2, + 8, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + (37, 0, 37, 1, "x".to_string(), SymbolKind::Value), + (38, 16, 38, 17, "x".to_string(), SymbolKind::Unresolved), + ( + 37, + 0, + 37, + 1, + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Value, + ), + ], + ), + ( + "src/advanced_resolver/test_data/import_test/f.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 7, 1, 16, "UnionType".to_string(), SymbolKind::Schema), + (2, 4, 2, 5, "b".to_string(), SymbolKind::Attribute), + ], + ), + ( + "src/advanced_resolver/test_data/import_test/c.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 7, 1, 18, "TestOfMixin".to_string(), SymbolKind::Schema), + (2, 4, 2, 7, "age".to_string(), SymbolKind::Attribute), + ], + ), + ( + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![ + (1, 7, 1, 11, "Name".to_string(), SymbolKind::Schema), + (2, 4, 2, 8, "name".to_string(), SymbolKind::Attribute), + (4, 7, 4, 13, "Person".to_string(), SymbolKind::Schema), + (5, 4, 5, 8, "name".to_string(), SymbolKind::Attribute), + (5, 10, 5, 14, "Name".to_string(), SymbolKind::Unresolved), + ( + 1, + 7, + 1, + 11, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (5, 17, 5, 21, "Name".to_string(), SymbolKind::Unresolved), + ( + 1, + 7, + 1, + 11, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Schema, + ), + (5, 23, 5, 27, "name".to_string(), SymbolKind::Unresolved), + ( + 2, + 4, + 2, + 8, + "src/advanced_resolver/test_data/pkg/pkg.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + SymbolKind::Attribute, + ), + ], + ), + ( + "src/advanced_resolver/test_data/import_test/b.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + vec![(1, 0, 1, 2, "_b".to_string(), SymbolKind::Value)], + ), + ]; + let mut skip_def_info = false; + for (filepath, symbols) in except_symbols.iter() { + let abs_filepath = adjust_canonicalization(base_path.join(filepath)); + // symbols will be sorted according to their position in the file + // now we check all symbols + for (index, symbol_info) in symbols.iter().enumerate() { + if skip_def_info { + skip_def_info = false; + continue; + } + let (start_line, start_col, end_line, end_col, name, kind) = symbol_info; + if abs_filepath.is_empty() { + continue; + } + // test look up symbols + let inner_pos = Position { + filename: abs_filepath.clone(), + line: (start_line + end_line) / 2, + column: Some((start_col + end_col) / 2), + }; + let looked_symbol_ref = gs.look_up_exact_symbol(&inner_pos).unwrap(); + let looked_symbol = gs.get_symbols().get_symbol(looked_symbol_ref).unwrap(); + let (start, end) = looked_symbol.get_range(); + // test symbol basic infomation + assert_eq!(start.filename, abs_filepath); + assert_eq!(start.line, *start_line); + assert_eq!(start.column.unwrap_or(0), *start_col); + assert_eq!(end.line, *end_line); + assert_eq!(end.column.unwrap_or(0), *end_col); + assert_eq!(*name, looked_symbol.get_name()); + assert_eq!(looked_symbol_ref.get_kind(), *kind); + + // test find def + if SymbolKind::Unresolved == looked_symbol_ref.get_kind() { + let (start_line, start_col, end_line, end_col, path, kind) = + symbols.get(index + 1).unwrap(); + let def_ref = looked_symbol.get_definition().unwrap(); + let def = gs.get_symbols().get_symbol(def_ref).unwrap(); + let (start, end) = def.get_range(); + let def_filepath = adjust_canonicalization(base_path.join(path)); + assert_eq!(start.line, *start_line); + assert_eq!(start.column.unwrap_or(0), *start_col); + assert_eq!(end.line, *end_line); + assert_eq!(end.column.unwrap_or(0), *end_col); + if !path.is_empty() { + assert_eq!(start.filename, def_filepath); + } + assert_eq!(def_ref.get_kind(), *kind); + skip_def_info = true; + } + } + } + } + + #[test] + fn test_look_up_cloest_symbol() { + let sess = Arc::new(ParseSession::default()); + + let path = "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()); + let mut program = load_program(sess.clone(), &[&path], None, None) + .unwrap() + .program; + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + let node_ty_map = resolver::resolve_program(&mut program).node_ty_map; + let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map); + let base_path = Path::new(".").canonicalize().unwrap(); + + let test_cases = vec![ + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 19_u64, + 25_u64, + Some((19, 20, 19, 24, "name".to_string(), SymbolKind::Unresolved)), + ), + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 32_u64, + 7_u64, + Some((28, 4, 28, 8, "Main".to_string(), SymbolKind::Unresolved)), + ), + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 35_u64, + 5_u64, + Some((33, 13, 33, 19, "Person".to_string(), SymbolKind::Unresolved)), + ), + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 28_u64, + 30_u64, + None, + ), + ]; + + for (filepath, line, col, symbol_info) in test_cases.iter() { + let abs_scope_file_path = adjust_canonicalization(base_path.join(filepath)); + let symbol_ref = gs.look_up_closest_symbol(&Position { + filename: abs_scope_file_path.clone(), + line: *line, + column: Some(*col), + }); + + match symbol_info { + Some((start_line, start_col, end_line, end_col, name, kind)) => { + let symbol_ref = symbol_ref.unwrap(); + let symbol = gs.get_symbols().get_symbol(symbol_ref).unwrap(); + + let (start, end) = symbol.get_range(); + assert_eq!(start.line, *start_line); + assert_eq!(start.column.unwrap_or(0), *start_col); + assert_eq!(end.line, *end_line); + assert_eq!(end.column.unwrap_or(0), *end_col); + assert_eq!(*name, symbol.get_name()); + assert_eq!(symbol_ref.get_kind(), *kind); + } + None => assert!(symbol_ref.is_none()), + } + } + } + + #[test] + fn test_look_up_scope() { + let sess = Arc::new(ParseSession::default()); + + let path = "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()); + let mut program = load_program(sess.clone(), &[&path], None, None) + .unwrap() + .program; + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + let node_ty_map = resolver::resolve_program(&mut program).node_ty_map; + let gs = AdvancedResolver::resolve_program(&program, gs, node_ty_map); + let base_path = Path::new(".").canonicalize().unwrap(); + + let scope_test_cases = vec![ + // __main__.Main schema stmt scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 17_u64, + 26_u64, + 10_usize, + ), + // __main__.Main schema expr scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 30, + 6, + 6, + ), + // __main__.Main schema config entry value scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 30, + 20, + 10, + ), + // pkg.Person schema expr scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 33, + 21, + 1, + ), + // pkg.Person schema config entry value scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 34, + 17, + 6, + ), + // __main__ package scope + ( + "src/advanced_resolver/test_data/schema_symbols.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 36, + 31, + 5, + ), + // import_test.a.Person expr scope + ( + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 15, + 11, + 6, + ), + // import_test.a.Name expr scope + ( + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 12, + 5, + 2, + ), + // import_test.a.Name config entry value scope + ( + "src/advanced_resolver/test_data/import_test/a.k" + .to_string() + .replace("/", &std::path::MAIN_SEPARATOR.to_string()), + 12, + 21, + 8, + ), + ]; + + for (filepath, line, col, def_num) in scope_test_cases.iter() { + let abs_scope_file_path = adjust_canonicalization(base_path.join(filepath)); + let scope_ref = gs + .look_up_scope(&Position { + filename: abs_scope_file_path.clone(), + line: *line, + column: Some(*col), + }) + .unwrap(); + + let all_defs = gs.get_all_defs_in_scope(scope_ref).unwrap(); + assert_eq!(all_defs.len(), *def_num) + } + } +} diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs new file mode 100644 index 000000000..b6480728c --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -0,0 +1,1218 @@ +use std::sync::Arc; + +use indexmap::IndexMap; +use kclvm_ast::ast; +use kclvm_ast::pos::GetPos; +use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_error::{diagnostic::Range, Position}; + +use crate::{ + core::{ + scope::LocalSymbolScopeKind, + symbol::{ + CommentSymbol, DecoratorSymbol, ExpressionSymbol, KCLSymbolSemanticInfo, SymbolRef, + UnresolvedSymbol, ValueSymbol, + }, + }, + ty::{Type, SCHEMA_MEMBER_FUNCTIONS}, +}; + +use super::AdvancedResolver; + +type ResolvedResult = Option; + +impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { + type Result = Option; + + fn walk_module(&mut self, module: &'ctx ast::Module) -> Self::Result { + for stmt in module.body.iter() { + self.stmt(&stmt); + } + for comment in module.comments.iter() { + let (start, end) = comment.get_span_pos(); + self.ctx.start_pos = start; + self.ctx.end_pos = end; + self.ctx.cur_node = comment.id.clone(); + self.walk_comment(&comment.node); + } + None + } + + fn walk_expr_stmt(&mut self, expr_stmt: &'ctx ast::ExprStmt) -> Self::Result { + for expr in expr_stmt.exprs.iter() { + self.expr(&expr); + } + None + } + + fn walk_unification_stmt( + &mut self, + unification_stmt: &'ctx ast::UnificationStmt, + ) -> Self::Result { + self.ctx.maybe_def = true; + self.walk_identifier_expr(&unification_stmt.target); + self.ctx.maybe_def = false; + self.walk_schema_expr(&unification_stmt.value.node); + None + } + + fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx ast::TypeAliasStmt) -> Self::Result { + let alias_symbol = self.gs.get_symbols().get_symbol_by_fully_qualified_name( + &(self.ctx.current_pkgpath.as_ref().unwrap().clone() + + "." + + &type_alias_stmt.type_name.node.get_name()), + )?; + if let Some(symbol) = self + .gs + .get_symbols_mut() + .type_aliases + .get_mut(alias_symbol.get_id()) + { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&type_alias_stmt.type_name.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + self.walk_type_expr(Some(&type_alias_stmt.ty)); + None + } + + fn walk_assign_stmt(&mut self, assign_stmt: &'ctx ast::AssignStmt) -> Self::Result { + for target in &assign_stmt.targets { + if target.node.names.is_empty() { + continue; + } + self.ctx.maybe_def = true; + self.walk_identifier_expr(target); + self.ctx.maybe_def = false; + } + self.walk_type_expr(assign_stmt.ty.as_ref().map(|ty| ty.as_ref())); + self.expr(&assign_stmt.value); + None + } + + fn walk_aug_assign_stmt(&mut self, aug_assign_stmt: &'ctx ast::AugAssignStmt) -> Self::Result { + self.ctx.maybe_def = true; + self.walk_identifier_expr(&aug_assign_stmt.target); + self.ctx.maybe_def = false; + self.expr(&aug_assign_stmt.value); + None + } + + fn walk_assert_stmt(&mut self, assert_stmt: &'ctx ast::AssertStmt) -> Self::Result { + self.expr(&assert_stmt.test); + if let Some(if_cond) = &assert_stmt.if_cond { + self.expr(if_cond); + } + if let Some(msg) = &assert_stmt.msg { + self.expr(msg); + } + None + } + + fn walk_if_stmt(&mut self, if_stmt: &'ctx ast::IfStmt) -> Self::Result { + self.expr(&if_stmt.cond); + for stmt in if_stmt.body.iter() { + self.stmt(stmt); + } + for stmt in if_stmt.orelse.iter() { + self.stmt(stmt); + } + None + } + + fn walk_import_stmt(&mut self, import_stmt: &'ctx ast::ImportStmt) -> Self::Result { + let ast_id = self.ctx.cur_node.clone(); + let (start_pos, end_pos) = import_stmt + .asname + .clone() + .unwrap_or(import_stmt.path.clone()) + .get_span_pos(); + + let mut unresolved = + UnresolvedSymbol::new(import_stmt.path.node.clone(), start_pos, end_pos, None); + let package_symbol = self + .gs + .get_symbols() + .get_symbol_by_fully_qualified_name(&import_stmt.path.node)?; + unresolved.def = Some(package_symbol); + let unresolved_ref = self + .gs + .get_symbols_mut() + .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + self.gs + .get_symbols_mut() + .symbols_info + .node_symbol_map + .insert(self.ctx.get_node_key(&ast_id), unresolved_ref); + let cur_scope = *self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .add_ref_to_scope(cur_scope, unresolved_ref); + Some(unresolved_ref) + } + + fn walk_schema_stmt(&mut self, schema_stmt: &'ctx ast::SchemaStmt) -> Self::Result { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + let schema_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&schema_stmt.name.id)) + .unwrap() + .clone(); + let schema_symbol = self + .gs + .get_symbols() + .get_type_symbol(&schema_ty, self.get_current_module_info()) + .unwrap(); + + if self + .gs + .get_symbols() + .schemas + .contains(schema_symbol.get_id()) + { + let mut schema_builtin_member = IndexMap::new(); + for name in SCHEMA_MEMBER_FUNCTIONS.iter() { + let func_ty = Arc::new(Type::function( + Some(schema_ty.clone()), + Type::list_ref(Type::any_ref()), + &[], + "", + false, + None, + )); + let mut func_value = ValueSymbol::new( + name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + Some(schema_symbol), + false, + ); + func_value.sema_info.ty = Some(func_ty); + let func_symbol_ref = self.gs.get_symbols_mut().alloc_value_symbol( + func_value, + self.ctx.get_node_key(&ast::AstIndex::default()), + ); + schema_builtin_member.insert(name.to_string(), func_symbol_ref); + } + self.gs + .get_symbols_mut() + .symbols_info + .schema_builtin_symbols + .insert(schema_symbol, schema_builtin_member); + self.gs + .get_symbols_mut() + .schemas + .get_mut(schema_symbol.get_id()) + .unwrap() + .sema_info = KCLSymbolSemanticInfo { + ty: Some(schema_ty.clone()), + doc: schema_stmt.doc.as_ref().map(|doc| doc.node.clone()), + }; + } + + self.resolve_decorator(&schema_stmt.decorators); + + let mut last_end_pos = start.clone(); + + self.enter_local_scope( + &self.ctx.current_filename.clone().unwrap(), + start, + end.clone(), + LocalSymbolScopeKind::SchemaDef, + ); + let cur_scope = *self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .set_owner_to_scope(cur_scope, schema_symbol); + if let Some(parent) = &schema_stmt.parent_name { + self.gs + .get_symbols_mut() + .schemas + .get_mut(schema_symbol.get_id()) + .unwrap() + .parent_schema = self.walk_identifier_expr(parent); + } + if let Some(for_host) = &schema_stmt.for_host_name { + self.gs + .get_symbols_mut() + .schemas + .get_mut(schema_symbol.get_id()) + .unwrap() + .for_host = self.walk_identifier_expr(for_host); + } + let mut mixins = vec![]; + for mixin in schema_stmt.mixins.iter() { + if let Some(mixin) = self.walk_identifier_expr(mixin) { + mixins.push(mixin); + } + last_end_pos = mixin.get_end_pos(); + } + self.gs + .get_symbols_mut() + .schemas + .get_mut(schema_symbol.get_id()) + .unwrap() + .mixins = mixins; + + if let Some(args) = &schema_stmt.args { + self.walk_arguments(&args.node); + last_end_pos = args.get_end_pos(); + } + if let Some(index_signature) = &schema_stmt.index_signature { + if let Some(key_name) = &index_signature.node.key_name { + let (start, end) = index_signature.get_span_pos(); + let value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(key_name.clone(), start, end, Some(schema_symbol), false), + self.ctx.get_node_key(&index_signature.id), + ); + if let Some(symbol) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&index_signature.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + + self.gs + .get_scopes_mut() + .add_def_to_scope(cur_scope, key_name.clone(), value); + + self.walk_type_expr(Some(&index_signature.node.value_ty)); + if let Some(value) = &index_signature.node.value { + self.expr(value); + }; + } + last_end_pos = index_signature.get_end_pos(); + } + for stmt in schema_stmt.body.iter() { + if let Some(attribute_symbol) = self.stmt(&stmt) { + let name = self + .gs + .get_symbols() + .get_symbol(attribute_symbol) + .unwrap() + .get_name(); + self.gs + .get_symbols_mut() + .schemas + .get_mut(schema_symbol.get_id()) + .unwrap() + .attributes + .insert(name, attribute_symbol); + } + last_end_pos = stmt.get_end_pos(); + } + + let has_check = !schema_stmt.checks.is_empty(); + if has_check { + self.enter_local_scope( + &self.ctx.current_filename.clone().unwrap(), + last_end_pos, + end, + LocalSymbolScopeKind::Check, + ); + } + + for check_expr in schema_stmt.checks.iter() { + self.walk_check_expr(&check_expr.node); + } + + if has_check { + self.leave_scope(); + } + + self.leave_scope(); + + Some(schema_symbol) + } + + fn walk_rule_stmt(&mut self, rule_stmt: &'ctx ast::RuleStmt) -> Self::Result { + let rule_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&rule_stmt.name.id))? + .clone(); + let rule_symbol = self + .gs + .get_symbols() + .get_type_symbol(&rule_ty, self.get_current_module_info())?; + if let Some(symbol) = self + .gs + .get_symbols_mut() + .rules + .get_mut(rule_symbol.get_id()) + { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&rule_stmt.name.id)) + .map(|ty| ty.clone()), + doc: rule_stmt.doc.as_ref().map(|doc| doc.node.clone()), + }; + } + + if let Some(for_host) = &rule_stmt.for_host_name { + self.gs + .get_symbols_mut() + .rules + .get_mut(rule_symbol.get_id())? + .for_host = self.walk_identifier_expr(for_host); + } + let mut parent_rules = vec![]; + for parent_rule in rule_stmt.parent_rules.iter() { + parent_rules.push(self.walk_identifier_expr(parent_rule)?); + } + self.gs + .get_symbols_mut() + .rules + .get_mut(rule_symbol.get_id())? + .parent_rules = parent_rules; + self.resolve_decorator(&rule_stmt.decorators); + Some(rule_symbol) + } + + fn walk_quant_expr(&mut self, quant_expr: &'ctx ast::QuantExpr) -> Self::Result { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + self.expr(&quant_expr.target); + self.enter_local_scope( + &self.ctx.current_filename.as_ref().unwrap().clone(), + start, + end, + LocalSymbolScopeKind::Quant, + ); + let cur_scope = *self.ctx.scopes.last().unwrap(); + for target in quant_expr.variables.iter() { + if target.node.names.is_empty() { + continue; + } + let name = target.node.get_name(); + let (start_pos, end_pos): Range = target.get_span_pos(); + let ast_id = if target.node.names.is_empty() { + &target.id + } else { + &target.node.names.last().unwrap().id + }; + let value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(name.clone(), start_pos, end_pos, None, false), + self.ctx.get_node_key(&ast_id), + ); + self.gs + .get_scopes_mut() + .add_def_to_scope(cur_scope, name, value); + if let Some(symbol) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(ast_id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + } + + if let Some(if_cond) = &quant_expr.if_cond { + self.expr(&if_cond); + } + self.expr(&quant_expr.test); + self.leave_scope(); + None + } + + fn walk_schema_attr(&mut self, schema_attr: &'ctx ast::SchemaAttr) -> Self::Result { + let attr_symbol = *self + .gs + .get_symbols() + .symbols_info + .node_symbol_map + .get(&self.ctx.get_node_key(&schema_attr.name.id))?; + let parent_scope = *self.ctx.scopes.last().unwrap(); + let parent_scope = self.gs.get_scopes().get_scope(&parent_scope).unwrap(); + let mut doc = None; + if let Some(schema_symbol) = parent_scope.get_owner() { + let schema_symbol = self.gs.get_symbols().get_symbol(schema_symbol).unwrap(); + if let Some(schema_ty) = schema_symbol.get_sema_info().ty.clone() { + let schema_ty = schema_ty.into_schema_type(); + if let Some(attr) = schema_ty.attrs.get(&schema_attr.name.node) { + doc = attr.doc.clone() + } + } + }; + + if let Some(symbol) = self + .gs + .get_symbols_mut() + .attributes + .get_mut(attr_symbol.get_id()) + { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&schema_attr.name.id)) + .map(|ty| ty.clone()), + doc, + }; + }; + + self.walk_type_expr(Some(&schema_attr.ty)); + if let Some(value) = &schema_attr.value { + self.expr(value); + } + + self.resolve_decorator(&schema_attr.decorators); + Some(attr_symbol) + } + + /// if else -> sup([body, orelse]) + fn walk_if_expr(&mut self, if_expr: &'ctx ast::IfExpr) -> Self::Result { + self.expr(&if_expr.cond); + self.expr(&if_expr.body); + self.expr(&if_expr.orelse); + None + } + + fn walk_unary_expr(&mut self, unary_expr: &'ctx ast::UnaryExpr) -> Self::Result { + self.expr(&unary_expr.operand); + None + } + + fn walk_binary_expr(&mut self, binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { + self.expr(&binary_expr.left); + self.expr(&binary_expr.right); + None + } + + fn walk_selector_expr(&mut self, selector_expr: &'ctx ast::SelectorExpr) -> Self::Result { + self.expr(&selector_expr.value); + let mut parent_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&selector_expr.value.id))? + .clone(); + for name in &selector_expr.attr.node.names { + let def_symbol_ref = self.gs.get_symbols().get_type_attribute( + &parent_ty, + &name.node, + self.get_current_module_info(), + )?; + + let (start_pos, end_pos): Range = name.get_span_pos(); + let ast_id = name.id.clone(); + let mut unresolved = UnresolvedSymbol::new(name.node.clone(), start_pos, end_pos, None); + unresolved.def = Some(def_symbol_ref); + let unresolved_ref = self + .gs + .get_symbols_mut() + .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + let cur_scope = *self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .add_ref_to_scope(cur_scope, unresolved_ref); + + parent_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&name.id))? + .clone(); + } + None + } + + fn walk_call_expr(&mut self, call_expr: &'ctx ast::CallExpr) -> Self::Result { + self.expr(&call_expr.func); + self.do_arguments_symbol_resolve(&call_expr.args, &call_expr.keywords); + None + } + + fn walk_subscript(&mut self, subscript: &'ctx ast::Subscript) -> Self::Result { + self.expr(&subscript.value); + if let Some(index) = &subscript.index { + self.expr(index); + } else { + for expr in [&subscript.lower, &subscript.upper, &subscript.step] + .iter() + .copied() + .flatten() + { + self.expr(expr); + } + } + None + } + + fn walk_paren_expr(&mut self, paren_expr: &'ctx ast::ParenExpr) -> Self::Result { + self.expr(&paren_expr.expr); + None + } + + fn walk_list_expr(&mut self, list_expr: &'ctx ast::ListExpr) -> Self::Result { + for expr in list_expr.elts.iter() { + self.expr(expr); + } + None + } + + fn walk_list_comp(&mut self, list_comp: &'ctx ast::ListComp) -> Self::Result { + let start = list_comp.elt.get_pos(); + let end = match list_comp.generators.last() { + Some(last) => last.get_end_pos(), + None => list_comp.elt.get_end_pos(), + }; + self.enter_local_scope( + &self.ctx.current_filename.clone().unwrap(), + start, + end, + LocalSymbolScopeKind::List, + ); + for comp_clause in &list_comp.generators { + self.walk_comp_clause(&comp_clause.node); + } + self.expr(&list_comp.elt); + self.leave_scope(); + None + } + + fn walk_dict_comp(&mut self, dict_comp: &'ctx ast::DictComp) -> Self::Result { + let key = dict_comp.entry.key.as_ref().unwrap(); + let start = key.get_pos(); + let end = match dict_comp.generators.last() { + Some(last) => last.get_end_pos(), + None => dict_comp.entry.value.get_end_pos(), + }; + self.enter_local_scope( + &self.ctx.current_filename.clone().unwrap(), + start, + end, + LocalSymbolScopeKind::Dict, + ); + for comp_clause in &dict_comp.generators { + self.walk_comp_clause(&comp_clause.node); + } + self.expr(key); + self.expr(&dict_comp.entry.value); + self.leave_scope(); + None + } + + fn walk_list_if_item_expr( + &mut self, + list_if_item_expr: &'ctx ast::ListIfItemExpr, + ) -> Self::Result { + self.expr(&list_if_item_expr.if_cond)?; + if let Some(orelse) = &list_if_item_expr.orelse { + self.expr(orelse); + } + for expr in list_if_item_expr.exprs.iter() { + self.expr(expr); + } + None + } + + fn walk_starred_expr(&mut self, starred_expr: &'ctx ast::StarredExpr) -> Self::Result { + self.expr(&starred_expr.value); + None + } + + fn walk_config_if_entry_expr( + &mut self, + config_if_entry_expr: &'ctx ast::ConfigIfEntryExpr, + ) -> Self::Result { + self.expr(&config_if_entry_expr.if_cond); + self.walk_config_entries(&config_if_entry_expr.items); + if let Some(expr) = config_if_entry_expr.orelse.as_ref() { + self.expr(expr); + } + None + } + + fn walk_comp_clause(&mut self, comp_clause: &'ctx ast::CompClause) -> Self::Result { + self.expr(&comp_clause.iter); + for target in comp_clause.targets.iter() { + self.ctx.maybe_def = true; + self.walk_identifier_expr(target); + self.ctx.maybe_def = false; + } + for if_expr in comp_clause.ifs.iter() { + self.expr(if_expr); + } + None + } + + fn walk_schema_expr(&mut self, schema_expr: &'ctx ast::SchemaExpr) -> Self::Result { + self.walk_identifier_expr(&schema_expr.name)?; + let schema_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&schema_expr.name.id))? + .clone(); + let schema_symbol = self + .gs + .get_symbols() + .get_type_symbol(&schema_ty, self.get_current_module_info())?; + self.ctx.current_schema_symbol = Some(schema_symbol); + self.expr(&schema_expr.config); + self.do_arguments_symbol_resolve(&schema_expr.args, &schema_expr.kwargs); + None + } + + fn walk_config_expr(&mut self, config_expr: &'ctx ast::ConfigExpr) -> Self::Result { + self.walk_config_entries(&config_expr.items); + None + } + + fn walk_check_expr(&mut self, check_expr: &'ctx ast::CheckExpr) -> Self::Result { + if let Some(msg) = &check_expr.msg { + self.expr(msg); + } + if let Some(if_cond) = &check_expr.if_cond { + self.expr(if_cond); + } + self.expr(&check_expr.test); + None + } + + fn walk_lambda_expr(&mut self, lambda_expr: &'ctx ast::LambdaExpr) -> Self::Result { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + self.enter_local_scope( + &self.ctx.current_filename.clone().unwrap(), + start, + end, + LocalSymbolScopeKind::Lambda, + ); + if let Some(args) = &lambda_expr.args { + self.walk_arguments(&args.node); + } + if let Some(ret_annotation_ty) = &lambda_expr.return_ty { + self.walk_type_expr(Some(&ret_annotation_ty)); + } + for stmt in lambda_expr.body.iter() { + self.stmt(&stmt); + } + self.leave_scope(); + None + } + + fn walk_keyword(&mut self, keyword: &'ctx ast::Keyword) -> Self::Result { + self.ctx.maybe_def = true; + self.walk_identifier_expr(&keyword.arg); + self.ctx.maybe_def = false; + if let Some(value) = &keyword.value { + self.expr(&value); + } + None + } + + fn walk_arguments(&mut self, arguments: &'ctx ast::Arguments) -> Self::Result { + for (i, arg) in arguments.args.iter().enumerate() { + let ty = arguments.get_arg_type_node(i); + self.walk_type_expr(ty); + self.ctx.maybe_def = true; + self.walk_identifier_expr(arg); + self.ctx.maybe_def = false; + + if let Some(val) = &arguments.defaults[i] { + self.expr(val); + } + } + None + } + + fn walk_compare(&mut self, compare: &'ctx ast::Compare) -> Self::Result { + self.expr(&compare.left); + for comparator in compare.comparators.iter() { + self.expr(&comparator); + } + None + } + + fn walk_identifier(&mut self, identifier: &'ctx ast::Identifier) -> Self::Result { + let symbol_ref = self.resolve_names(&identifier.names, self.ctx.maybe_def)?; + Some(symbol_ref) + } + + fn walk_number_lit(&mut self, _number_lit: &'ctx ast::NumberLit) -> Self::Result { + None + } + + fn walk_string_lit(&mut self, _string_lit: &'ctx ast::StringLit) -> Self::Result { + None + } + + fn walk_name_constant_lit( + &mut self, + _name_constant_lit: &'ctx ast::NameConstantLit, + ) -> Self::Result { + None + } + + fn walk_joined_string(&mut self, joined_string: &'ctx ast::JoinedString) -> Self::Result { + self.ctx.maybe_def = false; + for expr in joined_string.values.iter() { + self.expr(expr); + } + None + } + + fn walk_formatted_value(&mut self, formatted_value: &'ctx ast::FormattedValue) -> Self::Result { + self.expr(&formatted_value.value); + None + } + + fn walk_comment(&mut self, comment: &'ctx ast::Comment) -> Self::Result { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + let comment_symbol = CommentSymbol::new(start, end, comment.text.clone()); + self.gs + .get_symbols_mut() + .alloc_comment_symbol(comment_symbol, self.ctx.get_node_key(&self.ctx.cur_node)) + } + + fn walk_missing_expr(&mut self, _missing_expr: &'ctx ast::MissingExpr) -> Self::Result { + None + } +} + +impl<'ctx> AdvancedResolver<'ctx> { + #[inline] + pub fn expr(&mut self, expr: &'ctx ast::NodeRef) -> ResolvedResult { + if matches!( + &expr.node, + ast::Expr::Identifier(_) + | ast::Expr::Config(_) + | ast::Expr::Schema(_) + | ast::Expr::ConfigIfEntry(_) + | ast::Expr::Quant(_) + ) { + let (start, end) = expr.get_span_pos(); + self.ctx.start_pos = start; + self.ctx.end_pos = end; + } + self.ctx.cur_node = expr.id.clone(); + match self.walk_expr(&expr.node) { + None => match self.ctx.node_ty_map.get(&self.ctx.get_node_key(&expr.id)) { + Some(ty) => { + if let ast::Expr::Missing(_) = expr.node { + return None; + } + let (_, end) = expr.get_span_pos(); + let mut expr_symbol = ExpressionSymbol::new( + format!("@{}", expr.node.get_expr_name()), + end.clone(), + end, + None, + ); + expr_symbol.sema_info.ty = Some(ty.clone()); + self.gs + .get_symbols_mut() + .alloc_expression_symbol(expr_symbol, self.ctx.get_node_key(&expr.id)) + } + None => None, + }, + some => some, + } + } + + #[inline] + pub fn stmt(&mut self, stmt: &'ctx ast::NodeRef) -> ResolvedResult { + let (start, end) = stmt.get_span_pos(); + self.ctx.start_pos = start; + self.ctx.end_pos = end; + self.ctx.cur_node = stmt.id.clone(); + let result = self.walk_stmt(&stmt.node); + result + } + + fn resolve_names(&mut self, names: &[ast::Node], maybe_def: bool) -> ResolvedResult { + let first_name = names.get(0)?; + let cur_scope = *self.ctx.scopes.last().unwrap(); + + let mut first_symbol = self.gs.look_up_symbol( + &first_name.node, + cur_scope, + self.get_current_module_info(), + self.ctx.maybe_def, + ); + if first_symbol.is_none() { + //maybe import package symbol + let module_info = self.get_current_module_info().unwrap(); + + let import_info = module_info.get_import_info(&first_name.node); + if import_info.is_some() { + first_symbol = self + .gs + .get_symbols() + .get_symbol_by_fully_qualified_name(&import_info.unwrap().fully_qualified_name); + } + + if let Some(first_symbol) = first_symbol { + if self + .gs + .get_symbols() + .get_symbol(first_symbol) + .unwrap() + .get_sema_info() + .ty + .is_none() + { + if let Some(ty) = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&first_name.id)) + { + self.gs + .get_symbols_mut() + .set_symbol_type(first_symbol, ty.clone()); + } + } + } + } + match first_symbol { + Some(symbol_ref) => { + let (start_pos, end_pos): Range = first_name.get_span_pos(); + let (def_start_pos, def_end_pos) = + self.gs.get_symbols().get_symbol(symbol_ref)?.get_range(); + + // get an unresolved symbol + if def_start_pos != start_pos || def_end_pos != end_pos { + let ast_id = first_name.id.clone(); + let mut first_unresolved = + UnresolvedSymbol::new(first_name.node.clone(), start_pos, end_pos, None); + first_unresolved.def = Some(symbol_ref); + let first_unresolved_ref = self + .gs + .get_symbols_mut() + .alloc_unresolved_symbol(first_unresolved, self.ctx.get_node_key(&ast_id)); + let cur_scope = *self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .add_ref_to_scope(cur_scope, first_unresolved_ref); + } + if names.len() > 1 { + let mut parent_ty = self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&first_name.id))?; + + for index in 1..names.len() { + let name = names.get(index).unwrap(); + let def_symbol_ref = self.gs.get_symbols().get_type_attribute( + &parent_ty, + &name.node, + self.get_current_module_info(), + )?; + + let (start_pos, end_pos): Range = name.get_span_pos(); + let ast_id = name.id.clone(); + let mut unresolved = + UnresolvedSymbol::new(name.node.clone(), start_pos, end_pos, None); + unresolved.def = Some(def_symbol_ref); + let unresolved_ref = self + .gs + .get_symbols_mut() + .alloc_unresolved_symbol(unresolved, self.ctx.get_node_key(&ast_id)); + + let cur_scope = *self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .add_ref_to_scope(cur_scope, unresolved_ref); + + parent_ty = self.ctx.node_ty_map.get(&self.ctx.get_node_key(&name.id))?; + if index == names.len() - 1 { + return Some(unresolved_ref); + } + } + } + Some(symbol_ref) + } + None => { + if maybe_def { + let (start_pos, end_pos): Range = first_name.get_span_pos(); + let ast_id = first_name.id.clone(); + let first_value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(first_name.node.clone(), start_pos, end_pos, None, false), + self.ctx.get_node_key(&ast_id), + ); + self.gs.get_scopes_mut().add_def_to_scope( + cur_scope, + first_name.node.clone(), + first_value, + ); + + if let Some(symbol) = self + .gs + .get_symbols_mut() + .values + .get_mut(first_value.get_id()) + { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&first_name.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + + for index in 1..names.len() { + let name = names.get(index)?; + let (start_pos, end_pos): Range = name.get_span_pos(); + let ast_id = name.id.clone(); + let value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(name.node.clone(), start_pos, end_pos, None, false), + self.ctx.get_node_key(&ast_id), + ); + + self.gs.get_scopes_mut().add_def_to_scope( + cur_scope, + name.node.clone(), + value, + ); + + if let Some(symbol) = + self.gs.get_symbols_mut().values.get_mut(value.get_id()) + { + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&name.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + if index == names.len() - 1 { + return Some(value); + } + } + } + None + } + } + } + + #[inline] + pub fn walk_identifier_expr( + &mut self, + identifier: &'ctx ast::NodeRef, + ) -> ResolvedResult { + let symbol_ref = if let Some(identifier_symbol) = self + .gs + .get_symbols() + .symbols_info + .node_symbol_map + .get(&self.ctx.get_node_key(&&identifier.id)) + .map(|symbol_ref| *symbol_ref) + { + if let Some(symbol) = self + .gs + .get_symbols_mut() + .values + .get_mut(identifier_symbol.get_id()) + { + let id = if identifier.node.names.is_empty() { + &identifier.id + } else { + &identifier.node.names.last().unwrap().id + }; + symbol.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + + if self.ctx.maybe_def && identifier.node.names.len() > 0 { + let cur_scope = *self.ctx.scopes.last().unwrap(); + match cur_scope.kind { + crate::core::scope::ScopeKind::Local => { + self.gs.get_scopes_mut().add_def_to_scope( + cur_scope, + identifier.node.names.last().unwrap().node.clone(), + identifier_symbol, + ); + } + crate::core::scope::ScopeKind::Root => {} + } + } + identifier_symbol + } else { + self.resolve_names(&identifier.node.names, self.ctx.maybe_def)? + }; + + Some(symbol_ref) + } + + pub fn walk_type_expr( + &mut self, + ty_node: Option<&'ctx ast::Node>, + ) -> ResolvedResult { + if let Some(ty_node) = ty_node { + match &ty_node.node { + ast::Type::Any => {} + ast::Type::Named(identifier) => { + self.walk_identifier(identifier); + } + ast::Type::Basic(_) => {} + ast::Type::List(list_type) => { + self.walk_type_expr(list_type.inner_type.as_ref().map(|ty| ty.as_ref())); + } + ast::Type::Dict(dict_type) => { + self.walk_type_expr(dict_type.key_type.as_ref().map(|ty| ty.as_ref())); + self.walk_type_expr(dict_type.value_type.as_ref().map(|ty| ty.as_ref())); + } + ast::Type::Union(union_type) => { + for elem_ty in union_type.type_elements.iter() { + self.walk_type_expr(Some(elem_ty)); + } + } + ast::Type::Literal(_) => {} + ast::Type::Function(func_type) => { + if let Some(params_ty) = &func_type.params_ty { + for param_ty in params_ty.iter() { + self.walk_type_expr(Some(param_ty)); + } + } + if let Some(ret_ty) = &func_type.ret_ty { + self.walk_type_expr(Some(&ret_ty)); + } + } + } + } + None + } + + pub fn do_arguments_symbol_resolve( + &mut self, + args: &'ctx [ast::NodeRef], + kwargs: &'ctx [ast::NodeRef], + ) { + for arg in args.iter() { + self.expr(arg); + } + for kw in kwargs.iter() { + if let Some(value) = &kw.node.value { + self.expr(value); + } + let (start_pos, end_pos): Range = kw.get_span_pos(); + let value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(kw.node.arg.node.get_name(), start_pos, end_pos, None, false), + self.ctx.get_node_key(&kw.id), + ); + + if let Some(value) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { + value.sema_info = KCLSymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .get(&self.ctx.get_node_key(&kw.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + } + } + + pub(crate) fn walk_config_entries(&mut self, entries: &'ctx [ast::NodeRef]) { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + + let schema_symbol = self.ctx.current_schema_symbol.take(); + let kind = match &schema_symbol { + Some(_) => LocalSymbolScopeKind::SchemaConfig, + None => LocalSymbolScopeKind::Value, + }; + + self.enter_local_scope( + &self.ctx.current_filename.as_ref().unwrap().clone(), + start, + end, + kind, + ); + + if let Some(owner) = schema_symbol { + let cur_scope = self.ctx.scopes.last().unwrap(); + self.gs + .get_scopes_mut() + .set_owner_to_scope(*cur_scope, owner); + } + + for entry in entries.iter() { + if let Some(key) = &entry.node.key { + self.ctx.maybe_def = true; + if let Some(key_symbol_ref) = self.expr(key) { + self.set_current_schema_symbol(key_symbol_ref); + } + self.ctx.maybe_def = false; + } + + let (start, end) = entry.node.value.get_span_pos(); + + self.enter_local_scope( + &self.ctx.current_filename.as_ref().unwrap().clone(), + start, + end, + LocalSymbolScopeKind::Value, + ); + + self.expr(&entry.node.value); + self.leave_scope(); + } + self.leave_scope() + } + + pub(crate) fn set_current_schema_symbol(&mut self, key_symbol_ref: SymbolRef) { + let symbols = self.gs.get_symbols(); + + if let Some(def_symbol_ref) = symbols.get_symbol(key_symbol_ref).unwrap().get_definition() { + if let Some(node_key) = symbols.symbols_info.symbol_node_map.get(&def_symbol_ref) { + if let Some(def_ty) = self.ctx.node_ty_map.get(node_key) { + if let Some(ty) = get_possible_schema_ty(def_ty.clone()) { + self.ctx.current_schema_symbol = + self.gs.get_symbols().get_type_symbol(&ty, None); + } + } + } + } + fn get_possible_schema_ty(ty: Arc) -> Option> { + match &ty.kind { + crate::ty::TypeKind::List(ty) => get_possible_schema_ty(ty.clone()), + crate::ty::TypeKind::Dict(dict_ty) => { + get_possible_schema_ty(dict_ty.val_ty.clone()) + } + crate::ty::TypeKind::Union(_) => { + // Todo: fix union schema type + None + } + crate::ty::TypeKind::Schema(_) => Some(ty.clone()), + _ => None, + } + } + } + + pub(crate) fn resolve_decorator(&mut self, decorators: &'ctx [ast::NodeRef]) { + for decorator in decorators { + let func_ident = &decorator.node.func; + let (start, end) = func_ident.get_span_pos(); + if let kclvm_ast::ast::Expr::Identifier(id) = &func_ident.node { + let decorator_symbol = DecoratorSymbol::new(start, end, id.get_name()); + self.gs.get_symbols_mut().alloc_decorator_symbol( + decorator_symbol, + self.ctx.get_node_key(&self.ctx.cur_node), + ); + } + } + } +} diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/a.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/a.k new file mode 100644 index 000000000..b4938a73c --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/a.k @@ -0,0 +1,16 @@ +_a = 1 +schema Name: + firstName: str + lastName: str + +schema Person: + name: Name + age: int + +_person = Person { + name = Name { + firstName = "a" + lastName = "b" + } + age = 20 +} \ No newline at end of file diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/b.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/b.k new file mode 100644 index 000000000..79fa8ccc7 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/b.k @@ -0,0 +1 @@ +_b = 1 diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/c.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/c.k new file mode 100644 index 000000000..f4832d10f --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/c.k @@ -0,0 +1,2 @@ +schema TestOfMixin: + age?: int diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/d.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/d.k new file mode 100644 index 000000000..78dcd8b21 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/d.k @@ -0,0 +1,2 @@ +schema Parent: + age1?: int diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/e.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/e.k new file mode 100644 index 000000000..98fabf8f4 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/e.k @@ -0,0 +1,2 @@ +schema UnionType: + a?: int diff --git a/kclvm/sema/src/advanced_resolver/test_data/import_test/f.k b/kclvm/sema/src/advanced_resolver/test_data/import_test/f.k new file mode 100644 index 000000000..65a0fa043 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/import_test/f.k @@ -0,0 +1,2 @@ +schema UnionType: + b?: int diff --git a/kclvm/sema/src/advanced_resolver/test_data/kcl.mod b/kclvm/sema/src/advanced_resolver/test_data/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/sema/src/advanced_resolver/test_data/pkg/pkg.k b/kclvm/sema/src/advanced_resolver/test_data/pkg/pkg.k new file mode 100644 index 000000000..f8c946eff --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/pkg/pkg.k @@ -0,0 +1,5 @@ +schema Name: + name?: str + +schema Person: + name: Name = Name {name = "Alice"} diff --git a/kclvm/sema/src/advanced_resolver/test_data/schema_symbols.k b/kclvm/sema/src/advanced_resolver/test_data/schema_symbols.k new file mode 100644 index 000000000..2a2139846 --- /dev/null +++ b/kclvm/sema/src/advanced_resolver/test_data/schema_symbols.k @@ -0,0 +1,38 @@ +import import_test.a +import import_test.b +import import_test.c +import import_test.d +import import_test.e +import import_test.f as g +import pkg +import regex + +schema Main(d.Parent): + mixin [c.TestOfMixin] + name?: str + age?: int = 18 + person?: a.Person + list_union_type?: [e.UnionType|int] + dict_union_type?: {g.UnionType|int:float} + + check: + regex.match(name, r"[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*") if name + +if a._a > 1: + _c = 1 +elif a._a == 1: + _c = 2 +else: + _c = 3 + +p = Main{ + name = a._person.name.firstName + " " + a._person?.name.lastName + age = b._b + a._person?.age +} + +person = pkg.Person { + name.name = "" +} + +x = "123" +assert True, "${x}456" diff --git a/kclvm/sema/src/builtin/decorator.rs b/kclvm/sema/src/builtin/decorator.rs index 446c36e4e..6a453bfed 100644 --- a/kclvm/sema/src/builtin/decorator.rs +++ b/kclvm/sema/src/builtin/decorator.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::sync::Arc; use indexmap::IndexMap; use once_cell::sync::Lazy; @@ -22,49 +22,33 @@ macro_rules! register_decorator { register_decorator! { deprecated => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[ Parameter { name: "version".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: true, }, Parameter { name: "reason".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: true, }, Parameter { name: "strict".to_string(), - ty: Rc::new(Type::BOOL), + ty: Arc::new(Type::BOOL), has_default: true, }, ], - r#"This decorator is used to get the deprecation message according to the wrapped key-value pair. - - Examples - -------- - @deprecated(version="v1.16", reason="The age attribute was deprecated", strict=True) - schema Person: - name: str - age: int - "#, + r#"This decorator is used to get the deprecation message according to the wrapped key-value pair."#, false, None, ) info => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[], - r#"Info decorator is used to mark some compile-time information for external API queries - - Examples - -------- - @info(message="User message") - schema Person: - name: str - age: int - "#, + r#"Info decorator is used to mark some compile-time information for external API queries"#, true, Some(0), ) diff --git a/kclvm/sema/src/builtin/mod.rs b/kclvm/sema/src/builtin/mod.rs index f932c4fa5..cf6e324fb 100644 --- a/kclvm/sema/src/builtin/mod.rs +++ b/kclvm/sema/src/builtin/mod.rs @@ -4,7 +4,7 @@ pub mod decorator; pub mod string; pub mod system_module; -use std::rc::Rc; +use std::sync::Arc; use indexmap::IndexMap; use once_cell::sync::Lazy; @@ -35,41 +35,41 @@ macro_rules! register_builtin { register_builtin! { option => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[ Parameter { name: "key".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: false, }, Parameter { name: "type".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: true, }, Parameter { name: "required".to_string(), - ty: Rc::new(Type::BOOL), + ty: Arc::new(Type::BOOL), has_default: true, }, Parameter { name: "default".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, Parameter { name: "help".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: true, }, Parameter { name: "file".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: true, }, Parameter { name: "line".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, ], @@ -79,42 +79,41 @@ register_builtin! { ) print => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::NONE), &[], - r#"Prints the values to a stream, or to sys.stdout by default. - Optional keyword arguments: - sep: string inserted between values, default a space. - end: string appended after the last value, default a newline. - "#, + r#"Prints the values to a stream, or to the system stdout by default. +Optional keyword arguments: +sep: string inserted between values, default a space. +end: string appended after the last value, default a newline."#, true, - Some(0), + None, ) multiplyof => Type::function( None, - Rc::new(Type::BOOL), + Arc::new(Type::BOOL), &[ Parameter { name: "a".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: false, }, Parameter { name: "b".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: false, }, ], "Check if the modular result of a and b is 0.", - true, - Some(0), + false, + None, ) isunique => Type::function( None, - Rc::new(Type::BOOL), + Arc::new(Type::BOOL), &[ Parameter { name: "inval".to_string(), - ty: Type::list_ref(Rc::new(Type::ANY)), + ty: Type::list_ref(Arc::new(Type::ANY)), has_default: false, }, ], @@ -124,7 +123,7 @@ register_builtin! { ) len => Type::function( None, - Rc::new(Type::INT), + Arc::new(Type::INT), &[ Parameter { name: "inval".to_string(), @@ -138,11 +137,11 @@ register_builtin! { ) abs => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[ Parameter { name: "inval".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: false, }, ], @@ -152,43 +151,43 @@ register_builtin! { ) all_true => Type::function( None, - Rc::new(Type::BOOL), + Arc::new(Type::BOOL), &[ Parameter { name: "inval".to_string(), - ty: Type::list_ref(Rc::new(Type::ANY)), + ty: Type::list_ref(Arc::new(Type::ANY)), has_default: false, }, ], r#"Return True if bool(x) is True for all values x in the iterable. - If the iterable is empty, return True."#, +If the iterable is empty, return True."#, false, None, ) any_true => Type::function( None, - Rc::new(Type::BOOL), + Arc::new(Type::BOOL), &[ Parameter { name: "inval".to_string(), - ty: Type::list_ref(Rc::new(Type::ANY)), + ty: Type::list_ref(Arc::new(Type::ANY)), has_default: false, }, ], r#"Return True if bool(x) is True for any x in the iterable. - If the iterable is empty, return False."#, +If the iterable is empty, return False."#, false, None, ) hex => Type::function( None, - Rc::new(Type::STR), + Arc::new(Type::STR), &[ Parameter { name: "number".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: false, }, ], @@ -198,11 +197,11 @@ register_builtin! { ) bin => Type::function( None, - Rc::new(Type::STR), + Arc::new(Type::STR), &[ Parameter { name: "number".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: false, }, ], @@ -212,11 +211,11 @@ register_builtin! { ) oct => Type::function( None, - Rc::new(Type::STR), + Arc::new(Type::STR), &[ Parameter { name: "number".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: false, }, ], @@ -226,11 +225,11 @@ register_builtin! { ) ord => Type::function( None, - Rc::new(Type::INT), + Arc::new(Type::INT), &[ Parameter { name: "c".to_string(), - ty: Rc::new(Type::STR), + ty: Arc::new(Type::STR), has_default: false, }, ], @@ -240,7 +239,7 @@ register_builtin! { ) sorted => Type::function( None, - Type::list_ref(Rc::new(Type::ANY)), + Type::list_ref(Arc::new(Type::ANY)), &[ Parameter { name: "inval".to_string(), @@ -249,34 +248,34 @@ register_builtin! { }, Parameter { name: "reverse".to_string(), - ty: Rc::new(Type::BOOL), + ty: Arc::new(Type::BOOL), has_default: true, }, ], r#"Return a new list containing all items from the iterable in ascending order. - A custom key function can be supplied to customize the sort order, and the reverse - flag can be set to request the result in descending order."#, +A custom key function can be supplied to customize the sort order, and the reverse +flag can be set to request the result in descending order."#, false, Some(1), ) range => Type::function( None, - Type::list_ref(Rc::new(Type::INT)), + Type::list_ref(Arc::new(Type::INT)), &[ Parameter { name: "start".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, Parameter { name: "stop".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, Parameter { name: "step".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, ], @@ -286,44 +285,44 @@ register_builtin! { ) max => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[], r#"With a single iterable argument, return its biggest item. - The default keyword-only argument specifies an object to return - if the provided iterable is empty. With two or more arguments, - return the largest argument."#, +The default keyword-only argument specifies an object to return +if the provided iterable is empty. With two or more arguments, +return the largest argument."#, true, None, ) min => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[], r#"With a single iterable argument, return its smallest item. - The default keyword-only argument specifies an object to return - if the provided iterable is empty. With two or more arguments, - return the smallest argument."#, +The default keyword-only argument specifies an object to return +if the provided iterable is empty. With two or more arguments, +return the smallest argument."#, true, None, ) sum => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::ANY), &[ Parameter { name: "iterable".to_string(), - ty: Type::list_ref(Rc::new(Type::ANY)), + ty: Type::list_ref(Arc::new(Type::ANY)), has_default: false, }, Parameter { name: "start".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, ], r#"When the iterable is empty, return the start value. This function is - intended specifically for use with numeric values and may reject - non-numeric types."#, +intended specifically for use with numeric values and may reject +non-numeric types."#, false, None, ) @@ -347,10 +346,10 @@ register_builtin! { has_default: true, }, ], - r#"Equivalent to x**y (with two arguments) or x**y % z (with three arguments) + r#"Equivalent to `x ** y` (with two arguments) or `x ** y % z` (with three arguments) - Some types, such as ints, are able to use a more efficient algorithm when - invoked using the three argument form."#, +Some types, such as ints, are able to use a more efficient algorithm when +invoked using the three argument form."#, false, None, ) @@ -365,55 +364,55 @@ register_builtin! { }, Parameter { name: "ndigits".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, ], r#"Round a number to a given precision in decimal digits. - The return value is an integer if ndigits is omitted or None. - Otherwise the return value has the same type as the number. - ndigits may be negative."#, +The return value is an integer if ndigits is omitted or None. +Otherwise the return value has the same type as the number. +ndigits may be negative."#, false, None, ) zip => Type::function( None, - Type::list_ref(Rc::new(Type::ANY)), + Type::list_ref(Arc::new(Type::ANY)), &[], r#"Return a zip object whose next method returns - a tuple where the i-th element comes from the i-th iterable - argument."#, +a tuple where the i-th element comes from the i-th iterable +argument."#, true, None, ) int => Type::function( None, - Rc::new(Type::INT), + Arc::new(Type::INT), &[ Parameter { name: "number".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: false, }, Parameter { name: "base".to_string(), - ty: Rc::new(Type::INT), + ty: Arc::new(Type::INT), has_default: true, }, ], r#"Convert a number or string to an integer, or return 0 if no arguments - are given. For floating point numbers, this truncates towards zero."#, +are given. For floating point numbers, this truncates towards zero."#, false, None, ) float => Type::function( None, - Rc::new(Type::FLOAT), + Arc::new(Type::FLOAT), &[ Parameter { name: "number".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: false, }, ], @@ -423,85 +422,87 @@ register_builtin! { ) bool => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::BOOL), &[ Parameter { name: "x".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, ], r#"Returns True when the argument x is true, False otherwise. - The builtins True and False are the only two instances of the class bool. - The class bool is a subclass of the class int, and cannot be subclassed."#, +The builtin `True` and `False` are the only two instances of the class bool. +The class bool is a subclass of the class int, and cannot be subclassed."#, false, None, ) str => Type::function( None, - Rc::new(Type::ANY), + Arc::new(Type::STR), &[ Parameter { name: "x".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, ], r#"Create a new string object from the given object. - If encoding or errors is specified, then the object must - expose a data buffer that will be decoded using the - given encoding and error handler."#, +If encoding or errors is specified, then the object must +expose a data buffer that will be decoded using the +given encoding and error handler."#, false, None, ) list => Type::function( None, - Type::list_ref(Rc::new(Type::ANY)), + Type::list_ref(Arc::new(Type::ANY)), &[ Parameter { name: "x".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, ], - r#"Built-in mutable sequence. + r#"Built-in list function, which can convert other data types or construct a list. - If no argument is given, the constructor creates a new empty list. - The argument must be an iterable if specified."#, +If no argument is given, the constructor creates a new empty list. +The argument must be an iterable if specified."#, false, None, ) dict => Type::function( None, - Type::dict_ref(Rc::new(Type::ANY), Rc::new(Type::ANY)), + Type::dict_ref(Arc::new(Type::ANY), Arc::new(Type::ANY)), &[ Parameter { name: "x".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: true, }, ], - r#"Built-in mutable dict."#, + r#"Built-in dict function. + +If no argument is given, the constructor creates a new empty dict."#, true, None, ) typeof => Type::function( None, - Rc::new(Type::STR), + Arc::new(Type::STR), &[ Parameter { name: "x".to_string(), - ty: Rc::new(Type::ANY), + ty: Arc::new(Type::ANY), has_default: false, }, Parameter { name: "full_name".to_string(), - ty: Rc::new(Type::BOOL), + ty: Arc::new(Type::BOOL), has_default: true, }, ], r#"Return the type of the object"#, - true, + false, None, ) } diff --git a/kclvm/sema/src/builtin/string.rs b/kclvm/sema/src/builtin/string.rs index 64ec80594..1778afc0d 100644 --- a/kclvm/sema/src/builtin/string.rs +++ b/kclvm/sema/src/builtin/string.rs @@ -1,8 +1,9 @@ +use std::sync::Arc; + use indexmap::IndexMap; use once_cell::sync::Lazy; -use std::rc::Rc; -use crate::ty::Type; +use crate::ty::{Parameter, Type}; macro_rules! register_string_member { ($($name:ident => $ty:expr)*) => ( @@ -17,232 +18,424 @@ macro_rules! register_string_member { register_string_member! { capitalize => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::ANY), + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), &[], r#"Return a copy of the string with its first character capitalized and the rest lowercased."#, false, None, ) count => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::INT), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::INT), + &[ + Parameter { + name: "sub".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return the number of non-overlapping occurrences of substring sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation."#, false, None, ) endswith => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), + &[ + Parameter { + name: "val".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return True if the string ends with the specified suffix, otherwise return False. suffix can also be a tuple of suffixes to look for. With optional start, test beginning at that position. With optional end, stop comparing at that position."#, false, None, ) find => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::INT), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::INT), + &[ + Parameter { + name: "sub".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return the lowest index in the string where substring sub is found within the slice s[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 if sub is not found."#, false, None, ) format => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), &[], r#"Perform a string formatting operation. The string on which this method is called can contain literal text or replacement fields delimited by braces {}. Each replacement field contains either the numeric index of a positional argument, or the name of a keyword argument. Returns a copy of the string where each replacement field is replaced with the string value of the corresponding argument."#, true, None, ) index => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::INT), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::INT), + &[ + Parameter { + name: "sub".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Like str.find(), but raise an error when the substring is not found."#, false, None, ) isalpha => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if all characters in the string are alphabetic and there is at least one character, False otherwise. Alphabetic characters are those characters defined in the Unicode character database as “Letter”, i.e., those with general category property being one of “Lm”, “Lt”, “Lu”, “Ll”, or “Lo”. Note that this is different from the “Alphabetic” property defined in the Unicode Standard."#, false, None, ) isalnum => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if all characters in the string are alphanumeric and there is at least one character, False otherwise. A character c is alphanumeric if one of the following returns True: c.isalpha(), c.isdecimal(), c.isdigit(), or c.isnumeric()."#, false, None, ) isdigit => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if all characters in the string are digits and there is at least one character, False otherwise. Digits include decimal characters and digits that need special handling, such as the compatibility superscript digits. This covers digits which cannot be used to form numbers in base 10, like the Kharosthi numbers. Formally, a digit is a character that has the property value Numeric_Type=Digit or Numeric_Type=Decimal."#, false, None, ) islower => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if all cased characters in the string are lowercase and there is at least one cased character, False otherwise."#, false, None, ) isspace => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if there are only whitespace characters in the string and there is at least one character, False otherwise."#, false, None, ) istitle => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if the string is a titlecased string and there is at least one character, for example uppercase characters may only follow uncased characters and lowercase characters only cased ones. Return False otherwise."#, false, None, ) isupper => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), &[], r#"Return True if all cased characters in the string are uppercase and there is at least one cased character, False otherwise."#, false, None, ) join => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "iter".to_string(), + ty: Type::list_ref(Type::any_ref()), + has_default: false, + }, + ], r#"Return a string which is the concatenation of the strings in iterable. An error will be raised if there are any non-string values in iterable. The separator between elements is the string providing this method."#, - true, + false, None, ) lower => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), &[], r#"Return a copy of the string with all the cased characters converted to lowercase."#, - true, + false, None, ) upper => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), &[], - r#""#, - true, + r#"Return a copy of the string with all the cased characters converted to uppercase."#, + false, None, ) lstrip => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "chars".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], r#"Return a copy of the string with leading characters removed. The chars argument is a string specifying the set of characters to be removed. If omitted or None, the chars argument defaults to removing whitespace. The chars argument is not a prefix; rather, all combinations of its values are stripped:"#, - true, + false, None, ) rstrip => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "chars".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], r#"Return a copy of the string with trailing characters removed. The chars argument is a string specifying the set of characters to be removed. If omitted or None, the chars argument defaults to removing whitespace. The chars argument is not a suffix; rather, all combinations of its values are stripped:"#, - true, + false, None, ) replace => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "old".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "new".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "count".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.Return a copy of the string with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced."#, - true, + false, None, ) removeprefix => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "prefix".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], r#"If the string starts with the prefix string, return string[len(prefix):]. Otherwise, return a copy of the original string."#, - true, + false, None, ) removesuffix => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "suffix".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], r#"If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string."#, - true, + false, None, ) rfind => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::INT), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::INT), + &[ + Parameter { + name: "sub".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return the highest index in the string where substring sub is found, such that sub is contained within s[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure."#, - true, + false, None, ) rindex => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::INT), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::INT), + &[ + Parameter { + name: "sub".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Like rfind() but raises ValueError when the substring sub is not found."#, - true, + false, None, ) rsplit => Type::function( - Some(Rc::new(Type::STR)), - Type::list_ref(Rc::new(Type::STR)), - &[], + Some(Arc::new(Type::STR)), + Type::list_ref(Arc::new(Type::STR)), + &[ + Parameter { + name: "sep".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + Parameter { + name: "maxsplit".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done, the rightmost ones. If sep is not specified or None, any whitespace string is a separator. Except for splitting from the right, rsplit() behaves like split() which is described in detail below."#, - true, + false, None, ) split => Type::function( - Some(Rc::new(Type::STR)), - Type::list_ref(Rc::new(Type::STR)), - &[], + Some(Arc::new(Type::STR)), + Type::list_ref(Arc::new(Type::STR)), + &[ + Parameter { + name: "sep".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + Parameter { + name: "maxsplit".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made)."#, - true, + false, None, ) splitlines => Type::function( - Some(Rc::new(Type::STR)), - Type::list_ref(Rc::new(Type::STR)), - &[], + Some(Arc::new(Type::STR)), + Type::list_ref(Arc::new(Type::STR)), + &[ + Parameter { + name: "keepends".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], r#"Return a list of the lines in the string, breaking at line boundaries. Line breaks are not included in the resulting list unless keepends is given and true."#, - true, + false, None, ) startswith => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::BOOL), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::BOOL), + &[ + Parameter { + name: "val".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "start".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "end".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], r#"Return True if string starts with the prefix, otherwise return False. prefix can also be a tuple of prefixes to look for. With optional start, test string beginning at that position. With optional end, stop comparing string at that position."#, false, None, ) strip => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), - &[], + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), + &[ + Parameter { + name: "chars".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], r#"Return a copy of the string with the leading and trailing characters removed. The chars argument is a string specifying the set of characters to be removed. If omitted or None, the chars argument defaults to removing whitespace. The chars argument is not a prefix or suffix; rather, all combinations of its values are stripped:"#, false, None, ) title => Type::function( - Some(Rc::new(Type::STR)), - Rc::new(Type::STR), + Some(Arc::new(Type::STR)), + Arc::new(Type::STR), &[], r#"Return a titlecased version of the string where words start with an uppercase character and the remaining characters are lowercase."#, false, diff --git a/kclvm/sema/src/builtin/system_module.rs b/kclvm/sema/src/builtin/system_module.rs index 86da72ea2..12e4a1844 100644 --- a/kclvm/sema/src/builtin/system_module.rs +++ b/kclvm/sema/src/builtin/system_module.rs @@ -1,10 +1,73 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. + +use std::sync::Arc; + +use crate::ty::{Parameter, Type, TypeRef}; +use indexmap::IndexMap; +use once_cell::sync::Lazy; + +// ------------------------------ +// base64 system package +// ------------------------------ pub const BASE64: &str = "base64"; -pub const BASE64_FUNCTION_NAMES: [&str; 2] = ["encode", "decode"]; +pub const BASE64_FUNCTION_NAMES: &[&str] = &["encode", "decode"]; +macro_rules! register_base64_member { + ($($name:ident => $ty:expr)*) => ( + pub const BASE64_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_base64_member! { + encode => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encode the string `value` using the codec registered for encoding."#, + false, + None, + ) + decode => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Decode the string `value` using the codec registered for encoding."#, + false, + None, + ) +} + +// ------------------------------ +// net system package +// ------------------------------ pub const NET: &str = "net"; -pub const NET_FUNCTION_NAMES: [&str; 16] = [ +pub const NET_FUNCTION_NAMES: &[&str] = &[ "split_host_port", "join_host_port", "fqdn", @@ -22,12 +85,297 @@ pub const NET_FUNCTION_NAMES: [&str; 16] = [ "is_global_unicast_IP", "is_unspecified_IP", ]; +macro_rules! register_net_member { + ($($name:ident => $ty:expr)*) => ( + pub const NET_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_net_member! { + split_host_port => Type::function( + None, + Type::list_ref(Type::str_ref()), + &[ + Parameter { + name: "ip_end_point".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Split the `host` and `port` from the `ip_end_point`."#, + false, + None, + ) + join_host_port => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "host".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "port".to_string(), + ty: Type::union_ref(&[Type::int_ref(), Type::str_ref()]), + has_default: false, + }, + ], + r#"Merge the `host` and `port`."#, + false, + None, + ) + fqdn => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "name".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Return Fully Qualified Domain Name (FQDN)."#, + false, + None, + ) + parse_IP => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Parse ip to a real IP address."#, + false, + None, + ) + IP_string => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Get the IP string."#, + false, + None, + ) + to_IP4 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Get the IP4 form of ip."#, + false, + None, + ) + to_IP16 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Get the IP16 form of ip."#, + false, + None, + ) + is_IPv4 => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a IPv4 one."#, + false, + None, + ) + is_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a valid ip address."#, + false, + None, + ) + is_loopback_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a loopback one."#, + false, + None, + ) + is_multicast_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a multicast one."#, + false, + None, + ) + is_interface_local_multicast_IP => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a interface, local and multicast one."#, + false, + None, + ) + is_link_local_multicast_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a link local and multicast one."#, + false, + None, + ) + is_link_local_unicast_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a link local and unicast one."#, + false, + None, + ) + is_global_unicast_IP =>Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a global and unicast one."#, + false, + None, + ) + is_unspecified_IP => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "ip".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Whether ip is a unspecified one."#, + false, + None, + ) +} + +// ------------------------------ +// manifests system package +// ------------------------------ pub const MANIFESTS: &str = "manifests"; -pub const MANIFESTS_FUNCTION_NAMES: [&str; 1] = ["yaml_stream"]; +pub const MANIFESTS_FUNCTION_NAMES: &[&str] = &["yaml_stream"]; +macro_rules! register_manifests_member { + ($($name:ident => $ty:expr)*) => ( + pub const MANIFESTS_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_manifests_member! { + yaml_stream => Type::function( + None, + Type::any_ref(), + &[ + Parameter { + name: "values".to_string(), + ty: Type::any_ref(), + has_default: false, + }, + Parameter { + name: "opts".to_string(), + ty: Type::dict_ref(Type::str_ref(), Type::any_ref()), + has_default: true, + }, + ], + r#"This function is used to serialize the KCL object list into YAML output with the --- separator. It has two parameters: +values - A list of KCL objects +opts - The YAML serialization options + + sort_keys: Whether to sort the serialized results in the dictionary order of attribute names (the default is False). + + ignore_private: Whether to ignore the attribute output whose name starts with the character _ (the default value is True). + + ignore_none: Whether to ignore the attribute with the value of' None '(the default value is False). + + sep: Set the separator between multiple YAML documents (the default value is "---"). +"#, + false, + None, + ) +} + +// ------------------------------ +// math system package +// ------------------------------ pub const MATH: &str = "math"; -pub const MATH_FUNCTION_NAMES: [&str; 16] = [ +pub const MATH_FUNCTION_NAMES: &[&str] = &[ "ceil", "factorial", "floor", @@ -45,34 +393,937 @@ pub const MATH_FUNCTION_NAMES: [&str; 16] = [ "pow", "sqrt", ]; +macro_rules! register_math_member { + ($($name:ident => $ty:expr)*) => ( + pub const MATH_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_math_member! { + ceil => Type::function( + None, + Type::int_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the ceiling of `x` as an Integral. This is the smallest integer >= `x`."#, + false, + None, + ) + factorial => Type::function( + None, + Type::int_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `x`!. Raise a error if `x` is negative or non-integral."#, + false, + None, + ) + floor => Type::function( + None, + Type::int_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the floor of `x` as an Integral. This is the largest integer <= `x`."#, + false, + None, + ) + gcd => Type::function( + None, + Type::int_ref(), + &[ + Parameter { + name: "a".to_string(), + ty: Type::int_ref(), + has_default: false, + }, + Parameter { + name: "b".to_string(), + ty: Type::int_ref(), + has_default: false, + }, + ], + r#"Return the greatest common divisor of `x` and `y`."#, + false, + None, + ) + isfinite => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `True` if `x` is neither an infinity nor a NaN, and `False` otherwise."#, + false, + None, + ) + isinf => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `True` if `x` is a positive or negative infinity, and `False` otherwise."#, + false, + None, + ) + isnan => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `True` if `x` is a NaN (not a number), and `False` otherwise."#, + false, + None, + ) + modf => Type::function( + None, + Type::list_ref(Type::float_ref()), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the fractional and integer parts of `x`. Both results carry the sign of `x` and are floats."#, + false, + None, + ) + exp => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `e` raised to the power of `x`."#, + false, + None, + ) + expm1 => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `exp(x) - 1`. This function avoids the loss of precision involved in the direct evaluation of `exp(x) - 1` for small `x`."#, + false, + None, + ) + log => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + Parameter { + name: "e".to_string(), + ty: Type::float_ref(), + has_default: true, + }, + ], + r#"Return the logarithm of `x` to the base `e`."#, + false, + None, + ) + log1p => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the natural logarithm of `1+x` (base `e`). The result is computed in a way which is accurate for `x` near zero."#, + false, + None, + ) + log2 => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the base 2 logarithm of x."#, + false, + None, + ) + log10 => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the base 10 logarithm of `x`."#, + false, + None, + ) + pow => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + Parameter { + name: "y".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return `x**y` (`x` to the power of `y`)."#, + false, + None, + ) + sqrt => Type::function( + None, + Type::float_ref(), + &[ + Parameter { + name: "x".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Return the square root of `x`."#, + false, + None, + ) +} + +// ------------------------------ +// datetime system package +// ------------------------------ pub const DATETIME: &str = "datetime"; pub const DATETIME_FUNCTION_NAMES: [&str; 4] = ["today", "now", "ticks", "date"]; +macro_rules! register_datetime_member { + ($($name:ident => $ty:expr)*) => ( + pub const DATETIME_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_datetime_member! { + ticks => Type::function( + None, + Type::float_ref(), + &[], + r#"Return the current time in seconds since the Epoch. Fractions of a second may be present if the system clock provides them."#, + false, + None, + ) + date => Type::function( + None, + Type::str_ref(), + &[], + r#"Return the `%Y-%m-%d %H:%M:%S` format date."#, + false, + None, + ) + now => Type::function( + None, + Type::str_ref(), + &[], + r#"Return the local time. e.g. 'Sat Jun 06 16:26:11 1998'."#, + false, + None, + ) + today => Type::function( + None, + Type::str_ref(), + &[], + r#"Return the `%Y-%m-%d %H:%M:%S.%{ticks}` format date."#, + false, + None, + ) +} + +// ------------------------------ +// regex system package +// ------------------------------ pub const REGEX: &str = "regex"; -pub const REGEX_FUNCTION_NAMES: [&str; 6] = - ["replace", "match", "compile", "findall", "search", "split"]; +pub const REGEX_FUNCTION_NAMES: &[&str] = + &["replace", "match", "compile", "findall", "search", "split"]; +macro_rules! register_regex_member { + ($($name:ident => $ty:expr)*) => ( + pub const REGEX_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_regex_member! { + replace => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "string".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "replace".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "count".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], + r#"Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement."#, + false, + None, + ) + match => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "string".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Try to apply the pattern at the start of the string, returning a bool value `True` if any match was found, or `False` if no match was found."#, + false, + None, + ) + compile => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Compile a regular expression pattern, returning a bool value denoting whether the pattern is valid."#, + false, + None, + ) + findall => Type::function( + None, + Type::list_ref(Type::str_ref()), + &[ + Parameter { + name: "string".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Return a list of all non-overlapping matches in the string."#, + false, + None, + ) + search => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "string".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Scan through string looking for a match to the pattern, returning a bool value `True` if any match was found, or `False` if no match was found."#, + false, + None, + ) + split => Type::function( + None, + Type::list_ref(Type::str_ref()), + &[ + Parameter { + name: "string".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "maxsplit".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + ], + r#"Return a list composed of words from the string, splitting up to a maximum of `maxsplit` times using `pattern` as the separator."#, + false, + None, + ) +} + +// ------------------------------ +// yaml system package +// ------------------------------ pub const YAML: &str = "yaml"; -pub const YAML_FUNCTION_NAMES: [&str; 3] = ["encode", "decode", "dump_to_file"]; +pub const YAML_FUNCTION_NAMES: &[&str] = &[ + "encode", + "encode_all", + "decode", + "decode_all", + "dump_to_file", + "dump_all_to_file", + "validate", +]; +macro_rules! register_yaml_member { + ($($name:ident => $ty:expr)*) => ( + pub const YAML_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_yaml_member! { + encode => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::any_ref(), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a KCL object `data` to a YAML formatted str."#, + false, + Some(1), + ) + encode_all => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::list_ref(Type::any_ref()), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a sequence of KCL objects into a YAML stream str."#, + false, + Some(1), + ) + decode => Type::function( + None, + Type::any_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Deserialize `value` (a string instance containing a YAML document) to a KCL object."#, + false, + None, + ) + decode_all => Type::function( + None, + Type::list_ref(Type::any_ref()), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Parse all YAML documents in a stream and produce corresponding KCL objects."#, + false, + None, + ) + dump_to_file => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::any_ref(), + has_default: false, + }, + Parameter { + name: "filename".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a KCL object `data` to a YAML formatted str and write it into the file `filename`."#, + false, + Some(2), + ) + dump_all_to_file => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::list_ref(Type::any_ref()), + has_default: false, + }, + Parameter { + name: "filename".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a sequence of KCL objects into a YAML stream str and write it into the file `filename`."#, + false, + Some(2), + ) + validate => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Validate whether the given string is a valid YAML or YAML stream document."#, + false, + None, + ) +} + +// ------------------------------ +// json system package +// ------------------------------ pub const JSON: &str = "json"; -pub const JSON_FUNCTION_NAMES: [&str; 3] = ["encode", "decode", "dump_to_file"]; +pub const JSON_FUNCTION_NAMES: &[&str] = &["encode", "decode", "dump_to_file", "validate"]; +macro_rules! register_json_member { + ($($name:ident => $ty:expr)*) => ( + pub const JSON_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_json_member! { + encode => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::any_ref(), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "indent".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a KCL object `data` to a JSON formatted str."#, + false, + Some(1), + ) + decode => Type::function( + None, + Type::any_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Deserialize `value` (a string instance containing a JSON document) to a KCL object."#, + false, + None, + ) + dump_to_file => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "data".to_string(), + ty: Type::any_ref(), + has_default: false, + }, + Parameter { + name: "filename".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "sort_keys".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "indent".to_string(), + ty: Type::int_ref(), + has_default: true, + }, + Parameter { + name: "ignore_private".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + Parameter { + name: "ignore_none".to_string(), + ty: Type::bool_ref(), + has_default: true, + }, + ], + r#"Serialize a KCL object `data` to a YAML formatted str and write it into the file `filename`."#, + false, + Some(2), + ) + validate => Type::function( + None, + Type::bool_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Validate whether the given string is a valid JSON"#, + false, + None, + ) +} + +// ------------------------------ +// crypto system package +// ------------------------------ pub const CRYPTO: &str = "crypto"; -pub const CRYPTO_FUNCTION_NAMES: [&str; 6] = - ["md5", "sha1", "sha224", "sha256", "sha384", "sha512"]; +pub const CRYPTO_FUNCTION_NAMES: &[&str] = &[ + "md5", + "sha1", + "sha224", + "sha256", + "sha384", + "sha512", + "uuid", + "filesha256", +]; +macro_rules! register_crypto_member { + ($($name:ident => $ty:expr)*) => ( + pub const CRYPTO_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_crypto_member! { + md5 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `MD5` and the codec registered for encoding."#, + false, + None, + ) + sha1 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `SHA1` and the codec registered for encoding."#, + false, + None, + ) + sha224 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `SHA224` and the codec registered for encoding."#, + false, + None, + ) + sha256 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `SHA256` and the codec registered for encoding."#, + false, + None, + ) + sha384 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `SHA384` and the codec registered for encoding."#, + false, + None, + ) + sha512 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "value".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + Parameter { + name: "encoding".to_string(), + ty: Type::str_ref(), + has_default: true, + }, + ], + r#"Encrypt the string `value` using `SHA512` and the codec registered for encoding."#, + false, + None, + ) + uuid => Type::function( + None, + Type::str_ref(), + &[], + r#"Generate a random UUID."#, + false, + None, + ) + filesha256 => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "filepath".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Calculate the SHA256 hash of the file `filepath`."#, + false, + None, + ) +} -pub const TESTING: &str = "testing"; -pub const TESTING_FUNCTION_NAMES: [&str; 2] = ["arguments", "setting_file"]; +// ------------------------------ +// units system package +// ------------------------------ pub const UNITS: &str = "units"; -pub const UNITS_FUNCTION_NAMES: [&str; 13] = [ +pub const UNITS_FUNCTION_NAMES: &[&str] = &[ "to_n", "to_u", "to_m", "to_K", "to_M", "to_G", "to_T", "to_P", "to_Ki", "to_Mi", "to_Gi", "to_Ti", "to_Pi", ]; pub const UNITS_NUMBER_MULTIPLIER: &str = "NumberMultiplier"; -pub const UNITS_FIELD_NAMES: [&str; 15] = [ +pub const UNITS_FIELD_NAMES: &[&str] = &[ "n", "u", "m", @@ -89,15 +1340,313 @@ pub const UNITS_FIELD_NAMES: [&str; 15] = [ "Pi", UNITS_NUMBER_MULTIPLIER, ]; +macro_rules! register_units_member { + ($($name:ident => $ty:expr)*) => ( + pub const UNITS_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_units_member! { + n => Type::INT + u => Type::INT + m => Type::INT + k => Type::INT + K => Type::INT + M => Type::INT + G => Type::INT + T => Type::INT + P => Type::INT + Ki => Type::INT + Mi => Type::INT + Gi => Type::INT + Ti => Type::INT + Pi => Type::INT + to_n => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `n` suffix."#, + false, + None, + ) + to_u => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `u` suffix."#, + false, + None, + ) + to_m => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `m` suffix."#, + false, + None, + ) + to_K => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `K` suffix."#, + false, + None, + ) + to_M => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `M` suffix."#, + false, + None, + ) + to_G => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `G` suffix."#, + false, + None, + ) + to_T => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `T` suffix."#, + false, + None, + ) + to_P => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `P` suffix."#, + false, + None, + ) + to_Ki => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `Ki` suffix."#, + false, + None, + ) + to_Mi => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `Mi` suffix."#, + false, + None, + ) + to_Gi => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `Gi` suffix."#, + false, + None, + ) + to_Ti => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `Ti` suffix."#, + false, + None, + ) + to_Pi => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::number(), + has_default: false, + }, + ], + r#"Int literal to string with `Pi` suffix."#, + false, + None, + ) +} + +// ------------------------------ +// collection system package +// ------------------------------ pub const COLLECTION: &str = "collection"; -pub const COLLECTION_FUNCTION_NAMES: [&str; 1] = ["union_all"]; +pub const COLLECTION_FUNCTION_NAMES: &[&str] = &["union_all"]; +macro_rules! register_collection_member { + ($($name:ident => $ty:expr)*) => ( + pub const COLLECTION_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_collection_member! { + union_all => Type::function( + None, + Type::any_ref(), + &[ + Parameter { + name: "num".to_string(), + ty: Type::list_ref(Type::any_ref()), + has_default: false, + }, + ], + r#"Union all object to one object."#, + false, + None, + ) +} + +// ------------------------------ +// file system package +// ------------------------------ -pub const STANDARD_SYSTEM_MODULES: [&str; 12] = [ - COLLECTION, NET, MANIFESTS, MATH, DATETIME, REGEX, YAML, JSON, CRYPTO, BASE64, TESTING, UNITS, +pub const FILE: &str = "file"; +pub const FILE_FUNCTION_NAMES: &[&str] = &["read", "glob", "modpath", "workdir"]; +macro_rules! register_file_member { + ($($name:ident => $ty:expr)*) => ( + pub const FILE_FUNCTION_TYPES: Lazy> = Lazy::new(|| { + let mut builtin_mapping = IndexMap::default(); + $( builtin_mapping.insert(stringify!($name).to_string(), $ty); )* + builtin_mapping + }); + ) +} +register_file_member! { + read => Type::function( + None, + Type::str_ref(), + &[ + Parameter { + name: "filepath".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Read the file content from path"#, + false, + None, + ) + glob => Type::function( + None, + Type::list_ref(Type::str_ref()), + &[ + Parameter { + name: "pattern".to_string(), + ty: Type::str_ref(), + has_default: false, + }, + ], + r#"Find all paths that match a pattern"#, + false, + None, + ) + modpath => Type::function( + None, + Type::str_ref(), + &[], + r#"Read the module root path (kcl.mod file path or a single *.k file path)"#, + false, + None, + ) + workdir => Type::function( + None, + Type::str_ref(), + &[], + r#"Read the workdir"#, + false, + None, + ) +} + +pub const STANDARD_SYSTEM_MODULES: &[&str] = &[ + COLLECTION, NET, MANIFESTS, MATH, DATETIME, REGEX, YAML, JSON, CRYPTO, BASE64, UNITS, FILE, ]; -pub const STANDARD_SYSTEM_MODULE_NAMES_WITH_AT: [&str; 12] = [ +pub const STANDARD_SYSTEM_MODULE_NAMES_WITH_AT: &[&str] = &[ "@collection", "@net", "@manifests", @@ -108,8 +1657,8 @@ pub const STANDARD_SYSTEM_MODULE_NAMES_WITH_AT: [&str; 12] = [ "@json", "@crypto", "@base64", - "@testing", "@units", + "@file", ]; /// Get the system module members @@ -124,13 +1673,71 @@ pub fn get_system_module_members(name: &str) -> Vec<&str> { YAML => YAML_FUNCTION_NAMES.to_vec(), JSON => JSON_FUNCTION_NAMES.to_vec(), CRYPTO => CRYPTO_FUNCTION_NAMES.to_vec(), - TESTING => TESTING_FUNCTION_NAMES.to_vec(), UNITS => { let mut members = UNITS_FUNCTION_NAMES.to_vec(); members.append(&mut UNITS_FIELD_NAMES.to_vec()); members } COLLECTION => COLLECTION_FUNCTION_NAMES.to_vec(), + FILE => FILE_FUNCTION_NAMES.to_vec(), _ => bug!("invalid system module name '{}'", name), } } + +/// Get the system package member function type, if not found, return the any type. +pub fn get_system_member_function_ty(name: &str, func: &str) -> TypeRef { + let optional_ty = match name { + BASE64 => { + let types = BASE64_FUNCTION_TYPES; + types.get(func).cloned() + } + NET => { + let types = NET_FUNCTION_TYPES; + types.get(func).cloned() + } + MANIFESTS => { + let types = MANIFESTS_FUNCTION_TYPES; + types.get(func).cloned() + } + MATH => { + let types = MATH_FUNCTION_TYPES; + types.get(func).cloned() + } + DATETIME => { + let types = DATETIME_FUNCTION_TYPES; + types.get(func).cloned() + } + REGEX => { + let types = REGEX_FUNCTION_TYPES; + types.get(func).cloned() + } + YAML => { + let types = YAML_FUNCTION_TYPES; + types.get(func).cloned() + } + JSON => { + let types = JSON_FUNCTION_TYPES; + types.get(func).cloned() + } + CRYPTO => { + let types = CRYPTO_FUNCTION_TYPES; + types.get(func).cloned() + } + UNITS => { + let types = UNITS_FUNCTION_TYPES; + types.get(func).cloned() + } + COLLECTION => { + let types = COLLECTION_FUNCTION_TYPES; + types.get(func).cloned() + } + FILE => { + let types = FILE_FUNCTION_TYPES; + types.get(func).cloned() + } + _ => None, + }; + optional_ty + .map(|ty| Arc::new(ty)) + .unwrap_or(Type::any_ref()) +} diff --git a/kclvm/sema/src/core/global_state.rs b/kclvm/sema/src/core/global_state.rs new file mode 100644 index 000000000..b5ec23208 --- /dev/null +++ b/kclvm/sema/src/core/global_state.rs @@ -0,0 +1,545 @@ +use indexmap::IndexMap; +use kclvm_error::Position; + +use super::{ + package::{ModuleInfo, PackageDB}, + scope::{ScopeData, ScopeKind, ScopeRef}, + semantic_information::{CachedLocation, CachedRange, FileSemanticInfo, SemanticDB}, + symbol::{SymbolData, SymbolKind, SymbolRef}, +}; + +/// GlobalState is used to store semantic information of KCL source code +#[derive(Default, Debug, Clone)] +pub struct GlobalState { + // store all allocated symbols + symbols: SymbolData, + // store all allocated scopes + scopes: ScopeData, + // store package information for name mapping + packages: PackageDB, + // store semantic information after analysis + pub(crate) sema_db: SemanticDB, +} + +impl GlobalState { + pub fn get_symbols(&self) -> &SymbolData { + &self.symbols + } + + pub fn get_symbols_mut(&mut self) -> &mut SymbolData { + &mut self.symbols + } + + pub fn get_scopes(&self) -> &ScopeData { + &self.scopes + } + + pub fn get_scopes_mut(&mut self) -> &mut ScopeData { + &mut self.scopes + } + + pub fn get_packages(&self) -> &PackageDB { + &self.packages + } + + pub fn get_packages_mut(&mut self) -> &mut PackageDB { + &mut self.packages + } + + pub fn get_sema_db(&self) -> &SemanticDB { + &self.sema_db + } +} + +impl GlobalState { + /// look up symbol by name within specific scope + /// + /// # Parameters + /// + /// + /// `name`: [&str] + /// The name of symbol + /// + /// `scope_ref`: [ScopeRef] + /// the reference of scope which was allocated by [ScopeData] + /// + /// `module_info`: [Option<&ModuleInfo>] + /// the module import information + /// `local`: [bool] + /// look up in current scope + /// + /// # Returns + /// + /// result: [Option] + /// the matched symbol + pub fn look_up_symbol( + &self, + name: &str, + scope_ref: ScopeRef, + module_info: Option<&ModuleInfo>, + local: bool, + ) -> Option { + match self.scopes.get_scope(&scope_ref)?.look_up_def( + name, + &self.scopes, + &self.symbols, + module_info, + local, + ) { + None => self + .symbols + .symbols_info + .global_builtin_symbols + .get(name) + .cloned(), + some => some, + } + } + + /// look up scope by specific position + /// + /// # Parameters + /// + /// `pos`: [&Position] + /// The pos within the scope + /// + /// + /// # Returns + /// + /// result: [Option] + /// the matched scope + pub fn look_up_scope(&self, pos: &Position) -> Option { + let scopes = &self.scopes; + for root_ref in scopes.root_map.values() { + if let Some(root) = scopes.get_scope(root_ref) { + if root.contains_pos(pos) { + if let Some(inner_ref) = self.look_up_into_scope(*root_ref, pos) { + return Some(inner_ref); + } else { + return Some(*root_ref); + } + } + } + } + None + } + + fn look_up_closest_sub_scope(&self, parent: ScopeRef, pos: &Position) -> Option { + let file_sema_info = self.sema_db.file_sema_map.get(&pos.filename)?; + let loc = CachedLocation { + line: pos.line, + column: pos.column.unwrap_or(0), + }; + let children = match parent.kind { + ScopeKind::Local => &self.scopes.locals.get(parent.id)?.children, + ScopeKind::Root => &self + .scopes + .roots + .get(parent.id)? + .children + .get(&pos.filename)?, + }; + + match children.binary_search_by(|scope_ref| { + file_sema_info + .local_scope_locs + .get(scope_ref) + .unwrap() + .start + .cmp(&loc) + }) { + Ok(symbol_index) => Some(children[symbol_index]), + Err(symbol_index) => { + if symbol_index > 0 { + Some(children[symbol_index - 1]) + } else { + None + } + } + } + } + + /// get all definition symbols within specific scope + /// + /// # Parameters + /// + /// `scope`: [ScopeRef] + /// the reference of scope which was allocated by [ScopeData] + /// + /// + /// # Returns + /// + /// result: [Option>] + /// all definition symbols in the scope + pub fn get_all_defs_in_scope(&self, scope: ScopeRef) -> Option> { + let scopes = &self.scopes; + let scope = scopes.get_scope(&scope)?; + let all_defs: Vec = scope + .get_all_defs( + scopes, + &self.symbols, + self.packages.get_module_info(scope.get_filename()), + false, + ) + .values() + .into_iter() + .cloned() + .collect(); + Some(all_defs) + } + + /// look up closest symbol by specific position, which means + /// the specified position is located after the starting position of the returned symbol + /// and before the starting position of the next symbol + /// + /// # Parameters + /// + /// `pos`: [&Position] + /// The target pos + /// + /// + /// # Returns + /// + /// result: [Option] + /// the closest symbol to the target pos + pub fn look_up_closest_symbol(&self, pos: &Position) -> Option { + let file_sema_info = self.sema_db.file_sema_map.get(&pos.filename)?; + let candidate = file_sema_info.look_up_closest_symbol(&CachedLocation { + line: pos.line, + column: pos.column.unwrap_or(0), + }); + match self.look_up_scope(pos) { + Some(parent_scope_ref) => { + let candidate_symbol = self.symbols.get_symbol(candidate?)?; + let (start, _) = candidate_symbol.get_range(); + let parent_scope = self.scopes.get_scope(&parent_scope_ref)?; + if parent_scope.contains_pos(&start) { + let barrier_scope = self.look_up_closest_sub_scope(parent_scope_ref, pos); + match barrier_scope { + Some(barrier_scope) => { + let barrier_scope = self.scopes.locals.get(barrier_scope.id)?; + // there is no local scope between the candidate and the specified position + // the candidate is the answer + if barrier_scope.end.less(&candidate_symbol.get_range().0) { + candidate + } + // otherwise, it indicates that the found symbol is shadowed by the local scope. + // we just skip the scope and directly look up its start pos + else { + file_sema_info.look_up_closest_symbol(&CachedLocation { + line: barrier_scope.start.line, + column: barrier_scope.start.column.unwrap_or(0), + }) + } + } + None => candidate, + } + } else { + None + } + } + None => None, + } + } + + /// look up exact symbol by specific position, which means + /// the specified position is within the range of the returned symbol + /// + /// # Parameters + /// + /// `pos`: [&Position] + /// The target pos + /// + /// + /// # Returns + /// + /// result: [Option] + /// the exact symbol to the target pos + pub fn look_up_exact_symbol(&self, pos: &Position) -> Option { + let candidate = self + .sema_db + .file_sema_map + .get(&pos.filename)? + .look_up_closest_symbol(&CachedLocation { + line: pos.line, + column: pos.column.unwrap_or(0), + }); + let (start, end) = self.symbols.get_symbol(candidate?)?.get_range(); + if start.less_equal(pos) && pos.less_equal(&end) { + candidate + } else { + None + } + } + + fn look_up_into_scope(&self, parent: ScopeRef, pos: &Position) -> Option { + let candidate_ref = self.look_up_closest_sub_scope(parent, pos)?; + + let candidate = self.scopes.get_scope(&candidate_ref)?; + if candidate.contains_pos(pos) { + if let Some(inner_ref) = self.look_up_into_scope(candidate_ref, pos) { + return Some(inner_ref); + } else { + return Some(candidate_ref); + } + } + None + } +} + +impl GlobalState { + fn build_sema_db_with_symbols(&self, file_sema_map: &mut IndexMap) { + // put symbols + for (index, symbol) in self.symbols.schemas.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Schema, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + for (index, symbol) in self.symbols.type_aliases.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::TypeAlias, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + for (index, symbol) in self.symbols.attributes.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Attribute, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + for (index, symbol) in self.symbols.rules.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Rule, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + for (index, symbol) in self.symbols.values.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Value, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + for (index, symbol) in self.symbols.unresolved.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Unresolved, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + + for (index, symbol) in self.symbols.exprs.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Expression, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + + for (index, symbol) in self.symbols.comments.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Comment, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + + for (index, symbol) in self.symbols.decorators.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Decorator, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + + // remove dummy file + file_sema_map.remove(""); + + for (_, sema_info) in file_sema_map.iter_mut() { + sema_info + .symbols + .sort_by_key(|symbol_ref| sema_info.symbol_locs.get(symbol_ref).unwrap()) + } + } + fn build_sema_db_with_scopes(&self, file_sema_map: &mut IndexMap) { + // put scope + for (index, scope) in self.scopes.locals.iter() { + let scope_ref = ScopeRef { + kind: ScopeKind::Local, + id: index, + }; + let filename = scope.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.local_scope_locs.insert( + scope_ref, + CachedRange { + start: CachedLocation { + line: scope.start.line, + column: scope.start.column.unwrap_or(0), + }, + end: CachedLocation { + line: scope.end.line, + column: scope.end.column.unwrap_or(0), + }, + }, + ); + file_sema_map + .get_mut(&filename) + .unwrap() + .scopes + .push(scope_ref); + } + } + + fn sort_local_scopes(&mut self, file_sema_map: &IndexMap) { + // Direct sub scopes do not overlap, so we can directly sort them by start loc + for (_, root) in self.scopes.roots.iter_mut() { + for (filename, scopes) in root.children.iter_mut() { + let file_sema_info = file_sema_map.get(filename).unwrap(); + scopes.sort_by_key(|scope_ref| { + &file_sema_info + .local_scope_locs + .get(scope_ref) + .unwrap() + .start + }) + } + } + // Direct sub scopes do not overlap, so we can directly sort them by start loc + for (_, scope) in self.scopes.locals.iter_mut() { + let file_sema_info = file_sema_map.get(&scope.start.filename).unwrap(); + scope.children.sort_by_key(|scope_ref| { + &file_sema_info + .local_scope_locs + .get(scope_ref) + .unwrap() + .start + }) + } + } + + pub(crate) fn build_sema_db(&mut self) { + let mut file_sema_map = IndexMap::::default(); + self.build_sema_db_with_symbols(&mut file_sema_map); + self.build_sema_db_with_scopes(&mut file_sema_map); + self.sort_local_scopes(&mut file_sema_map); + + self.sema_db.file_sema_map = file_sema_map; + } +} diff --git a/kclvm/sema/src/core/mod.rs b/kclvm/sema/src/core/mod.rs new file mode 100644 index 000000000..14b98ccce --- /dev/null +++ b/kclvm/sema/src/core/mod.rs @@ -0,0 +1,5 @@ +pub mod global_state; +pub mod package; +pub mod scope; +pub mod semantic_information; +pub mod symbol; diff --git a/kclvm/sema/src/core/package.rs b/kclvm/sema/src/core/package.rs new file mode 100644 index 000000000..b0de5be90 --- /dev/null +++ b/kclvm/sema/src/core/package.rs @@ -0,0 +1,118 @@ +use indexmap::{IndexMap, IndexSet}; + +#[derive(Default, Debug, Clone)] +pub struct PackageDB { + pub(crate) package_info: IndexMap, + pub(crate) module_info: IndexMap, +} + +impl PackageDB { + pub fn add_package(&mut self, info: PackageInfo) { + self.package_info + .insert(info.fully_qualified_name.clone(), info); + } + + pub fn remove_package_info(&mut self, name: &str) { + self.package_info.remove(name); + } + + pub fn get_package_info(&self, name: &str) -> Option<&PackageInfo> { + self.package_info.get(name) + } + + pub fn get_package_info_mut(&mut self, name: &str) -> Option<&mut PackageInfo> { + self.package_info.get_mut(name) + } + + pub fn add_module_info(&mut self, info: ModuleInfo) { + self.module_info.insert(info.filename.clone(), info); + } + + pub fn remove_module_info(&mut self, name: &str) { + self.module_info.remove(name); + } + + pub fn get_module_info_mut(&mut self, name: &str) -> Option<&mut ModuleInfo> { + self.module_info.get_mut(name) + } + + pub fn get_module_info(&self, name: &str) -> Option<&ModuleInfo> { + self.module_info.get(name) + } +} +#[derive(Debug, Clone)] +pub struct PackageInfo { + pub(crate) fully_qualified_name: String, + pub(crate) pkg_filepath: String, + pub(crate) kfile_paths: IndexSet, +} + +impl PackageInfo { + pub fn new(fully_qualified_name: String, pkg_filepath: String) -> Self { + Self { + fully_qualified_name, + pkg_filepath, + kfile_paths: IndexSet::default(), + } + } + + pub fn get_kfile_paths(&self) -> &IndexSet { + &self.kfile_paths + } + + pub fn get_pkg_filepath(&self) -> &String { + &self.pkg_filepath + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct ImportInfo { + pub(crate) unqualified_name: String, + pub(crate) fully_qualified_name: String, +} + +impl ImportInfo { + pub fn new(unqualified_name: String, fully_qualified_name: String) -> Self { + Self { + unqualified_name, + fully_qualified_name, + } + } + + pub fn get_fully_qualified_name(&self) -> String { + self.fully_qualified_name.clone() + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct ModuleInfo { + pub(crate) filename: String, + pub(crate) pkgpath: String, + pub(crate) imports: IndexMap, +} + +impl ModuleInfo { + pub fn new(filename: String, pkgpath: String) -> Self { + Self { + filename, + pkgpath, + imports: IndexMap::default(), + } + } + + pub fn add_import_info(&mut self, info: ImportInfo) { + self.imports.insert(info.unqualified_name.clone(), info); + } + + pub fn remove_import_info(&mut self, name: &str) { + self.imports.remove(name); + } + + pub fn get_import_info(&self, name: &str) -> Option<&ImportInfo> { + self.imports.get(name) + } + + pub fn get_imports(&self) -> IndexMap { + self.imports.clone() + } +} diff --git a/kclvm/sema/src/core/scope.rs b/kclvm/sema/src/core/scope.rs new file mode 100644 index 000000000..0d98861c3 --- /dev/null +++ b/kclvm/sema/src/core/scope.rs @@ -0,0 +1,562 @@ +use std::collections::HashMap; + +use indexmap::{IndexMap, IndexSet}; +use kclvm_error::Position; +use serde::Serialize; + +use crate::core::symbol::SymbolRef; + +use super::{package::ModuleInfo, symbol::SymbolData}; + +pub trait Scope { + type SymbolData; + fn get_filename(&self) -> &str; + fn get_parent(&self) -> Option; + fn get_children(&self) -> Vec; + + fn contains_pos(&self, pos: &Position) -> bool; + fn get_range(&self) -> Option<(Position, Position)>; + + fn get_owner(&self) -> Option; + fn look_up_def( + &self, + name: &str, + scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + local: bool, + ) -> Option; + + fn get_all_defs( + &self, + scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + recursive: bool, + ) -> HashMap; + + fn dump(&self, scope_data: &ScopeData, symbol_data: &Self::SymbolData) -> Option; +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Serialize)] +pub enum ScopeKind { + Local, + Root, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub struct ScopeRef { + pub(crate) id: generational_arena::Index, + pub(crate) kind: ScopeKind, +} + +impl Serialize for ScopeRef { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let (index, generation) = self.id.into_raw_parts(); + let data = SerializableScopeRef { + i: index as u64, + g: generation, + kind: self.kind.clone(), + }; + data.serialize(serializer) + } +} + +#[derive(Debug, Clone, Serialize)] + +struct SerializableScopeRef { + i: u64, + g: u64, + kind: ScopeKind, +} + +impl ScopeRef { + pub fn get_id(&self) -> generational_arena::Index { + self.id + } + + pub fn get_kind(&self) -> ScopeKind { + self.kind + } +} + +#[derive(Default, Debug, Clone)] +pub struct ScopeData { + /// map pkgpath to root_scope + pub(crate) root_map: IndexMap, + pub(crate) locals: generational_arena::Arena, + pub(crate) roots: generational_arena::Arena, +} + +impl ScopeData { + #[inline] + pub fn get_root_scope_map(&self) -> &IndexMap { + &self.root_map + } + + pub fn get_scope(&self, scope: &ScopeRef) -> Option<&dyn Scope> { + match scope.get_kind() { + ScopeKind::Local => { + Some(self.locals.get(scope.get_id())? as &dyn Scope) + } + ScopeKind::Root => { + Some(self.roots.get(scope.get_id())? as &dyn Scope) + } + } + } + + pub fn try_get_local_scope(&self, scope: &ScopeRef) -> Option<&LocalSymbolScope> { + match scope.get_kind() { + ScopeKind::Local => Some(self.locals.get(scope.get_id())?), + ScopeKind::Root => None, + } + } + + pub fn get_root_scope(&self, name: String) -> Option { + self.root_map.get(&name).copied() + } + + pub fn add_def_to_scope(&mut self, scope: ScopeRef, name: String, symbol: SymbolRef) { + match scope.get_kind() { + ScopeKind::Local => { + if let Some(local) = self.locals.get_mut(scope.get_id()) { + local.defs.insert(name, symbol); + } + } + ScopeKind::Root => { + unreachable!("never add symbol to root scope after namer pass") + } + } + } + + pub fn add_ref_to_scope(&mut self, scope: ScopeRef, symbol: SymbolRef) { + match scope.get_kind() { + ScopeKind::Local => { + if let Some(local) = self.locals.get_mut(scope.get_id()) { + local.refs.push(symbol); + } + } + ScopeKind::Root => { + if let Some(root) = self.roots.get_mut(scope.get_id()) { + root.refs.push(symbol); + } + } + } + } + + pub fn set_owner_to_scope(&mut self, scope: ScopeRef, owner: SymbolRef) { + match scope.get_kind() { + ScopeKind::Local => { + if let Some(local) = self.locals.get_mut(scope.get_id()) { + local.owner = Some(owner); + } + } + ScopeKind::Root => { + if let Some(root) = self.roots.get_mut(scope.get_id()) { + root.owner = owner; + } + } + } + } + + pub fn alloc_root_scope(&mut self, root: RootSymbolScope) -> ScopeRef { + let filepath = root.pkgpath.clone(); + let id = self.roots.insert(root); + let scope_ref = ScopeRef { + id, + kind: ScopeKind::Root, + }; + self.root_map.insert(filepath, scope_ref); + scope_ref + } + + pub fn alloc_local_scope(&mut self, local: LocalSymbolScope) -> ScopeRef { + let id = self.locals.insert(local); + ScopeRef { + id, + kind: ScopeKind::Local, + } + } +} + +#[derive(Debug, Clone)] +pub struct RootSymbolScope { + pub(crate) pkgpath: String, + + pub(crate) filename: String, + + pub(crate) kfile_path: IndexSet, + + /// PackageSymbol of this scope + pub(crate) owner: SymbolRef, + + /// map filepath to children + pub(crate) children: IndexMap>, + + pub(crate) refs: Vec, +} + +impl Scope for RootSymbolScope { + type SymbolData = SymbolData; + fn get_filename(&self) -> &str { + &self.filename + } + + fn get_children(&self) -> Vec { + let mut children = vec![]; + for scopes in self.children.values() { + children.append(&mut scopes.clone()) + } + children + } + + fn get_parent(&self) -> Option { + None + } + + fn contains_pos(&self, pos: &Position) -> bool { + self.kfile_path.contains(&pos.filename) + } + fn get_owner(&self) -> Option { + Some(self.owner) + } + + fn look_up_def( + &self, + name: &str, + _scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + _local: bool, + ) -> Option { + let package_symbol = symbol_data.get_symbol(self.owner)?; + + package_symbol.get_attribute(name, symbol_data, module_info) + } + + fn get_all_defs( + &self, + _scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + _recursive: bool, + ) -> HashMap { + let mut all_defs_map = HashMap::new(); + if let Some(owner) = symbol_data.get_symbol(self.owner) { + let all_defs = owner.get_all_attributes(symbol_data, module_info); + + for def_ref in all_defs { + if let Some(def) = symbol_data.get_symbol(def_ref) { + all_defs_map.insert(def.get_name(), def_ref); + } + } + } + all_defs_map + } + + fn dump(&self, scope_data: &ScopeData, symbol_data: &Self::SymbolData) -> Option { + let mut output = String::from(""); + output.push_str("{\n\"scope_kind\": \"Root\",\n"); + output.push_str(&format!("\n\"pkgpath\": \"{}\",\n", self.pkgpath)); + let owner_symbol = symbol_data.get_symbol(self.owner)?; + output.push_str(&format!( + "\"owner\": {},\n", + owner_symbol.full_dump(symbol_data)? + )); + output.push_str("\"refs\": [\n"); + for (index, symbol) in self.refs.iter().enumerate() { + let symbol = symbol_data.get_symbol(*symbol)?; + output.push_str(&format!("{}", symbol.full_dump(symbol_data)?)); + if index + 1 < self.refs.len() { + output.push_str(",\n") + } + } + output.push_str("\n],\n"); + output.push_str("\"children\": {\n"); + for (index, (key, scopes)) in self.children.iter().enumerate() { + output.push_str(&format!("\"{}\": [\n", key)); + for (index, scope) in scopes.iter().enumerate() { + let scope = scope_data.get_scope(scope)?; + output.push_str(&format!("{}", scope.dump(scope_data, symbol_data)?)); + if index + 1 < scopes.len() { + output.push_str(",\n"); + } + } + output.push_str("\n]"); + if index + 1 < self.children.len() { + output.push_str(",\n"); + } + } + output.push_str("\n}\n}"); + + let val: serde_json::Value = serde_json::from_str(&output).unwrap(); + Some(serde_json::to_string_pretty(&val).ok()?) + } + + fn get_range(&self) -> Option<(Position, Position)> { + None + } +} + +impl RootSymbolScope { + pub fn new( + pkgpath: String, + filename: String, + owner: SymbolRef, + kfile_path: IndexSet, + ) -> Self { + Self { + pkgpath, + kfile_path, + filename, + owner, + children: IndexMap::default(), + refs: vec![], + } + } + + pub fn add_child(&mut self, filepath: &str, child: ScopeRef) { + if self.children.contains_key(filepath) { + self.children.get_mut(filepath).unwrap().push(child); + } else { + self.children.insert(filepath.to_string(), vec![child]); + } + } +} + +#[derive(Debug, Clone)] +pub struct LocalSymbolScope { + pub(crate) parent: ScopeRef, + pub(crate) owner: Option, + pub(crate) children: Vec, + pub(crate) defs: IndexMap, + pub(crate) refs: Vec, + + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) kind: LocalSymbolScopeKind, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum LocalSymbolScopeKind { + List, + Dict, + Quant, + Lambda, + SchemaDef, + SchemaConfig, + Value, + Check, +} + +impl Scope for LocalSymbolScope { + type SymbolData = SymbolData; + + fn get_filename(&self) -> &str { + &self.start.filename + } + + fn get_children(&self) -> Vec { + self.children.clone() + } + + fn get_parent(&self) -> Option { + Some(self.parent) + } + + fn contains_pos(&self, pos: &Position) -> bool { + self.start.filename == pos.filename + && self.start.less_equal(pos) + && pos.less_equal(&self.end) + } + + fn get_owner(&self) -> Option { + self.owner.clone() + } + + fn look_up_def( + &self, + name: &str, + scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + local: bool, + ) -> Option { + match self.defs.get(name) { + Some(symbol_ref) => return Some(*symbol_ref), + None => { + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = symbol_data.get_symbol(*owner)?; + if let Some(symbol_ref) = + owner_symbol.get_attribute(name, symbol_data, module_info) + { + return Some(symbol_ref); + } + }; + + if local { + None + } else { + let parent = scope_data.get_scope(&self.parent)?; + parent.look_up_def(name, scope_data, symbol_data, module_info, false) + } + } + } + } + + fn get_all_defs( + &self, + scope_data: &ScopeData, + symbol_data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + recursive: bool, + ) -> HashMap { + let mut all_defs_map = HashMap::new(); + if let Some(owner) = self.owner { + if let Some(owner) = symbol_data.get_symbol(owner) { + for def_ref in owner.get_all_attributes(symbol_data, module_info) { + if let Some(def) = symbol_data.get_symbol(def_ref) { + let name = def.get_name(); + if !all_defs_map.contains_key(&name) { + all_defs_map.insert(name, def_ref); + } + } + } + } + } + // In SchemaConfig, available definitions only contain keys of schema attr,i.e., `left` values in schema expr. + // but in child scope, i.e., right value in schema expr, available definitions contain all parent definitions. + // ``` + // b = "bar" + // foo = Foo{ + // bar: b + // } + // ```` + // and scope range is(use `#kind[]` to represent the range of the scope`) + // ``` + // #Root[ + // b = "bar" + // foo = Foo #SchemaConfig[{ + // bar: #Value[b] + // }] + // ] + // ```` + // At position of `bar`, the scope kind is SchemaConfig, only get the definition of bar. + // At position of seconde `b`, the scope is the child scope of SchemaConfig, need to recursively find the definition of `b`` at a higher level + if self.kind == LocalSymbolScopeKind::SchemaConfig && !recursive { + return all_defs_map; + } else { + for def_ref in self.defs.values() { + if let Some(def) = symbol_data.get_symbol(*def_ref) { + all_defs_map.insert(def.get_name(), *def_ref); + } + } + + if let Some(parent) = scope_data.get_scope(&self.parent) { + for (name, def_ref) in + parent.get_all_defs(scope_data, symbol_data, module_info, true) + { + if !all_defs_map.contains_key(&name) { + all_defs_map.insert(name, def_ref); + } + } + } + } + all_defs_map + } + + fn dump(&self, scope_data: &ScopeData, symbol_data: &Self::SymbolData) -> Option { + let mut output = String::from(""); + output.push_str("{\n\"scope_kind\": \"Local\",\n"); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\",\n"); + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = symbol_data.get_symbol(*owner)?; + output.push_str(&format!( + "\"owner\": {},\n", + owner_symbol.full_dump(symbol_data)? + )); + } + output.push_str("\"defs\": {\n"); + for (index, (key, symbol)) in self.defs.iter().enumerate() { + let symbol = symbol_data.get_symbol(*symbol)?; + output.push_str(&format!("\"{}\": {}", key, symbol.full_dump(symbol_data)?)); + if index + 1 < self.defs.len() { + output.push_str(",\n") + } + } + output.push_str("\n},\n"); + output.push_str("\"refs\": [\n"); + for (index, symbol) in self.refs.iter().enumerate() { + let symbol = symbol_data.get_symbol(*symbol)?; + output.push_str(&format!("{}", symbol.full_dump(symbol_data)?)); + if index + 1 < self.refs.len() { + output.push_str(",\n") + } + } + output.push_str("\n],"); + output.push_str("\n\"children\": [\n"); + for (index, scope) in self.children.iter().enumerate() { + let scope = scope_data.get_scope(scope)?; + output.push_str(&format!("{}", scope.dump(scope_data, symbol_data)?)); + if index + 1 < self.children.len() { + output.push_str(",\n") + } + } + output.push_str("\n]\n}"); + Some(output) + } + + fn get_range(&self) -> Option<(Position, Position)> { + Some((self.start.clone(), self.end.clone())) + } +} + +impl LocalSymbolScope { + pub fn new( + parent: ScopeRef, + start: Position, + end: Position, + kind: LocalSymbolScopeKind, + ) -> Self { + Self { + parent, + owner: None, + children: vec![], + defs: IndexMap::default(), + refs: vec![], + start, + end, + kind, + } + } + + #[inline] + pub fn get_kind(&self) -> &LocalSymbolScopeKind { + &self.kind + } + + #[inline] + pub fn add_child(&mut self, child: ScopeRef) { + self.children.push(child) + } + + #[inline] + pub fn set_owner(&mut self, owner: SymbolRef) { + self.owner = Some(owner) + } +} diff --git a/kclvm/sema/src/core/semantic_information.rs b/kclvm/sema/src/core/semantic_information.rs new file mode 100644 index 000000000..1dc3b03e7 --- /dev/null +++ b/kclvm/sema/src/core/semantic_information.rs @@ -0,0 +1,90 @@ +use indexmap::IndexMap; +use kclvm_ast::ast::AstIndex; +use std::sync::Arc; + +use super::{scope::ScopeRef, symbol::SymbolRef}; +use crate::ty::Type; +#[allow(unused)] +#[derive(Debug, Default, Clone)] +pub struct SemanticDB { + pub(crate) tys: IndexMap>, + pub(crate) file_sema_map: IndexMap, +} + +impl SemanticDB { + pub fn get_file_sema(&self, file: &str) -> Option<&FileSemanticInfo> { + self.file_sema_map.get(file) + } +} + +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct FileSemanticInfo { + pub(crate) filename: String, + pub(crate) symbols: Vec, + pub(crate) scopes: Vec, + pub(crate) symbol_locs: IndexMap, + pub(crate) local_scope_locs: IndexMap, +} + +impl FileSemanticInfo { + pub fn new(filename: String) -> Self { + Self { + filename, + symbols: vec![], + scopes: vec![], + symbol_locs: IndexMap::default(), + local_scope_locs: IndexMap::default(), + } + } + + pub fn look_up_closest_symbol(&self, loc: &CachedLocation) -> Option { + match self + .symbols + .binary_search_by(|symbol_ref| self.symbol_locs.get(symbol_ref).unwrap().cmp(loc)) + { + Ok(symbol_index) => Some(self.symbols[symbol_index]), + Err(symbol_index) => { + if symbol_index > 0 { + Some(self.symbols[symbol_index - 1]) + } else { + None + } + } + } + } + + pub fn get_symbols(&self) -> &Vec { + &self.symbols + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct CachedLocation { + pub(crate) line: u64, + pub(crate) column: u64, +} + +#[derive(Debug, Eq, PartialEq, Clone)] +pub struct CachedRange { + pub(crate) start: CachedLocation, + pub(crate) end: CachedLocation, +} + +impl Ord for CachedLocation { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match self.line.cmp(&other.line) { + core::cmp::Ordering::Equal => self.column.cmp(&other.column), + ord => return ord, + } + } +} + +impl PartialOrd for CachedLocation { + fn partial_cmp(&self, other: &Self) -> Option { + match self.line.partial_cmp(&other.line) { + Some(core::cmp::Ordering::Equal) => self.column.partial_cmp(&other.column), + ord => return ord, + } + } +} diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs new file mode 100644 index 000000000..772b2bc65 --- /dev/null +++ b/kclvm/sema/src/core/symbol.rs @@ -0,0 +1,2052 @@ +use std::sync::Arc; + +use generational_arena::Arena; +use indexmap::{IndexMap, IndexSet}; + +use kclvm_error::{diagnostic::Range, Position}; +use serde::Serialize; + +use super::package::ModuleInfo; +use crate::{ + resolver::scope::NodeKey, + ty::{Type, TypeKind, TypeRef}, +}; + +pub trait Symbol { + type SymbolData; + type SemanticInfo; + fn get_sema_info(&self) -> &Self::SemanticInfo; + fn is_global(&self) -> bool; + fn get_range(&self) -> Range; + fn get_owner(&self) -> Option; + fn get_definition(&self) -> Option; + fn get_name(&self) -> String; + fn get_id(&self) -> Option; + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option; + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool; + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec; + + fn simple_dump(&self) -> String; + + fn full_dump(&self, data: &Self::SymbolData) -> Option; +} + +pub type KCLSymbol = dyn Symbol; +#[derive(Debug, Clone, Default)] +pub struct KCLSymbolSemanticInfo { + pub ty: Option>, + pub doc: Option, +} + +pub(crate) const BUILTIN_STR_PACKAGE: &'static str = "@str"; + +#[derive(Default, Debug, Clone)] +pub struct SymbolData { + pub(crate) values: Arena, + pub(crate) packages: Arena, + pub(crate) attributes: Arena, + pub(crate) schemas: Arena, + pub(crate) type_aliases: Arena, + pub(crate) unresolved: Arena, + pub(crate) rules: Arena, + pub(crate) exprs: Arena, + pub(crate) comments: Arena, + pub(crate) decorators: Arena, + + pub(crate) symbols_info: SymbolDB, +} + +#[derive(Default, Debug, Clone)] +pub struct SymbolDB { + pub(crate) symbol_pos_set: IndexSet, + pub(crate) global_builtin_symbols: IndexMap, + pub(crate) fully_qualified_name_map: IndexMap, + pub(crate) schema_builtin_symbols: IndexMap>, + pub(crate) node_symbol_map: IndexMap, + pub(crate) symbol_node_map: IndexMap, +} + +impl SymbolData { + pub fn get_package_symbol(&self, id: SymbolRef) -> Option<&PackageSymbol> { + if matches!(id.get_kind(), SymbolKind::Package) { + self.packages.get(id.get_id()) + } else { + None + } + } + + pub fn get_value_symbol(&self, id: SymbolRef) -> Option<&ValueSymbol> { + if matches!(id.get_kind(), SymbolKind::Value) { + self.values.get(id.get_id()) + } else { + None + } + } + + pub fn get_attribute_symbol(&self, id: SymbolRef) -> Option<&AttributeSymbol> { + if matches!(id.get_kind(), SymbolKind::Attribute) { + self.attributes.get(id.get_id()) + } else { + None + } + } + + pub fn get_type_alias_symbol(&self, id: SymbolRef) -> Option<&TypeAliasSymbol> { + if matches!(id.get_kind(), SymbolKind::TypeAlias) { + self.type_aliases.get(id.get_id()) + } else { + None + } + } + + pub fn get_schema_symbol(&self, id: SymbolRef) -> Option<&SchemaSymbol> { + if matches!(id.get_kind(), SymbolKind::Schema) { + self.schemas.get(id.get_id()) + } else { + None + } + } + + pub fn get_rule_symbol(&self, id: SymbolRef) -> Option<&RuleSymbol> { + if matches!(id.get_kind(), SymbolKind::Rule) { + self.rules.get(id.get_id()) + } else { + None + } + } + + pub fn get_symbol(&self, id: SymbolRef) -> Option<&KCLSymbol> { + match id.get_kind() { + SymbolKind::Schema => self + .schemas + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Attribute => self + .attributes + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Value => self + .values + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Package => self + .packages + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::TypeAlias => self + .type_aliases + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Unresolved => self + .unresolved + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Rule => self + .rules + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Expression => self + .exprs + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Comment => self + .comments + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Decorator => self + .decorators + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), + } + } + + pub fn set_symbol_type(&mut self, id: SymbolRef, ty: TypeRef) { + match id.get_kind() { + SymbolKind::Schema => { + self.schemas.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Attribute => { + self.attributes.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Value => { + self.values.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Package => { + self.packages.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::TypeAlias => { + self.type_aliases.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Unresolved => { + self.unresolved.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Rule => { + self.rules.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Expression => { + self.exprs.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Comment => { + self.comments.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + SymbolKind::Decorator => { + self.decorators.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } + } + } + + pub fn get_type_symbol( + &self, + ty: &Type, + module_info: Option<&ModuleInfo>, + ) -> Option { + match &ty.kind { + //TODO: builtin ty symbol,now we just return none + TypeKind::None => None, + TypeKind::Any => None, + TypeKind::Void => None, + TypeKind::Bool => None, + TypeKind::BoolLit(_) => None, + TypeKind::Int => None, + TypeKind::IntLit(_) => None, + TypeKind::Float => None, + TypeKind::FloatLit(_) => None, + TypeKind::Str => self.get_symbol_by_fully_qualified_name(BUILTIN_STR_PACKAGE), + TypeKind::StrLit(_) => self.get_symbol_by_fully_qualified_name(BUILTIN_STR_PACKAGE), + TypeKind::List(_) => None, + TypeKind::Dict(_) => None, + TypeKind::NumberMultiplier(_) => None, + TypeKind::Function(_) => None, + TypeKind::Union(_) => None, + + TypeKind::Schema(schema_ty) => { + let fully_qualified_ty_name = schema_ty.pkgpath.clone() + "." + &schema_ty.name; + + self.get_symbol_by_fully_qualified_name(&fully_qualified_ty_name) + } + TypeKind::Module(module_ty) => { + self.get_symbol_by_fully_qualified_name(&module_ty.pkgpath) + } + TypeKind::Named(name) => { + let splits: Vec<&str> = name.rsplitn(2, '.').collect(); + let len = splits.len(); + let pkgname = splits[len - 1]; + + let pkgpath: &String = &module_info?.get_import_info(pkgname)?.fully_qualified_name; + let fully_qualified_ty_name = if name.contains('.') { + name.replacen(&pkgname, pkgpath, 1) + } else { + kclvm_ast::MAIN_PKG.to_string() + name + }; + + self.get_symbol_by_fully_qualified_name(&fully_qualified_ty_name) + } + } + } + + pub fn get_type_all_attribute( + &self, + ty: &Type, + name: &str, + module_info: Option<&ModuleInfo>, + ) -> Vec { + match &ty.kind { + //TODO: builtin ty symbol,now we just return none + TypeKind::None => vec![], + TypeKind::Any => vec![], + TypeKind::Void => vec![], + TypeKind::Bool => vec![], + TypeKind::BoolLit(_) => vec![], + TypeKind::Int => vec![], + TypeKind::IntLit(_) => vec![], + TypeKind::Float => vec![], + TypeKind::FloatLit(_) => vec![], + TypeKind::Str => { + let mut result = vec![]; + if let Some(symbol_ref) = self.get_type_symbol(ty, module_info) { + if let Some(symbol) = self.get_symbol(symbol_ref) { + result = symbol.get_all_attributes(self, module_info); + } + } + result + } + TypeKind::StrLit(_) => vec![], + TypeKind::List(_) => vec![], + TypeKind::Dict(_) => vec![], + TypeKind::NumberMultiplier(_) => vec![], + TypeKind::Function(_) => vec![], + TypeKind::Union(tys) => { + let mut result = vec![]; + for ty in tys.iter() { + result.append(&mut self.get_type_all_attribute(ty, name, module_info)); + } + result + } + TypeKind::Schema(_) => { + let mut result = vec![]; + if let Some(symbol_ref) = self.get_type_symbol(ty, module_info) { + if let Some(symbol) = self.get_symbol(symbol_ref) { + result = symbol.get_all_attributes(self, module_info); + } + } + result + } + TypeKind::Module(_) => { + let mut result = vec![]; + if let Some(symbol_ref) = self.get_type_symbol(ty, module_info) { + if let Some(symbol) = self.get_symbol(symbol_ref) { + result = symbol.get_all_attributes(self, module_info); + } + } + result + } + TypeKind::Named(_) => { + let mut result = vec![]; + if let Some(symbol_ref) = self.get_type_symbol(ty, module_info) { + if let Some(symbol) = self.get_symbol(symbol_ref) { + result = symbol.get_all_attributes(self, module_info); + } + } + result + } + } + } + + pub fn get_type_attribute( + &self, + ty: &Type, + name: &str, + module_info: Option<&ModuleInfo>, + ) -> Option { + match &ty.kind { + TypeKind::None => None, + TypeKind::Any => None, + TypeKind::Void => None, + TypeKind::Bool => None, + TypeKind::BoolLit(_) => None, + TypeKind::Int => None, + TypeKind::IntLit(_) => None, + TypeKind::Float => None, + TypeKind::FloatLit(_) => None, + TypeKind::Str => self + .get_symbol(self.get_type_symbol(ty, module_info)?)? + .get_attribute(name, self, module_info), + TypeKind::StrLit(_) => self + .get_symbol(self.get_type_symbol(ty, module_info)?)? + .get_attribute(name, self, module_info), + TypeKind::List(_) => None, + TypeKind::Dict(_) => None, + TypeKind::NumberMultiplier(_) => None, + TypeKind::Function(_) => None, + TypeKind::Union(tys) => { + for ty in tys.iter() { + if let Some(symbol_ref) = self.get_type_attribute(ty, name, module_info) { + return Some(symbol_ref); + } + } + None + } + TypeKind::Schema(_) => self + .get_symbol(self.get_type_symbol(ty, module_info)?)? + .get_attribute(name, self, module_info), + TypeKind::Module(_) => self + .get_symbol(self.get_type_symbol(ty, module_info)?)? + .get_attribute(name, self, module_info), + TypeKind::Named(_) => self + .get_symbol(self.get_type_symbol(ty, module_info)?)? + .get_attribute(name, self, module_info), + } + } + + pub fn get_symbol_by_fully_qualified_name(&self, fqn: &str) -> Option { + self.symbols_info.fully_qualified_name_map.get(fqn).cloned() + } + + pub fn get_fully_qualified_name(&self, symbol_ref: SymbolRef) -> Option { + match symbol_ref.get_kind() { + SymbolKind::Unresolved => None, + _ => { + let symbol = self.get_symbol(symbol_ref)?; + let owner = symbol.get_owner(); + if let Some(owner) = owner { + Some(self.get_fully_qualified_name(owner)? + "." + &symbol.get_name()) + } else { + Some(symbol.get_name()) + } + } + } + } + + pub fn build_fully_qualified_name_map(&mut self) { + for (id, _) in self.packages.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Package, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.schemas.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Schema, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.type_aliases.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::TypeAlias, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.attributes.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Attribute, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.rules.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Rule, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.values.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Value, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + } + + pub fn alloc_package_symbol(&mut self, pkg: PackageSymbol) -> SymbolRef { + let symbol_id = self.packages.insert(pkg); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Package, + }; + self.packages.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_schema_symbol(&mut self, schema: SchemaSymbol, node_key: NodeKey) -> SymbolRef { + self.symbols_info.symbol_pos_set.insert(schema.end.clone()); + let symbol_id = self.schemas.insert(schema); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Schema, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.schemas.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_unresolved_symbol( + &mut self, + unresolved: UnresolvedSymbol, + node_key: NodeKey, + ) -> SymbolRef { + self.symbols_info + .symbol_pos_set + .insert(unresolved.end.clone()); + let symbol_id = self.unresolved.insert(unresolved); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Unresolved, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.unresolved.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_type_alias_symbol( + &mut self, + alias: TypeAliasSymbol, + node_key: NodeKey, + ) -> SymbolRef { + self.symbols_info.symbol_pos_set.insert(alias.end.clone()); + let symbol_id = self.type_aliases.insert(alias); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::TypeAlias, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.type_aliases.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_rule_symbol(&mut self, rule: RuleSymbol, node_key: NodeKey) -> SymbolRef { + self.symbols_info.symbol_pos_set.insert(rule.end.clone()); + let symbol_id = self.rules.insert(rule); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Rule, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.rules.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_attribute_symbol( + &mut self, + attribute: AttributeSymbol, + node_key: NodeKey, + ) -> SymbolRef { + self.symbols_info + .symbol_pos_set + .insert(attribute.end.clone()); + let symbol_id = self.attributes.insert(attribute); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Attribute, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.attributes.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_value_symbol(&mut self, value: ValueSymbol, node_key: NodeKey) -> SymbolRef { + self.symbols_info.symbol_pos_set.insert(value.end.clone()); + let symbol_id = self.values.insert(value); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Value, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.values.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_expression_symbol( + &mut self, + expr: ExpressionSymbol, + node_key: NodeKey, + ) -> Option { + if self.symbols_info.symbol_pos_set.contains(&expr.end) { + return None; + } + self.symbols_info.symbol_pos_set.insert(expr.end.clone()); + let symbol_id = self.exprs.insert(expr); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Expression, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.exprs.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + Some(symbol_ref) + } + + pub fn alloc_comment_symbol( + &mut self, + comment: CommentSymbol, + node_key: NodeKey, + ) -> Option { + let symbol_id = self.comments.insert(comment); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Comment, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.comments.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + Some(symbol_ref) + } + + pub fn alloc_decorator_symbol( + &mut self, + decorator: DecoratorSymbol, + node_key: NodeKey, + ) -> Option { + let symbol_id = self.decorators.insert(decorator); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Decorator, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_node_map + .insert(symbol_ref, node_key); + self.decorators.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + Some(symbol_ref) + } + + #[inline] + pub fn get_node_symbol_map(&self) -> &IndexMap { + &self.symbols_info.node_symbol_map + } + + #[inline] + pub fn get_symbol_node_map(&self) -> &IndexMap { + &self.symbols_info.symbol_node_map + } + + #[inline] + pub fn get_fully_qualified_name_map(&self) -> &IndexMap { + &self.symbols_info.fully_qualified_name_map + } + + #[inline] + pub fn get_builtin_symbols(&self) -> &IndexMap { + &self.symbols_info.global_builtin_symbols + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] +pub enum SymbolKind { + Schema, + Attribute, + Value, + Package, + TypeAlias, + Unresolved, + Rule, + Expression, + Comment, + Decorator, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct SymbolRef { + pub(crate) id: generational_arena::Index, + pub(crate) kind: SymbolKind, +} + +impl Serialize for SymbolRef { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let (index, generation) = self.id.into_raw_parts(); + let data = SerializableSymbolRef { + i: index as u64, + g: generation, + kind: self.kind.clone(), + }; + data.serialize(serializer) + } +} + +#[derive(Debug, Clone, Serialize)] + +struct SerializableSymbolRef { + i: u64, + g: u64, + kind: SymbolKind, +} + +impl SymbolRef { + #[inline] + pub fn get_kind(&self) -> SymbolKind { + self.kind + } + #[inline] + pub fn get_id(&self) -> generational_arena::Index { + self.id + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct SchemaSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, + pub(crate) sema_info: KCLSymbolSemanticInfo, + + pub(crate) parent_schema: Option, + pub(crate) for_host: Option, + pub(crate) mixins: Vec, + pub(crate) attributes: IndexMap, +} + +impl Symbol for SchemaSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + true + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + Some(self.owner) + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + match self.attributes.get(name) { + Some(attribute) => Some(*attribute), + None => { + if let Some(parent_schema) = self.parent_schema { + if let Some(attribute) = + data.get_symbol(parent_schema)? + .get_attribute(name, data, module_info) + { + return Some(attribute); + } + } + + if let Some(for_host) = self.for_host { + if let Some(attribute) = + data.get_symbol(for_host)? + .get_attribute(name, data, module_info) + { + return Some(attribute); + } + } + + for mixin in self.mixins.iter() { + if let Some(attribute) = + data.get_symbol(*mixin)? + .get_attribute(name, data, module_info) + { + return Some(attribute); + } + } + + None + } + } + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + for attribute in self.attributes.values() { + result.push(*attribute); + } + if let Some(parent_schema) = self.parent_schema { + if let Some(parent) = data.get_symbol(parent_schema) { + result.append(&mut parent.get_all_attributes(data, module_info)) + } + } + + if let Some(for_host) = self.for_host { + if let Some(for_host) = data.get_symbol(for_host) { + result.append(&mut for_host.get_all_attributes(data, module_info)) + } + } + for mixin in self.mixins.iter() { + if let Some(mixin) = data.get_symbol(*mixin) { + result.append(&mut mixin.get_all_attributes(data, module_info)) + } + } + result + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"SchemaSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + let owner_symbol = data.get_symbol(self.owner)?; + output.push_str(&format!("\"owner\": {},\n", owner_symbol.simple_dump())); + if let Some(parent_schema) = self.parent_schema.as_ref() { + let parent_schema_symbol = data.get_symbol(*parent_schema)?; + output.push_str(&format!( + "\"parent_schema\": {},\n", + parent_schema_symbol.simple_dump() + )); + } + if let Some(parent_schema) = self.for_host.as_ref() { + let host_symbol = data.get_symbol(*parent_schema)?; + output.push_str(&format!("\"for_host\": {},\n", host_symbol.simple_dump())); + } + output.push_str("\"mixins\": [\n"); + for (index, mixin) in self.mixins.iter().enumerate() { + let mixin_symbol = data.get_symbol(*mixin)?; + output.push_str(&format!("{}", mixin_symbol.simple_dump())); + if index + 1 < self.mixins.len() { + output.push_str(",\n") + } + } + output.push_str("\n],\n"); + output.push_str("\"attributes\": {\n"); + for (index, (key, attribute)) in self.attributes.iter().enumerate() { + let attribute_symbol = data.get_symbol(*attribute)?; + output.push_str(&format!("\"{}\": {}", key, attribute_symbol.simple_dump())); + if index + 1 < self.attributes.len() { + output.push_str(",\n") + } + } + output.push_str("\n}\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl SchemaSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + parent_schema: None, + for_host: None, + sema_info: KCLSymbolSemanticInfo::default(), + mixins: Vec::default(), + attributes: IndexMap::default(), + } + } +} + +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct ValueSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: Option, + pub(crate) sema_info: KCLSymbolSemanticInfo, + + pub(crate) is_global: bool, +} + +impl Symbol for ValueSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + self.is_global + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + self.owner.clone() + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + data.get_type_attribute(self.sema_info.ty.as_ref()?, name, module_info) + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + if let Some(ty) = self.sema_info.ty.as_ref() { + if let Some(symbol_ref) = data.get_type_symbol(ty, module_info) { + if let Some(symbol) = data.get_symbol(symbol_ref) { + result.append(&mut symbol.get_all_attributes(data, module_info)) + } + } + } + + result + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"ValueSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = data.get_symbol(*owner)?; + output.push_str(&format!("\"owner\": {}\n", owner_symbol.simple_dump())); + } + output.push_str("\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl ValueSymbol { + pub fn new( + name: String, + start: Position, + end: Position, + owner: Option, + is_global: bool, + ) -> Self { + Self { + id: None, + name, + start, + end, + owner, + sema_info: KCLSymbolSemanticInfo::default(), + is_global, + } + } +} + +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct AttributeSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for AttributeSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + true + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + Some(self.owner) + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + let ty = self.sema_info.ty.as_ref()?; + data.get_type_attribute(ty, name, module_info) + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + if module_info.is_none() { + return result; + } + if let Some(ty) = self.sema_info.ty.as_ref() { + if let Some(symbol_ref) = data.get_type_symbol(ty, module_info) { + if let Some(symbol) = data.get_symbol(symbol_ref) { + result.append(&mut symbol.get_all_attributes(data, module_info)) + } + } + } + + result + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"AttributeSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + let owner_symbol = data.get_symbol(self.owner)?; + output.push_str(&format!("\"owner\": {}\n", owner_symbol.simple_dump())); + output.push_str("\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl AttributeSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + sema_info: KCLSymbolSemanticInfo::default(), + owner, + } + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct PackageSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) members: IndexMap, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for PackageSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + true + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + None + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Option { + self.members.get(name).cloned() + } + + fn get_all_attributes( + &self, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + for member in self.members.values() { + result.push(*member); + } + result + } + + fn has_attribute( + &self, + name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> bool { + self.members.contains_key(name) + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"PackageSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + output.push_str("\"members\": {\n"); + for (index, (key, member)) in self.members.iter().enumerate() { + let member_symbol = data.get_symbol(*member)?; + output.push_str(&format!("\"{}\": {}", key, member_symbol.simple_dump())); + if index + 1 < self.members.len() { + output.push_str(",\n"); + } + } + output.push_str("\n}\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl PackageSymbol { + pub fn new(name: String, start: Position, end: Position) -> Self { + Self { + id: None, + name, + start, + end, + sema_info: KCLSymbolSemanticInfo::default(), + members: IndexMap::default(), + } + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct TypeAliasSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for TypeAliasSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + true + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + Some(self.owner) + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + let ty = self.sema_info.ty.as_ref()?; + data.get_type_attribute(ty, name, module_info) + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + if let Some(ty) = self.sema_info.ty.as_ref() { + if let Some(symbol_ref) = data.get_type_symbol(ty, module_info) { + if let Some(symbol) = data.get_symbol(symbol_ref) { + result.append(&mut symbol.get_all_attributes(data, module_info)) + } + } + } + result + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"TypeAliasSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + let owner_symbol = data.get_symbol(self.owner)?; + output.push_str(&format!( + "\"owner\": {}\n}}\n}}", + owner_symbol.simple_dump() + )); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl TypeAliasSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + sema_info: KCLSymbolSemanticInfo::default(), + owner, + } + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct RuleSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, + pub(crate) sema_info: KCLSymbolSemanticInfo, + + pub(crate) parent_rules: Vec, + pub(crate) for_host: Option, +} + +impl Symbol for RuleSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + true + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + Some(self.owner) + } + + fn get_definition(&self) -> Option { + self.id.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Option { + None + } + + fn get_all_attributes( + &self, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Vec { + vec![] + } + + fn has_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> bool { + false + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"RuleSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + let owner_symbol = data.get_symbol(self.owner)?; + output.push_str(&format!("\"owner\": {},\n", owner_symbol.simple_dump())); + + if let Some(parent_schema) = self.for_host.as_ref() { + let host_symbol = data.get_symbol(*parent_schema)?; + output.push_str(&format!("\"for_host\": {},\n", host_symbol.simple_dump())); + } + output.push_str("\"parent_rules\": [\n"); + for (index, parent_rule) in self.parent_rules.iter().enumerate() { + let parent_symbol = data.get_symbol(*parent_rule)?; + output.push_str(&format!("{}", parent_symbol.simple_dump())); + if index + 1 < self.parent_rules.len() { + output.push_str(",\n") + } + } + output.push_str("\n]\n}\n}"); + + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl RuleSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + sema_info: KCLSymbolSemanticInfo::default(), + parent_rules: vec![], + for_host: None, + } + } +} +#[allow(unused)] +#[derive(Debug, Clone)] +pub struct UnresolvedSymbol { + pub(crate) id: Option, + pub(crate) def: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: Option, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for UnresolvedSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + false + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + self.owner.clone() + } + + fn get_definition(&self) -> Option { + self.def.clone() + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + data.get_symbol(self.def?)? + .get_attribute(name, data, module_info) + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + if let Some(def) = self.def { + if let Some(def_symbol) = data.get_symbol(def) { + return def_symbol.get_all_attributes(data, module_info); + } + } + vec![] + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"UnresolvedSymbol\",\n"); + output.push_str(&format!("\"name\":\"{}\",\n", self.name)); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + if let Some(def) = self.def.as_ref() { + let def_symbol = data.get_symbol(*def)?; + output.push_str(&format!("\"def\": {}\n", def_symbol.simple_dump())); + } + output.push_str("\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl UnresolvedSymbol { + pub fn new(name: String, start: Position, end: Position, owner: Option) -> Self { + Self { + id: None, + def: None, + name, + start, + end, + sema_info: KCLSymbolSemanticInfo::default(), + owner, + } + } + + pub fn get_fully_qualified_name(&self, module_info: &ModuleInfo) -> String { + let names: Vec<_> = self.name.split('.').collect(); + let pkg_path = if names.len() == 1 { + kclvm_ast::MAIN_PKG.to_string() + } else { + let pkg_alias = names.first().unwrap(); + let import_info = module_info.get_import_info(*pkg_alias); + match import_info { + Some(info) => info.fully_qualified_name.clone(), + None => kclvm_ast::MAIN_PKG.to_string(), + } + }; + + pkg_path + "." + names.last().unwrap() + } +} + +#[derive(Debug, Clone)] +pub struct ExpressionSymbol { + pub(crate) id: Option, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: Option, + pub(crate) name: String, + + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for ExpressionSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn is_global(&self) -> bool { + false + } + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + self.owner.clone() + } + + fn get_definition(&self) -> Option { + self.id + } + + fn get_name(&self) -> String { + self.name.clone() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Option { + data.get_type_attribute(self.sema_info.ty.as_ref()?, name, module_info) + } + + fn get_all_attributes( + &self, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> Vec { + let mut result = vec![]; + if let Some(ty) = self.sema_info.ty.as_ref() { + if let Some(symbol_ref) = data.get_type_symbol(ty, module_info) { + if let Some(symbol) = data.get_symbol(symbol_ref) { + result.append(&mut symbol.get_all_attributes(data, module_info)) + } + } + } + + result + } + + fn has_attribute( + &self, + name: &str, + data: &Self::SymbolData, + module_info: Option<&ModuleInfo>, + ) -> bool { + self.get_attribute(name, data, module_info).is_some() + } + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"ExpressionSymbol\",\n"); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, data: &Self::SymbolData) -> Option { + let mut output = format!("{{\n\"simple_info\": {},\n", self.simple_dump()); + output.push_str("\"additional_info\": {\n"); + if let Some(owner) = self.owner.as_ref() { + let owner_symbol = data.get_symbol(*owner)?; + output.push_str(&format!("\"owner\": {}\n", owner_symbol.simple_dump())); + } + output.push_str("\n}\n}"); + Some(output) + } + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } +} + +impl ExpressionSymbol { + pub fn new(name: String, start: Position, end: Position, owner: Option) -> Self { + Self { + id: None, + name, + start, + end, + sema_info: KCLSymbolSemanticInfo::default(), + owner, + } + } +} + +#[derive(Debug, Clone)] +pub struct CommentSymbol { + pub(crate) id: Option, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) content: String, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for CommentSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } + + fn is_global(&self) -> bool { + true + } + + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + None + } + + fn get_definition(&self) -> Option { + self.id + } + + fn get_name(&self) -> String { + self.name() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Option { + None + } + + fn has_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> bool { + false + } + + fn get_all_attributes( + &self, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Vec { + vec![] + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"CommentSymbol\",\n"); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str(&format!("content :{}", self.name())); + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, _data: &Self::SymbolData) -> Option { + Some(self.simple_dump()) + } +} + +impl CommentSymbol { + pub fn new(start: Position, end: Position, content: String) -> Self { + Self { + id: None, + start, + end, + content, + sema_info: KCLSymbolSemanticInfo::default(), + } + } + + pub fn name(&self) -> String { + format!("# {}", self.content) + } +} + +#[derive(Debug, Clone)] +pub struct DecoratorSymbol { + pub(crate) id: Option, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) name: String, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for DecoratorSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } + + fn is_global(&self) -> bool { + true + } + + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + None + } + + fn get_definition(&self) -> Option { + self.id + } + + fn get_name(&self) -> String { + self.name() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Option { + None + } + + fn has_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> bool { + false + } + + fn get_all_attributes( + &self, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Vec { + vec![] + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"CommentSymbol\",\n"); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str(&format!("name :{}", self.name())); + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, _data: &Self::SymbolData) -> Option { + Some(self.simple_dump()) + } +} + +impl DecoratorSymbol { + pub fn new(start: Position, end: Position, name: String) -> Self { + Self { + id: None, + start, + end, + name, + sema_info: KCLSymbolSemanticInfo::default(), + } + } + + pub fn name(&self) -> String { + self.name.clone() + } +} diff --git a/kclvm/sema/src/info/mod.rs b/kclvm/sema/src/info/mod.rs index f025de680..c57844717 100644 --- a/kclvm/sema/src/info/mod.rs +++ b/kclvm/sema/src/info/mod.rs @@ -1,4 +1,12 @@ +use regex::Regex; + #[inline] pub fn is_private_field(name: &str) -> bool { name.starts_with('_') } + +#[inline] +pub fn is_valid_kcl_name(name: &str) -> bool { + let re = Regex::new(r#"^[a-zA-Z_][a-zA-Z0-9_]*$"#).unwrap(); + re.is_match(name) +} diff --git a/kclvm/sema/src/lib.rs b/kclvm/sema/src/lib.rs index 9a90ffecf..3f119adbf 100644 --- a/kclvm/sema/src/lib.rs +++ b/kclvm/sema/src/lib.rs @@ -1,11 +1,17 @@ +pub mod advanced_resolver; pub mod builtin; +pub mod core; pub mod eval; pub mod info; pub mod lint; +pub mod namer; pub mod plugin; pub mod pre_process; pub mod resolver; pub mod ty; +#[macro_use] +mod macros; + #[macro_use] extern crate compiler_base_macros; diff --git a/kclvm/sema/src/lint/LICENSE b/kclvm/sema/src/lint/LICENSE new file mode 100644 index 000000000..989e2c59e --- /dev/null +++ b/kclvm/sema/src/lint/LICENSE @@ -0,0 +1,201 @@ +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. \ No newline at end of file diff --git a/kclvm/sema/src/lint/lints_def.rs b/kclvm/sema/src/lint/lints_def.rs index dc66f5797..08663946f 100644 --- a/kclvm/sema/src/lint/lints_def.rs +++ b/kclvm/sema/src/lint/lints_def.rs @@ -4,7 +4,8 @@ use crate::resolver::scope::Scope; use crate::{declare_lint_pass, resolver::scope::ScopeObjectKind}; use indexmap::IndexSet; use kclvm_ast::ast; -use kclvm_error::{Handler, Level, Message, Position, Style, WarningKind}; +use kclvm_ast::pos::GetPos; +use kclvm_error::{Handler, Level, Message, Style, WarningKind}; /// The 'import_position' lint detects import statements that are not declared at the top of file. /// ### Example @@ -30,7 +31,12 @@ pub static IMPORT_POSITION: &Lint = &Lint { declare_lint_pass!(ImportPosition => [IMPORT_POSITION]); impl LintPass for ImportPosition { - fn check_module(&mut self, handler: &mut Handler, ctx: &mut LintContext, module: &ast::Module) { + fn check_module( + &mut self, + handler: &mut Handler, + _ctx: &mut LintContext, + module: &ast::Module, + ) { let mut first_non_importstmt = std::u64::MAX; for stmt in &module.body { match &stmt.node { @@ -48,11 +54,7 @@ impl LintPass for ImportPosition { handler.add_warning( WarningKind::ImportPositionWarning, &[Message { - pos: Position { - filename: ctx.filename.clone(), - line: stmt.line, - column: None, - }, + range: stmt.get_span_pos(), style: Style::Line, message: format!( "Importstmt should be placed at the top of the module" @@ -60,6 +62,7 @@ impl LintPass for ImportPosition { note: Some( "Consider moving tihs statement to the top of the file".to_string(), ), + suggested_replacement: None, }], ); } @@ -97,20 +100,21 @@ impl LintPass for UnusedImport { let scope_objs = &scope.elems; for (_, scope_obj) in scope_objs { let scope_obj = scope_obj.borrow(); - if scope_obj.kind == ScopeObjectKind::Module && scope_obj.used == false { - handler.add_warning( - WarningKind::UnusedImportWarning, - &[Message { - pos: Position { - filename: scope_obj.start.filename.clone(), - line: scope_obj.start.line, - column: None, - }, - style: Style::Line, - message: format!("Module '{}' imported but unused", scope_obj.name), - note: Some("Consider removing this statement".to_string()), - }], - ); + if let ScopeObjectKind::Module(m) = &scope_obj.kind { + for (stmt, has_used) in &m.import_stmts { + if !has_used { + handler.add_warning( + WarningKind::UnusedImportWarning, + &[Message { + range: stmt.get_span_pos(), + style: Style::Line, + message: format!("Module '{}' imported but unused", scope_obj.name), + note: Some("Consider removing this statement".to_string()), + suggested_replacement: None, + }], + ); + } + } } } } @@ -141,29 +145,31 @@ pub static REIMPORT: &Lint = &Lint { declare_lint_pass!(ReImport => [REIMPORT]); impl LintPass for ReImport { - fn check_module(&mut self, handler: &mut Handler, ctx: &mut LintContext, module: &ast::Module) { + fn check_module( + &mut self, + handler: &mut Handler, + _ctx: &mut LintContext, + module: &ast::Module, + ) { let mut import_names = IndexSet::::new(); for stmt in &module.body { if let ast::Stmt::Import(import_stmt) = &stmt.node { - if import_names.contains(&import_stmt.path) { + if import_names.contains(&import_stmt.path.node) { handler.add_warning( WarningKind::ReimportWarning, &[Message { - pos: Position { - filename: ctx.filename.clone(), - line: stmt.line, - column: None, - }, + range: stmt.get_span_pos(), style: Style::Line, message: format!( "Module '{}' is reimported multiple times", &import_stmt.name ), note: Some("Consider removing this statement".to_string()), + suggested_replacement: None, }], ); } else { - import_names.insert(import_stmt.path.clone()); + import_names.insert(import_stmt.path.node.clone()); } } } diff --git a/kclvm/sema/src/lint/mod.rs b/kclvm/sema/src/lint/mod.rs index 3d0da1698..f60613a66 100644 --- a/kclvm/sema/src/lint/mod.rs +++ b/kclvm/sema/src/lint/mod.rs @@ -1,3 +1,5 @@ +//! The design and implementation of KCL Lint refer to the [rust-lang/rustc](https://github.com/rust-lang/rust) lint and follow Apache License Version 2.0 +//! //! This file is the implementation of KCLLint, which is used to perform some additional checks on KCL code. //! The main structures of the file are Lint, LintPass, CombinedLintPass and Linter. //! For details see the: https://github.com/kcl-lang/kcl/issues/109 diff --git a/kclvm/sema/src/macros.rs b/kclvm/sema/src/macros.rs new file mode 100644 index 000000000..8848527c2 --- /dev/null +++ b/kclvm/sema/src/macros.rs @@ -0,0 +1,11 @@ +//! Copyright The KCL Authors. All rights reserved. + +#[macro_export] +macro_rules! pkgpath_without_prefix { + ($pkgpath: expr) => { + match $pkgpath.strip_prefix('@') { + Some(v) => v.to_string(), + None => $pkgpath.to_string(), + } + }; +} diff --git a/kclvm/sema/src/namer/mod.rs b/kclvm/sema/src/namer/mod.rs new file mode 100644 index 000000000..965d02670 --- /dev/null +++ b/kclvm/sema/src/namer/mod.rs @@ -0,0 +1,341 @@ +/* + ┌─────────────────────────────────────────────────────────────────────────────────────────────────┐ + │ namer │ + ├─────────────────────────────────────────────────────────────────────────────────────────────────┤ + │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ + │ │ ast::Expression │ │ ast::Expression │ │ ast::Expression │ │ + │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ + │ │ │ │ │ + │ │ find_symbols │ find_symbols │ find_symbols │ + │ ▼ ▼ ▼ │ + │ ┌─────────────────────────┐ ┌─────────────────────────┐ ┌─────────────────────────┐ │ + │ │ core::SymbolRef │ │ core::SymbolRef │ │ core::SymbolRef │ │ + │ └─────────────────────────┘ └─────────────────────────┘ └─────────────────────────┘ │ + │ │ │ │ │ + │ │ │ │ │ + │ └───────────────────────────────┼───────────────────────────────┘ │ + │ │ │ + │ │ merge findSymbols results │ + │ ▼ │ + │ ┌─────────────────────────┐ │ + │ │ core::SymbolRef │ │ + │ └─────────────────────────┘ │ + │ │ │ + │ │ define_symbols(FQN) │ + │ ■ │ + │ (mutates GlobalState) | + │ │ + └─────────────────────────────────────────────────────────────────────────────────────────────────┘ + + The early stage of the namer will be based on file level , which collects global symbols defined in the file, + and then merges the symbols based on FQN to obtain a unique GlobalState + + Based on file level, it means that we can easily perform incremental compilation in the future + + Now we just run namer pass serially + +*/ + +use std::path::Path; +use std::sync::Arc; + +use crate::builtin::{ + get_system_member_function_ty, get_system_module_members, BUILTIN_FUNCTIONS, + STANDARD_SYSTEM_MODULES, STRING_MEMBER_FUNCTIONS, +}; +use crate::core::global_state::GlobalState; +use crate::core::package::{ModuleInfo, PackageInfo}; +use crate::core::symbol::{PackageSymbol, SymbolRef, ValueSymbol, BUILTIN_STR_PACKAGE}; +use crate::resolver::scope::NodeKey; +use indexmap::IndexSet; +use kclvm_ast::ast::AstIndex; +use kclvm_ast::ast::Program; +use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_error::Position; +mod node; + +pub const BUILTIN_SYMBOL_PKG_PATH: &str = "@builtin"; + +pub struct Namer<'ctx> { + gs: GlobalState, + ctx: NamerContext<'ctx>, +} + +struct NamerContext<'ctx> { + pub program: &'ctx Program, + pub current_package_info: Option, + pub current_module_info: Option, + pub owner_symbols: Vec, + pub value_fully_qualified_name_set: IndexSet, +} + +impl<'ctx> NamerContext<'ctx> { + pub fn get_node_key(&self, id: &AstIndex) -> NodeKey { + NodeKey { + pkgpath: self + .current_package_info + .clone() + .unwrap() + .fully_qualified_name, + id: id.clone(), + } + } +} + +impl<'ctx> Namer<'ctx> { + fn new(program: &'ctx Program, gs: GlobalState) -> Self { + Self { + ctx: NamerContext { + program, + current_package_info: None, + current_module_info: None, + owner_symbols: Vec::default(), + value_fully_qualified_name_set: IndexSet::default(), + }, + gs, + } + } + + // serial namer pass + pub fn find_symbols(program: &'ctx Program, gs: GlobalState) -> GlobalState { + let mut namer = Self::new(program, gs); + namer.ctx.current_package_info = Some(PackageInfo::new( + BUILTIN_SYMBOL_PKG_PATH.to_string(), + "".to_string(), + )); + namer.init_builtin_symbols(); + + for (name, modules) in namer.ctx.program.pkgs.iter() { + { + if modules.is_empty() { + continue; + } + namer.ctx.value_fully_qualified_name_set.clear(); + let mut real_path = Path::new(&program.root) + .join(name.replace('.', &std::path::MAIN_SEPARATOR.to_string())) + .to_str() + .unwrap() + .to_string(); + if name == kclvm_ast::MAIN_PKG { + real_path = program.root.clone() + } + let pkg_pos = Position { + filename: real_path.clone(), + line: 0, + column: None, + }; + + let pkg_symbol = PackageSymbol::new(name.clone(), pkg_pos.clone(), pkg_pos); + let symbol_ref = namer.gs.get_symbols_mut().alloc_package_symbol(pkg_symbol); + namer.ctx.owner_symbols.push(symbol_ref); + + namer.ctx.current_package_info = + Some(PackageInfo::new(name.to_string(), real_path)); + } + + for module in modules.iter() { + namer + .ctx + .current_package_info + .as_mut() + .unwrap() + .kfile_paths + .insert(module.filename.clone()); + namer.ctx.current_module_info = + Some(ModuleInfo::new(module.filename.clone(), name.to_string())); + namer.walk_module(module); + namer + .gs + .get_packages_mut() + .add_module_info(namer.ctx.current_module_info.take().unwrap()); + } + + namer.ctx.owner_symbols.pop(); + namer + .gs + .get_packages_mut() + .add_package(namer.ctx.current_package_info.take().unwrap()) + } + + namer.define_symbols(); + + namer.gs + } + + fn init_builtin_symbols(&mut self) { + //add global built functions + for (name, builtin_func) in BUILTIN_FUNCTIONS.iter() { + let mut value_symbol = ValueSymbol::new( + name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + None, + true, + ); + value_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); + value_symbol.sema_info.doc = builtin_func.ty_doc(); + let symbol_ref = self + .gs + .get_symbols_mut() + .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + self.gs + .get_symbols_mut() + .symbols_info + .global_builtin_symbols + .insert(name.to_string(), symbol_ref); + } + + //add system modules + for system_pkg_name in STANDARD_SYSTEM_MODULES { + let package_symbol_ref = + self.gs + .get_symbols_mut() + .alloc_package_symbol(PackageSymbol::new( + system_pkg_name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + )); + for func_name in get_system_module_members(system_pkg_name) { + let func_ty = get_system_member_function_ty(*system_pkg_name, func_name); + let mut value_symbol = ValueSymbol::new( + func_name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + Some(package_symbol_ref), + false, + ); + value_symbol.sema_info.ty = Some(func_ty.clone()); + value_symbol.sema_info.doc = func_ty.ty_doc(); + let func_symbol_ref = self + .gs + .get_symbols_mut() + .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + self.gs + .get_symbols_mut() + .packages + .get_mut(package_symbol_ref.get_id()) + .unwrap() + .members + .insert(func_name.to_string(), func_symbol_ref); + } + } + + //add string builtin function + let package_symbol_ref = + self.gs + .get_symbols_mut() + .alloc_package_symbol(PackageSymbol::new( + BUILTIN_STR_PACKAGE.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + )); + for (name, builtin_func) in STRING_MEMBER_FUNCTIONS.iter() { + let mut value_symbol = ValueSymbol::new( + name.to_string(), + Position::dummy_pos(), + Position::dummy_pos(), + Some(package_symbol_ref), + true, + ); + value_symbol.sema_info.ty = Some(Arc::new(builtin_func.clone())); + value_symbol.sema_info.doc = builtin_func.ty_doc(); + let symbol_ref = self + .gs + .get_symbols_mut() + .alloc_value_symbol(value_symbol, self.ctx.get_node_key(&AstIndex::default())); + self.gs + .get_symbols_mut() + .packages + .get_mut(package_symbol_ref.get_id()) + .unwrap() + .members + .insert(name.to_string(), symbol_ref); + } + } + + fn define_symbols(&mut self) { + self.gs.get_symbols_mut().build_fully_qualified_name_map(); + } +} + +#[cfg(test)] +mod tests { + use super::Namer; + use crate::core::global_state::GlobalState; + use crate::core::symbol::SymbolKind; + use kclvm_parser::load_program; + use kclvm_parser::ParseSession; + use std::sync::Arc; + + #[test] + fn test_find_symbols() { + let sess = Arc::new(ParseSession::default()); + let program = load_program( + sess.clone(), + &["./src/namer/test_data/schema_symbols.k"], + None, + None, + ) + .unwrap() + .program; + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + + let symbols = gs.get_symbols(); + + let excepts_symbols = vec![ + // package + ("import_test.a", SymbolKind::Package), + ("import_test.b", SymbolKind::Package), + ("import_test.c", SymbolKind::Package), + ("import_test.d", SymbolKind::Package), + ("import_test.e", SymbolKind::Package), + ("import_test.f", SymbolKind::Package), + ("__main__", SymbolKind::Package), + ("pkg", SymbolKind::Package), + // schema + ("import_test.f.UnionType", SymbolKind::Schema), + ("import_test.a.Person", SymbolKind::Schema), + ("import_test.c.TestOfMixin", SymbolKind::Schema), + ("import_test.d.Parent", SymbolKind::Schema), + ("import_test.e.UnionType", SymbolKind::Schema), + ("pkg.Name", SymbolKind::Schema), + ("pkg.Person", SymbolKind::Schema), + ("__main__.Main", SymbolKind::Schema), + // attribute + ("import_test.f.UnionType.b", SymbolKind::Attribute), + ("import_test.a.Person.name", SymbolKind::Attribute), + ("import_test.a.Person.age", SymbolKind::Attribute), + ("pkg.Name.name", SymbolKind::Attribute), + ("pkg.Person.name", SymbolKind::Attribute), + ("import_test.c.TestOfMixin.age", SymbolKind::Attribute), + ("import_test.d.Parent.age1", SymbolKind::Attribute), + ("import_test.e.UnionType.a", SymbolKind::Attribute), + ("__main__.Main.name", SymbolKind::Attribute), + ("__main__.Main.age", SymbolKind::Attribute), + ("__main__.Main.person", SymbolKind::Attribute), + ("__main__.Main.list_union_type", SymbolKind::Attribute), + ("__main__.Main.dict_union_type", SymbolKind::Attribute), + // value + ("__main__.p", SymbolKind::Value), + ("__main__.person", SymbolKind::Value), + ("__main__._c", SymbolKind::Value), + ("import_test.a._a", SymbolKind::Value), + ("import_test.b._b", SymbolKind::Value), + ]; + + for (fqn, kind) in excepts_symbols { + assert!(symbols + .symbols_info + .fully_qualified_name_map + .contains_key(fqn)); + assert_eq!( + symbols + .get_symbol_by_fully_qualified_name(fqn) + .unwrap() + .get_kind(), + kind + ); + } + } +} diff --git a/kclvm/sema/src/namer/node.rs b/kclvm/sema/src/namer/node.rs new file mode 100644 index 000000000..71e0cb1bf --- /dev/null +++ b/kclvm/sema/src/namer/node.rs @@ -0,0 +1,363 @@ +use crate::core::package::ImportInfo; +use crate::core::symbol::{ + AttributeSymbol, RuleSymbol, SchemaSymbol, SymbolKind, SymbolRef, TypeAliasSymbol, ValueSymbol, +}; + +use super::Namer; +use kclvm_ast::ast; +use kclvm_ast::pos::GetPos; +use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_error::diagnostic::Range; + +impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { + type Result = Option>; + fn walk_module(&mut self, module: &'ctx ast::Module) -> Self::Result { + let owner = *self.ctx.owner_symbols.last().unwrap(); + for stmt_node in module.body.iter() { + let symbol_refs = self.walk_stmt(&stmt_node.node); + + if let Some(symbol_refs) = symbol_refs { + for symbol_ref in symbol_refs { + let full_name = self + .gs + .get_symbols() + .get_fully_qualified_name(symbol_ref) + .unwrap(); + let name = full_name.split(".").last().unwrap().to_string(); + + let package_symbol = self + .gs + .get_symbols_mut() + .packages + .get_mut(owner.get_id()) + .unwrap(); + + if !package_symbol.members.contains_key(&name) { + package_symbol.members.insert(name, symbol_ref); + } + } + } + } + + None + } + + fn walk_expr_stmt(&mut self, _expr_stmt: &'ctx ast::ExprStmt) -> Self::Result { + None + } + + fn walk_unification_stmt( + &mut self, + unification_stmt: &'ctx ast::UnificationStmt, + ) -> Self::Result { + let (start_pos, end_pos): Range = unification_stmt.target.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + if unification_stmt.target.node.names.len() == 1 { + let owner_fully_qualified_name = self + .gs + .get_symbols() + .get_fully_qualified_name(owner) + .unwrap(); + let value_name = unification_stmt.target.node.get_name(); + let value_fully_qualified_name = owner_fully_qualified_name + "." + &value_name; + if !self + .ctx + .value_fully_qualified_name_set + .contains(&value_fully_qualified_name) + { + let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(value_name, start_pos, end_pos, Some(owner), true), + self.ctx.get_node_key(&unification_stmt.target.id), + ); + self.ctx + .value_fully_qualified_name_set + .insert(value_fully_qualified_name); + Some(vec![value_ref]) + } else { + None + } + } else { + None + } + } + + fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx ast::TypeAliasStmt) -> Self::Result { + let (start_pos, end_pos): Range = type_alias_stmt.type_name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let type_alias_ref = self.gs.get_symbols_mut().alloc_type_alias_symbol( + TypeAliasSymbol::new( + type_alias_stmt.type_name.node.get_name(), + start_pos, + end_pos, + owner, + ), + self.ctx.get_node_key(&type_alias_stmt.type_name.id), + ); + Some(vec![type_alias_ref]) + } + + fn walk_assign_stmt(&mut self, assign_stmt: &'ctx ast::AssignStmt) -> Self::Result { + let mut value_symbols = vec![]; + for target in assign_stmt.targets.iter() { + let (start_pos, end_pos): Range = target.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + if target.node.names.len() == 1 { + let owner_fully_qualified_name = self + .gs + .get_symbols() + .get_fully_qualified_name(owner) + .unwrap(); + let value_name = target.node.get_name(); + let value_fully_qualified_name = owner_fully_qualified_name + "." + &value_name; + if !self + .ctx + .value_fully_qualified_name_set + .contains(&value_fully_qualified_name) + { + let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(value_name, start_pos, end_pos, Some(owner), true), + self.ctx.get_node_key(&target.id), + ); + self.ctx + .value_fully_qualified_name_set + .insert(value_fully_qualified_name); + value_symbols.push(value_ref) + } + } + } + Some(value_symbols) + } + + fn walk_aug_assign_stmt(&mut self, _aug_assign_stmt: &'ctx ast::AugAssignStmt) -> Self::Result { + None + } + + fn walk_assert_stmt(&mut self, _assert_stmt: &'ctx ast::AssertStmt) -> Self::Result { + None + } + + fn walk_if_stmt(&mut self, if_stmt: &'ctx ast::IfStmt) -> Self::Result { + let mut all_symbols = vec![]; + for stmt in if_stmt.body.iter() { + let mut symbols = self.walk_stmt(&stmt.node); + if let Some(symbols) = &mut symbols { + all_symbols.append(symbols); + } + } + for stmt in if_stmt.orelse.iter() { + let mut symbols = self.walk_stmt(&stmt.node); + if let Some(symbols) = &mut symbols { + all_symbols.append(symbols); + } + } + Some(all_symbols) + } + + fn walk_import_stmt(&mut self, import_stmt: &'ctx ast::ImportStmt) -> Self::Result { + self.ctx + .current_module_info + .as_mut() + .unwrap() + .add_import_info(ImportInfo::new( + import_stmt.name.clone(), + import_stmt.path.node.clone(), + )); + + None + } + + fn walk_schema_stmt(&mut self, schema_stmt: &'ctx ast::SchemaStmt) -> Self::Result { + let (start_pos, end_pos): Range = schema_stmt.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap(); + let shcema_ref = self.gs.get_symbols_mut().alloc_schema_symbol( + SchemaSymbol::new(schema_stmt.name.node.clone(), start_pos, end_pos, *owner), + self.ctx.get_node_key(&schema_stmt.name.id), + ); + self.ctx.owner_symbols.push(shcema_ref); + + for stmt in schema_stmt.body.iter() { + let symbol_refs = self.walk_stmt(&stmt.node); + if let Some(symbol_refs) = symbol_refs { + for symbol_ref in symbol_refs { + if matches!(&symbol_ref.get_kind(), SymbolKind::Attribute) { + let full_attribute_name = self + .gs + .get_symbols() + .get_fully_qualified_name(symbol_ref) + .unwrap(); + self.ctx + .value_fully_qualified_name_set + .insert(full_attribute_name.clone()); + let attribute_name = + full_attribute_name.split(".").last().unwrap().to_string(); + + let schema_symbol = self + .gs + .get_symbols_mut() + .schemas + .get_mut(shcema_ref.get_id()) + .unwrap(); + if !schema_symbol.attributes.contains_key(&attribute_name) { + schema_symbol.attributes.insert(attribute_name, symbol_ref); + } + } + } + } + } + self.ctx.owner_symbols.pop(); + Some(vec![shcema_ref]) + } + + fn walk_rule_stmt(&mut self, rule_stmt: &'ctx ast::RuleStmt) -> Self::Result { + let (start_pos, end_pos): Range = rule_stmt.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let rule_ref = self.gs.get_symbols_mut().alloc_rule_symbol( + RuleSymbol::new(rule_stmt.name.node.clone(), start_pos, end_pos, owner), + self.ctx.get_node_key(&rule_stmt.name.id), + ); + Some(vec![rule_ref]) + } + + fn walk_quant_expr(&mut self, _quant_expr: &'ctx ast::QuantExpr) -> Self::Result { + None + } + + fn walk_schema_attr(&mut self, schema_attr: &'ctx ast::SchemaAttr) -> Self::Result { + let (start_pos, end_pos): Range = schema_attr.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let attribute_ref = self.gs.get_symbols_mut().alloc_attribute_symbol( + AttributeSymbol::new(schema_attr.name.node.clone(), start_pos, end_pos, owner), + self.ctx.get_node_key(&schema_attr.name.id), + ); + Some(vec![attribute_ref]) + } + + /// if else -> sup([body, orelse]) + fn walk_if_expr(&mut self, _if_expr: &'ctx ast::IfExpr) -> Self::Result { + None + } + + fn walk_unary_expr(&mut self, _unary_expr: &'ctx ast::UnaryExpr) -> Self::Result { + None + } + + fn walk_binary_expr(&mut self, _binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { + None + } + + fn walk_selector_expr(&mut self, _selector_expr: &'ctx ast::SelectorExpr) -> Self::Result { + None + } + + fn walk_call_expr(&mut self, _call_expr: &'ctx ast::CallExpr) -> Self::Result { + None + } + + fn walk_subscript(&mut self, _subscript: &'ctx ast::Subscript) -> Self::Result { + None + } + + fn walk_paren_expr(&mut self, _paren_expr: &'ctx ast::ParenExpr) -> Self::Result { + None + } + + fn walk_list_expr(&mut self, _list_expr: &'ctx ast::ListExpr) -> Self::Result { + None + } + + fn walk_list_comp(&mut self, _list_comp: &'ctx ast::ListComp) -> Self::Result { + None + } + + fn walk_dict_comp(&mut self, _dict_comp: &'ctx ast::DictComp) -> Self::Result { + None + } + + fn walk_list_if_item_expr( + &mut self, + _list_if_item_expr: &'ctx ast::ListIfItemExpr, + ) -> Self::Result { + None + } + + fn walk_starred_expr(&mut self, _starred_expr: &'ctx ast::StarredExpr) -> Self::Result { + None + } + + fn walk_config_if_entry_expr( + &mut self, + _config_if_entry_expr: &'ctx ast::ConfigIfEntryExpr, + ) -> Self::Result { + None + } + + fn walk_comp_clause(&mut self, _comp_clause: &'ctx ast::CompClause) -> Self::Result { + None + } + + fn walk_schema_expr(&mut self, _schema_expr: &'ctx ast::SchemaExpr) -> Self::Result { + None + } + + fn walk_config_expr(&mut self, _config_expr: &'ctx ast::ConfigExpr) -> Self::Result { + None + } + + fn walk_check_expr(&mut self, _check_expr: &'ctx ast::CheckExpr) -> Self::Result { + None + } + + fn walk_lambda_expr(&mut self, _lambda_expr: &'ctx ast::LambdaExpr) -> Self::Result { + None + } + + fn walk_keyword(&mut self, _keyword: &'ctx ast::Keyword) -> Self::Result { + None + } + + fn walk_arguments(&mut self, _arguments: &'ctx ast::Arguments) -> Self::Result { + None + } + + fn walk_compare(&mut self, _compare: &'ctx ast::Compare) -> Self::Result { + None + } + + fn walk_identifier(&mut self, _identifier: &'ctx ast::Identifier) -> Self::Result { + None + } + + fn walk_number_lit(&mut self, _number_lit: &'ctx ast::NumberLit) -> Self::Result { + None + } + + fn walk_string_lit(&mut self, _string_lit: &'ctx ast::StringLit) -> Self::Result { + None + } + + fn walk_name_constant_lit( + &mut self, + _name_constant_lit: &'ctx ast::NameConstantLit, + ) -> Self::Result { + None + } + + fn walk_joined_string(&mut self, _joined_string: &'ctx ast::JoinedString) -> Self::Result { + None + } + + fn walk_formatted_value( + &mut self, + _formatted_value: &'ctx ast::FormattedValue, + ) -> Self::Result { + None + } + + fn walk_comment(&mut self, _comment: &'ctx ast::Comment) -> Self::Result { + None + } + + fn walk_missing_expr(&mut self, _missing_expr: &'ctx ast::MissingExpr) -> Self::Result { + None + } +} diff --git a/kclvm/sema/src/namer/test_data/import_test/a.k b/kclvm/sema/src/namer/test_data/import_test/a.k new file mode 100644 index 000000000..8b6a81409 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/a.k @@ -0,0 +1,4 @@ +_a = 1 +schema Person: + name: str + age: int diff --git a/kclvm/sema/src/namer/test_data/import_test/b.k b/kclvm/sema/src/namer/test_data/import_test/b.k new file mode 100644 index 000000000..79fa8ccc7 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/b.k @@ -0,0 +1 @@ +_b = 1 diff --git a/kclvm/sema/src/namer/test_data/import_test/c.k b/kclvm/sema/src/namer/test_data/import_test/c.k new file mode 100644 index 000000000..f4832d10f --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/c.k @@ -0,0 +1,2 @@ +schema TestOfMixin: + age?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/d.k b/kclvm/sema/src/namer/test_data/import_test/d.k new file mode 100644 index 000000000..78dcd8b21 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/d.k @@ -0,0 +1,2 @@ +schema Parent: + age1?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/e.k b/kclvm/sema/src/namer/test_data/import_test/e.k new file mode 100644 index 000000000..98fabf8f4 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/e.k @@ -0,0 +1,2 @@ +schema UnionType: + a?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/f.k b/kclvm/sema/src/namer/test_data/import_test/f.k new file mode 100644 index 000000000..65a0fa043 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/f.k @@ -0,0 +1,2 @@ +schema UnionType: + b?: int diff --git a/kclvm/sema/src/namer/test_data/kcl.mod b/kclvm/sema/src/namer/test_data/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/sema/src/namer/test_data/pkg/pkg.k b/kclvm/sema/src/namer/test_data/pkg/pkg.k new file mode 100644 index 000000000..f8c946eff --- /dev/null +++ b/kclvm/sema/src/namer/test_data/pkg/pkg.k @@ -0,0 +1,5 @@ +schema Name: + name?: str + +schema Person: + name: Name = Name {name = "Alice"} diff --git a/kclvm/sema/src/namer/test_data/schema_symbols.k b/kclvm/sema/src/namer/test_data/schema_symbols.k new file mode 100644 index 000000000..5452a4a94 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/schema_symbols.k @@ -0,0 +1,32 @@ +import import_test.a +import import_test.b +import import_test.c +import import_test.d +import import_test.e +import import_test.f as g +import pkg +import regex + +schema Main(d.Parent): + mixin [c.TestOfMixin] + name?: str + age?: int = 18 + person?: a.Person + list_union_type: [e.UnionType|int] + dict_union_type: {g.UnionType|int:float} + + check: + regex.match(name, r"[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*") if name + +if a._a > 1: + _c = 1 +elif a._a == 1: + _c = 2 +else: + _c = 3 + +p = Main{ + age = b._b +} + +person = pkg.Person {} diff --git a/kclvm/sema/src/pre_process/config.rs b/kclvm/sema/src/pre_process/config.rs index 9f8f9ea95..d5668fd7d 100644 --- a/kclvm/sema/src/pre_process/config.rs +++ b/kclvm/sema/src/pre_process/config.rs @@ -12,11 +12,30 @@ impl ConfigNestAttrTransformer { pub fn walk_config_entry(&mut self, config_entry: &mut Box>) { if let Some(key) = config_entry.node.key.as_mut() { if let ast::Expr::Identifier(identifier) = &mut key.node { + // desuger config expr, e.g., desuger + // ``` + // foo = Foo { + // bar.baz : xxx + // } + // ``` + // to: + // ``` + // foo = Foo { + // bar : Bar { + // baz : xxx + // } + // } + // ``` if identifier.names.len() > 1 { let mut names = identifier.names.clone(); let names = &mut names[1..]; names.reverse(); identifier.names = vec![identifier.names[0].clone()]; + key.filename = identifier.names[0].filename.clone(); + key.line = identifier.names[0].line; + key.column = identifier.names[0].column; + key.end_line = identifier.names[0].end_line; + key.end_column = identifier.names[0].end_column; let mut value = config_entry.node.value.clone(); for (i, name) in names.iter().enumerate() { @@ -29,11 +48,11 @@ impl ConfigNestAttrTransformer { let entry_value = ast::ConfigEntry { key: Some(Box::new(ast::Node::new( ast::Expr::Identifier(name_node), - key.filename.clone(), - key.line, - key.column, - key.end_line, - key.end_column, + name.filename.clone(), + name.line, + name.column, + name.end_line, + name.end_column, ))), value: value.clone(), operation: if is_last_item { @@ -46,18 +65,18 @@ impl ConfigNestAttrTransformer { let config_expr = ast::ConfigExpr { items: vec![Box::new(ast::Node::new( entry_value, - key.filename.clone(), - key.line, - key.column, - key.end_line, - key.end_column, + config_entry.filename.clone(), + name.line, + name.column, + config_entry.end_line, + config_entry.end_column, ))], }; value = Box::new(ast::Node::new( ast::Expr::Config(config_expr), value.filename.clone(), - value.line, - value.column, + name.line, + name.column, value.end_line, value.end_column, )) @@ -114,7 +133,7 @@ impl ConfigMergeTransformer { ast::Stmt::Unification(unification_stmt) if !unification_stmt.target.node.names.is_empty() => { - let name = &unification_stmt.target.node.names[0]; + let name = &unification_stmt.target.node.names[0].node; match name_declaration_mapping.get_mut(name) { Some(declarations) => declarations.push(( module.filename.to_string(), @@ -139,7 +158,7 @@ impl ConfigMergeTransformer { if let ast::Expr::Schema(_) = assign_stmt.value.node { for target in &assign_stmt.targets { if target.node.names.len() == 1 { - let name = &target.node.names[0]; + let name = &target.node.names[0].node; match name_declaration_mapping.get_mut(name) { Some(declarations) => { // A hidden var is mutable. diff --git a/kclvm/sema/src/pre_process/identifier.rs b/kclvm/sema/src/pre_process/identifier.rs index 180627b31..df017fc40 100644 --- a/kclvm/sema/src/pre_process/identifier.rs +++ b/kclvm/sema/src/pre_process/identifier.rs @@ -1,5 +1,6 @@ use crate::info::is_private_field; use indexmap::{IndexMap, IndexSet}; +use kclvm_ast::ast::Node; use kclvm_ast::pos::GetPos; use kclvm_ast::walker::MutSelfMutWalker; use kclvm_ast::{ast, walk_if_mut, walk_list_mut}; @@ -55,7 +56,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { let is_config = matches!(assign_stmt.value.node, ast::Expr::Schema(_)); for target in &assign_stmt.targets { if !target.node.names.is_empty() { - let name = &target.node.names[0]; + let name = &target.node.names[0].node; if (is_private_field(name) || !self.global_names.contains_key(name) || is_config) && self.scope_level == 0 { @@ -70,7 +71,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { if aug_assign_stmt.target.node.names.is_empty() { return; } - let name = &aug_assign_stmt.target.node.names[0]; + let name = &aug_assign_stmt.target.node.names[0].node; if is_private_field(name) || !self.global_names.contains_key(name) || is_config { if self.scope_level == 0 { self.global_names @@ -96,7 +97,8 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { for gen in &mut list_comp.generators { for target in &gen.node.targets { if !target.node.names.is_empty() { - self.local_vars.insert(target.node.names[0].to_string()); + self.local_vars + .insert(target.node.names[0].node.to_string()); } } } @@ -108,7 +110,8 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { for gen in &dict_comp.generators { for target in &gen.node.targets { if !target.node.names.is_empty() { - self.local_vars.insert(target.node.names[0].to_string()); + self.local_vars + .insert(target.node.names[0].node.to_string()); } } } @@ -122,7 +125,8 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { fn walk_quant_expr(&mut self, quant_expr: &'ctx mut ast::QuantExpr) { for target in &quant_expr.variables { if !target.node.names.is_empty() { - self.local_vars.insert(target.node.names[0].to_string()); + self.local_vars + .insert(target.node.names[0].node.to_string()); } } self.walk_expr(&mut quant_expr.target.node); @@ -133,7 +137,7 @@ impl<'ctx> MutSelfMutWalker<'ctx> for QualifiedIdentifierTransformer { fn walk_identifier(&mut self, identifier: &'ctx mut ast::Identifier) { if identifier.names.len() >= 2 { // skip global name and generator local variables in list/dict comp and quant expression - let name = &identifier.names[0]; + let name = &identifier.names[0].node; if !self.global_names.contains_key(name) && !self.local_vars.contains(name) { if let Some(pkgpath) = self.import_names.get(name) { identifier.pkgpath = pkgpath.clone() @@ -159,11 +163,23 @@ impl<'ctx> MutSelfMutWalker<'ctx> for RawIdentifierTransformer { identifier.names = identifier .names .iter() - .map(|n| remove_raw_ident_prefix(n)) - .collect::>(); + .map(|name| { + Node::node_with_pos_and_id( + remove_raw_ident_prefix(&name.node), + name.pos(), + name.id.clone(), + ) + }) + .collect::>>(); } fn walk_schema_attr(&mut self, schema_attr: &'ctx mut ast::SchemaAttr) { - schema_attr.name.node = remove_raw_ident_prefix(&schema_attr.name.node); + // If the attribute is an identifier and then fix it. + // Note that we do not fix a string-like attribute e.g., `"$name"` + if schema_attr.name.end_column - schema_attr.name.column + <= schema_attr.name.node.chars().count() as u64 + { + schema_attr.name.node = remove_raw_ident_prefix(&schema_attr.name.node); + } walk_list_mut!(self, walk_call_expr, schema_attr.decorators); walk_if_mut!(self, walk_expr, schema_attr.value); } @@ -190,11 +206,11 @@ impl<'ctx> MutSelfMutWalker<'ctx> for RawIdentifierTransformer { walk_if_mut!(self, walk_identifier, rule_stmt.for_host_name); } fn walk_import_stmt(&mut self, import_stmt: &'ctx mut ast::ImportStmt) { - if let Some(name) = import_stmt.asname.as_mut() { - *name = remove_raw_ident_prefix(name); + if let Some(name) = &mut import_stmt.asname { + name.node = remove_raw_ident_prefix(&name.node); } import_stmt.name = remove_raw_ident_prefix(&import_stmt.name); - import_stmt.path = remove_raw_ident_prefix(&import_stmt.path); + import_stmt.path.node = remove_raw_ident_prefix(&import_stmt.path.node); } } @@ -208,7 +224,7 @@ pub fn fix_qualified_identifier<'ctx>( // 0. init import names. for stmt in &module.body { if let ast::Stmt::Import(import_stmt) = &stmt.node { - import_names.insert(import_stmt.name.clone(), import_stmt.path.clone()); + import_names.insert(import_stmt.name.clone(), import_stmt.path.node.clone()); } } // 1. fix_global_ident diff --git a/kclvm/sema/src/pre_process/mod.rs b/kclvm/sema/src/pre_process/mod.rs index f775b7bd4..49d6ac928 100644 --- a/kclvm/sema/src/pre_process/mod.rs +++ b/kclvm/sema/src/pre_process/mod.rs @@ -12,15 +12,18 @@ pub use config::{fix_config_expr_nest_attr, merge_program}; pub use identifier::{fix_qualified_identifier, fix_raw_identifier_prefix}; pub use multi_assign::transform_multi_assign; +use crate::resolver::Options; + /// Pre-process AST program. -pub fn pre_process_program(program: &mut ast::Program) { +pub fn pre_process_program(program: &mut ast::Program, opts: &Options) { for (pkgpath, modules) in program.pkgs.iter_mut() { let mut import_names = IndexMap::default(); if pkgpath == kclvm_ast::MAIN_PKG { for module in modules.iter_mut() { for stmt in &module.body { if let ast::Stmt::Import(import_stmt) = &stmt.node { - import_names.insert(import_stmt.name.clone(), import_stmt.path.clone()); + import_names + .insert(import_stmt.name.clone(), import_stmt.path.node.clone()); } } } @@ -35,5 +38,7 @@ pub fn pre_process_program(program: &mut ast::Program) { fix_config_expr_nest_attr(module); } } - merge_program(program); + if opts.merge_program { + merge_program(program); + } } diff --git a/kclvm/sema/src/pre_process/multi_assign.rs b/kclvm/sema/src/pre_process/multi_assign.rs index 9b3e6faef..5425fa8ca 100644 --- a/kclvm/sema/src/pre_process/multi_assign.rs +++ b/kclvm/sema/src/pre_process/multi_assign.rs @@ -7,10 +7,10 @@ use kclvm_ast::{ast, walker::MutSelfMutWalker}; /// # Examples /// /// ``` -/// use kclvm_parser::parse_file; +/// use kclvm_parser::parse_file_force_errors; /// use kclvm_sema::pre_process::transform_multi_assign; /// -/// let mut module = parse_file("", Some("a = b = Config {}".to_string())).unwrap(); +/// let mut module = parse_file_force_errors("", Some("a = b = Config {}".to_string())).unwrap(); /// assert_eq!(module.body.len(), 1); /// transform_multi_assign(&mut module); /// assert_eq!(module.body.len(), 2); diff --git a/kclvm/sema/src/pre_process/test_data/raw_identifier.k b/kclvm/sema/src/pre_process/test_data/raw_identifier.k index d86374741..33298a1bc 100644 --- a/kclvm/sema/src/pre_process/test_data/raw_identifier.k +++ b/kclvm/sema/src/pre_process/test_data/raw_identifier.k @@ -1 +1,9 @@ $schema = 1 + +schema Name: + $name?: str + "$name"?: str + +n = Name { + "$name": "1" +} diff --git a/kclvm/sema/src/pre_process/test_data/skip_merge/config1.k b/kclvm/sema/src/pre_process/test_data/skip_merge/config1.k new file mode 100644 index 000000000..d370b4523 --- /dev/null +++ b/kclvm/sema/src/pre_process/test_data/skip_merge/config1.k @@ -0,0 +1,3 @@ +person: Person { + name = "Alice" +} diff --git a/kclvm/sema/src/pre_process/test_data/skip_merge/config2.k b/kclvm/sema/src/pre_process/test_data/skip_merge/config2.k new file mode 100644 index 000000000..48b33fd71 --- /dev/null +++ b/kclvm/sema/src/pre_process/test_data/skip_merge/config2.k @@ -0,0 +1,3 @@ +person: Person { + name = "bob" +} diff --git a/kclvm/sema/src/pre_process/test_data/skip_merge/def.k b/kclvm/sema/src/pre_process/test_data/skip_merge/def.k new file mode 100644 index 000000000..bb8a82ad6 --- /dev/null +++ b/kclvm/sema/src/pre_process/test_data/skip_merge/def.k @@ -0,0 +1,2 @@ +schema Person: + name: str diff --git a/kclvm/sema/src/pre_process/tests.rs b/kclvm/sema/src/pre_process/tests.rs index b03cfc11f..f3f41d31c 100644 --- a/kclvm/sema/src/pre_process/tests.rs +++ b/kclvm/sema/src/pre_process/tests.rs @@ -3,12 +3,13 @@ use std::sync::Arc; use super::*; use indexmap::IndexMap; use kclvm_ast::path::get_attr_paths_from_config_expr; -use kclvm_parser::{load_program, parse_file, ParseSession}; +use kclvm_parser::{load_program, parse_file_force_errors, ParseSession}; #[test] fn test_fix_qualified_identifier() { let mut module = - parse_file("./src/pre_process/test_data/qualified_identifier.k", None).unwrap(); + parse_file_force_errors("./src/pre_process/test_data/qualified_identifier.k", None) + .unwrap(); fix_qualified_identifier(&mut module, &mut IndexMap::default()); if let ast::Stmt::Assign(assign_stmt) = &module.body[1].node { if let ast::Expr::Identifier(identifier) = &assign_stmt.value.node { @@ -23,24 +24,40 @@ fn test_fix_qualified_identifier() { #[test] fn test_fix_raw_identifier_prefix() { - let mut module = parse_file("./src/pre_process/test_data/raw_identifier.k", None).unwrap(); + let mut module = + parse_file_force_errors("./src/pre_process/test_data/raw_identifier.k", None).unwrap(); if let ast::Stmt::Assign(assign_stmt) = &module.body[0].node { - assert_eq!(assign_stmt.targets[0].node.names[0], "$schema") + assert_eq!(assign_stmt.targets[0].node.names[0].node, "$schema") } else { panic!("invalid assign statement") } fix_raw_identifier_prefix(&mut module); if let ast::Stmt::Assign(assign_stmt) = &module.body[0].node { - assert_eq!(assign_stmt.targets[0].node.names[0], "schema") + assert_eq!(assign_stmt.targets[0].node.names[0].node, "schema") } else { panic!("invalid assign statement") } + if let ast::Stmt::Schema(schema_stmt) = &module.body[1].node { + if let ast::Stmt::SchemaAttr(attr) = &schema_stmt.body[0].node { + assert_eq!(attr.name.node, "name"); + } else { + panic!("invalid schema attr") + } + if let ast::Stmt::SchemaAttr(attr) = &schema_stmt.body[1].node { + assert_eq!(attr.name.node, "$name"); + } else { + panic!("invalid schema attr") + } + } else { + panic!("invalid schema statement") + } } #[test] fn test_transform_multi_assign() { let targets = ["a", "b", "c", "d"]; - let mut module = parse_file("./src/pre_process/test_data/multi_assign.k", None).unwrap(); + let mut module = + parse_file_force_errors("./src/pre_process/test_data/multi_assign.k", None).unwrap(); if let ast::Stmt::Assign(assign_stmt) = &module.body[1].node { assert_eq!(assign_stmt.targets.len(), targets.len()); for (i, target) in targets.iter().enumerate() { @@ -72,8 +89,10 @@ fn test_config_merge() { "./src/pre_process/test_data/config_merge/config2.k", ], None, + None, ) - .unwrap(); + .unwrap() + .program; merge_program(&mut program); let modules = program.pkgs.get_mut(kclvm_ast::MAIN_PKG).unwrap(); assert_eq!(modules.len(), 4); @@ -113,8 +132,10 @@ fn test_config_override() { sess, &["./src/pre_process/test_data/config_override.k"], None, + None, ) - .unwrap(); + .unwrap() + .program; merge_program(&mut program); let modules = program.pkgs.get_mut(kclvm_ast::MAIN_PKG).unwrap(); assert_eq!(modules.len(), 1); @@ -144,3 +165,59 @@ fn test_config_override() { ) } } + +#[test] +fn test_skip_merge_program() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess, + &[ + "./src/pre_process/test_data/config_merge/def.k", + "./src/pre_process/test_data/config_merge/config1.k", + "./src/pre_process/test_data/config_merge/config2.k", + ], + None, + None, + ) + .unwrap() + .program; + // skip merge program and save raw config ast node + // merge_program(&mut program); + let modules = program.pkgs.get_mut(kclvm_ast::MAIN_PKG).unwrap(); + assert_eq!(modules.len(), 3); + let config1 = &modules[1]; + let config2 = &modules[1]; + if let ast::Stmt::Unification(unification) = &config1.body[0].node { + let schema = &unification.value.node; + if let ast::Expr::Config(config) = &schema.config.node { + assert_eq!(config.items.len(), 1); + } else { + panic!( + "test failed, expect config expression, got {:?}", + schema.config + ) + } + } else { + panic!( + "test failed, expect unification statement, got {:?}", + config1.body[0] + ) + } + + if let ast::Stmt::Unification(unification) = &config2.body[0].node { + let schema = &unification.value.node; + if let ast::Expr::Config(config) = &schema.config.node { + assert_eq!(config.items.len(), 1); + } else { + panic!( + "test failed, expect config expression, got {:?}", + schema.config + ) + } + } else { + panic!( + "test failed, expect unification statement, got {:?}", + config2.body[0] + ) + } +} diff --git a/kclvm/sema/src/resolver/arg.rs b/kclvm/sema/src/resolver/arg.rs index 862807a7a..9570a32db 100644 --- a/kclvm/sema/src/resolver/arg.rs +++ b/kclvm/sema/src/resolver/arg.rs @@ -1,11 +1,13 @@ use crate::resolver::Resolver; -use crate::ty::{Parameter, Type}; +use crate::ty::FunctionType; +use compiler_base_error::unit_type::{TypeWithUnit, UnitUsize}; use indexmap::IndexSet; use kclvm_ast::ast; -use std::rc::Rc; use kclvm_ast::pos::GetPos; +use crate::ty::TypeRef; + impl<'ctx> Resolver<'ctx> { fn get_func_name(&mut self, func: &ast::Expr) -> String { let mut callee = func; @@ -26,79 +28,112 @@ impl<'ctx> Resolver<'ctx> { /// Do schema/function/decorator argument type check. pub fn do_arguments_type_check( &mut self, - func: &ast::Expr, + func: &ast::NodeRef, args: &'ctx [ast::NodeRef], kwargs: &'ctx [ast::NodeRef], - params: &[Parameter], + func_ty: &FunctionType, ) { - let func_name = self.get_func_name(func); + let func_name = self.get_func_name(&func.node); let arg_types = self.exprs(args); - let mut kwarg_types: Vec<(String, Rc)> = vec![]; + let mut kwarg_types: Vec<(String, TypeRef)> = vec![]; let mut check_table: IndexSet = IndexSet::default(); for kw in kwargs { if !kw.node.arg.node.names.is_empty() { - let arg_name = &kw.node.arg.node.names[0]; + let arg_name = &kw.node.arg.node.names[0].node; if check_table.contains(arg_name) { self.handler.add_compile_error( &format!("{} has duplicated keyword argument {}", func_name, arg_name), - kw.get_pos(), + kw.get_span_pos(), ); } check_table.insert(arg_name.to_string()); let arg_value_type = self.expr_or_any_type(&kw.node.value); + self.node_ty_map + .insert(self.get_node_key(kw.id.clone()), arg_value_type.clone()); kwarg_types.push((arg_name.to_string(), arg_value_type.clone())); } else { self.handler - .add_compile_error("missing argument", kw.get_pos()); + .add_compile_error("missing argument", kw.get_span_pos()); + } + } + // Do few argument count check + if !func_ty.is_variadic { + let mut got_count = 0; + let mut expect_count = 0; + for param in &func_ty.params { + if !param.has_default { + expect_count += 1; + if check_table.contains(¶m.name) { + got_count += 1 + } + } + } + got_count += args.len(); + if got_count < expect_count { + self.handler.add_compile_error( + &format!( + "expected {}, found {}", + UnitUsize(expect_count, "positional argument".to_string()) + .into_string_with_unit(), + got_count + ), + func.get_span_pos(), + ); } } - if !params.is_empty() { - for (i, ty) in arg_types.iter().enumerate() { - let expected_ty = match params.get(i) { - Some(param) => param.ty.clone(), - None => { + // Do normal argument type check + for (i, ty) in arg_types.iter().enumerate() { + let expected_ty = match func_ty.params.get(i) { + Some(param) => param.ty.clone(), + None => { + if !func_ty.is_variadic { self.handler.add_compile_error( &format!( - "{} takes {} positional argument but {} were given", + "{} takes {} but {} were given", func_name, - params.len(), + UnitUsize(func_ty.params.len(), "positional argument".to_string()) + .into_string_with_unit(), args.len(), ), - args[i].get_pos(), + args[i].get_span_pos(), ); - return; } - }; - self.must_assignable_to(ty.clone(), expected_ty, args[i].get_pos(), None) - } - for (i, (arg_name, kwarg_ty)) in kwarg_types.iter().enumerate() { - if !params - .iter() - .map(|p| p.name.clone()) - .any(|x| x == *arg_name) - { - self.handler.add_compile_error( - &format!( - "{} got an unexpected keyword argument '{}'", - func_name, arg_name - ), - kwargs[i].get_pos(), - ); + return; } - let expected_types: Vec> = params - .iter() - .filter(|p| p.name == *arg_name) - .map(|p| p.ty.clone()) - .collect(); - if !expected_types.is_empty() { - self.must_assignable_to( - kwarg_ty.clone(), - expected_types[0].clone(), - kwargs[i].get_pos(), - None, - ); - }; + }; + self.must_assignable_to(ty.clone(), expected_ty, args[i].get_span_pos(), None) + } + // Do keyword argument type check + for (i, (arg_name, kwarg_ty)) in kwarg_types.iter().enumerate() { + if !func_ty + .params + .iter() + .map(|p| p.name.clone()) + .any(|x| x == *arg_name) + && !func_ty.is_variadic + { + self.handler.add_compile_error( + &format!( + "{} got an unexpected keyword argument '{}'", + func_name, arg_name + ), + kwargs[i].get_span_pos(), + ); } + let expected_types: Vec = func_ty + .params + .iter() + .filter(|p| p.name == *arg_name) + .map(|p| p.ty.clone()) + .collect(); + if !expected_types.is_empty() { + self.must_assignable_to( + kwarg_ty.clone(), + expected_types[0].clone(), + kwargs[i].get_span_pos(), + None, + ); + }; } } } diff --git a/kclvm/sema/src/resolver/attr.rs b/kclvm/sema/src/resolver/attr.rs index 68ca18dfd..25d2dff38 100644 --- a/kclvm/sema/src/resolver/attr.rs +++ b/kclvm/sema/src/resolver/attr.rs @@ -1,32 +1,35 @@ -use std::rc::Rc; +use std::sync::Arc; use crate::builtin::system_module::{get_system_module_members, UNITS, UNITS_NUMBER_MULTIPLIER}; -use crate::builtin::STRING_MEMBER_FUNCTIONS; +use crate::builtin::{get_system_member_function_ty, STRING_MEMBER_FUNCTIONS}; use crate::resolver::Resolver; -use crate::ty::{ModuleKind, Type, TypeKind}; +use crate::ty::TypeKind::Schema; +use crate::ty::{DictType, ModuleKind, Type, TypeKind, TypeRef, SCHEMA_MEMBER_FUNCTIONS}; +use kclvm_error::diagnostic::Range; use kclvm_error::*; use super::node::ResolvedResult; impl<'ctx> Resolver<'ctx> { - pub fn check_attr_ty(&mut self, attr_ty: &Type, pos: Position) { + pub fn check_attr_ty(&mut self, attr_ty: &Type, range: Range) { if !attr_ty.is_any() && !attr_ty.is_key() { self.handler.add_error( ErrorKind::IllegalAttributeError, &[Message { - pos, + range, style: Style::LineAndColumn, message: format!( "A attribute must be string type, got '{}'", attr_ty.ty_str() ), note: None, + suggested_replacement: None, }], ); } } - pub fn load_attr(&mut self, obj: Rc, attr: &str, pos: Position) -> ResolvedResult { + pub fn load_attr(&mut self, obj: TypeRef, attr: &str, range: Range) -> ResolvedResult { let (result, return_ty) = match &obj.kind { TypeKind::Any => (true, self.any_ty()), TypeKind::None @@ -42,10 +45,20 @@ impl<'ctx> Resolver<'ctx> { | TypeKind::Named(_) | TypeKind::Void => (false, self.any_ty()), TypeKind::Str | TypeKind::StrLit(_) => match STRING_MEMBER_FUNCTIONS.get(attr) { - Some(ty) => (true, Rc::new(ty.clone())), + Some(ty) => (true, Arc::new(ty.clone())), None => (false, self.any_ty()), }, - TypeKind::Dict(_, val_ty) => (true, Rc::new(val_ty.as_ref().clone())), + TypeKind::Dict(DictType { + key_ty: _, + val_ty, + attrs, + }) => ( + true, + attrs + .get(attr) + .map(|attr| attr.ty.clone()) + .unwrap_or(Arc::new(val_ty.as_ref().clone())), + ), // union type load attr based the type guard. e.g, a: str|int; if a is str: xxx; if a is int: xxx; // return sup([self.load_attr_type(t, attr, filename, line, column) for t in obj.types]) TypeKind::Union(_) => (true, self.any_ty()), @@ -56,7 +69,7 @@ impl<'ctx> Resolver<'ctx> { } else if schema_ty.is_member_functions(attr) { ( true, - Rc::new(Type::function( + Arc::new(Type::function( Some(obj.clone()), Type::list_ref(self.any_ty()), &[], @@ -76,7 +89,7 @@ impl<'ctx> Resolver<'ctx> { Some(v) => { if v.borrow().ty.is_module() { self.handler - .add_compile_error(&format!("can not import the attribute '{}' from the module '{}'", attr, module_ty.pkgpath), pos.clone()); + .add_compile_error(&format!("can not import the attribute '{}' from the module '{}'", attr, module_ty.pkgpath), range.clone()); } (true, v.borrow().ty.clone()) } @@ -86,28 +99,53 @@ impl<'ctx> Resolver<'ctx> { }, ModuleKind::System => { if module_ty.pkgpath == UNITS && attr == UNITS_NUMBER_MULTIPLIER { - (true, Rc::new(Type::number_multiplier_non_lit_ty())) + (true, Arc::new(Type::number_multiplier_non_lit_ty())) } else { let members = get_system_module_members(&module_ty.pkgpath); - (members.contains(&attr), self.any_ty()) + ( + members.contains(&attr), + get_system_member_function_ty(&module_ty.pkgpath, attr), + ) } } ModuleKind::Plugin => (true, self.any_ty()), } } }; + if !result { + // The attr user input. + let (attr, suggestion) = if attr.is_empty() { + ("[missing name]", "".to_string()) + } else { + let mut suggestion = String::new(); + // Calculate the closest miss attributes. + if let Schema(schema_ty) = &obj.kind { + // Get all the attributes of the schema. + let attrs = if schema_ty.is_instance { + schema_ty.attrs.keys().cloned().collect::>() + } else { + SCHEMA_MEMBER_FUNCTIONS + .iter() + .map(|s| s.to_string()) + .collect::>() + }; + let suggs = suggestions::provide_suggestions(attr, &attrs); + if suggs.len() > 0 { + suggestion = format!(", did you mean '{:?}'?", suggs); + } + } + (attr, suggestion) + }; + self.handler.add_type_error( &format!( - "{} has no attribute {}", + "attribute '{}' not found in '{}'{}", + attr, obj.ty_str(), - if attr.is_empty() { - "[missing name]" - } else { - attr - } + suggestion ), - pos, + range, ); } return_ty diff --git a/kclvm/sema/src/resolver/calculation.rs b/kclvm/sema/src/resolver/calculation.rs index bbe2e1644..98e7c59a4 100644 --- a/kclvm/sema/src/resolver/calculation.rs +++ b/kclvm/sema/src/resolver/calculation.rs @@ -1,9 +1,11 @@ -use std::rc::Rc; +use std::sync::Arc; use crate::resolver::Resolver; -use crate::ty::{has_any_type, is_upper_bound, sup, Type, TypeInferMethods, ZERO_LIT_TYPES}; +use crate::ty::{ + has_any_type, is_upper_bound, sup, Type, TypeInferMethods, TypeRef, ZERO_LIT_TYPES, +}; use kclvm_ast::ast; -use kclvm_error::Position; +use kclvm_error::diagnostic::Range; const DIV_OR_MOD_ZERO_MSG: &str = "integer division or modulo by zero"; @@ -53,11 +55,11 @@ impl<'ctx> Resolver<'ctx> { /// Or: any_type1 or any_type1 -> sup([any_type1, any_type2]) pub fn binary( &mut self, - left: Rc, - right: Rc, + left: TypeRef, + right: TypeRef, op: &ast::BinOp, - pos: Position, - ) -> Rc { + range: Range, + ) -> TypeRef { let t1 = self .ctx .ty_ctx @@ -69,11 +71,11 @@ impl<'ctx> Resolver<'ctx> { if has_any_type(&[t1.clone(), t2.clone()]) { return self.any_ty(); } - let number_binary = |left: &Rc, right: &Rc| { + let number_binary = |left: &TypeRef, right: &TypeRef| { if left.is_float() || right.is_float() { - Rc::new(Type::FLOAT) + Arc::new(Type::FLOAT) } else { - Rc::new(Type::INT) + Arc::new(Type::INT) } }; let (result, return_ty) = match op { @@ -123,7 +125,7 @@ impl<'ctx> Resolver<'ctx> { if t1.is_number() && t2.is_number() { if ZERO_LIT_TYPES.contains(&t2) { self.handler - .add_type_error(DIV_OR_MOD_ZERO_MSG, pos.clone()); + .add_type_error(DIV_OR_MOD_ZERO_MSG, range.clone()); } (true, number_binary(&t1, &t2)) } else { @@ -134,7 +136,7 @@ impl<'ctx> Resolver<'ctx> { if t1.is_number() && t2.is_number() { if ZERO_LIT_TYPES.contains(&t2) { self.handler - .add_type_error(DIV_OR_MOD_ZERO_MSG, pos.clone()); + .add_type_error(DIV_OR_MOD_ZERO_MSG, range.clone()); } (true, self.int_ty()) } else { @@ -186,7 +188,7 @@ impl<'ctx> Resolver<'ctx> { t1.ty_str(), t2.ty_str() ), - pos.clone(), + range.clone(), ); } (true, t2) @@ -201,7 +203,7 @@ impl<'ctx> Resolver<'ctx> { left.ty_str(), right.ty_str() ), - pos, + range, ); } return_ty @@ -213,7 +215,7 @@ impl<'ctx> Resolver<'ctx> { /// - number unary negation (int, float) /// ~ number unary bitwise inversion (int) /// not x logical negation (any type) - pub fn unary(&mut self, ty: Rc, op: &ast::UnaryOp, pos: Position) -> Rc { + pub fn unary(&mut self, ty: TypeRef, op: &ast::UnaryOp, range: Range) -> TypeRef { if has_any_type(&[ty.clone()]) { return self.any_ty(); } @@ -235,7 +237,7 @@ impl<'ctx> Resolver<'ctx> { op.symbol(), ty.ty_str(), ), - pos, + range, ); self.any_ty() } @@ -251,11 +253,11 @@ impl<'ctx> Resolver<'ctx> { /// iterable # 1 in [1, 2, 3], "s" in "ss", "key" in Schema pub fn compare( &mut self, - left: Rc, - right: Rc, + left: TypeRef, + right: TypeRef, op: &ast::CmpOp, - pos: Position, - ) -> Rc { + range: Range, + ) -> TypeRef { let t1 = self.ctx.ty_ctx.literal_union_type_to_variable_type(left); let t2 = self.ctx.ty_ctx.literal_union_type_to_variable_type(right); if has_any_type(&[t1.clone(), t2.clone()]) { @@ -313,7 +315,7 @@ impl<'ctx> Resolver<'ctx> { t1.ty_str(), t2.ty_str(), ), - pos, + range, ); self.any_ty() } diff --git a/kclvm/sema/src/resolver/config.rs b/kclvm/sema/src/resolver/config.rs index c1f900325..9a2407d09 100644 --- a/kclvm/sema/src/resolver/config.rs +++ b/kclvm/sema/src/resolver/config.rs @@ -1,16 +1,16 @@ -use std::rc::Rc; +use std::sync::Arc; use super::{ - node::TypeRef, scope::{ScopeKind, ScopeObject, ScopeObjectKind}, Resolver, }; -use crate::ty::sup; -use crate::ty::SchemaType; +use crate::ty::{sup, DictType, TypeInferMethods, TypeRef}; +use crate::ty::{Attr, SchemaType}; use crate::ty::{Type, TypeKind}; +use indexmap::IndexMap; use kclvm_ast::ast; use kclvm_ast::pos::GetPos; -use kclvm_error::{ErrorKind, Message, Position, Style}; +use kclvm_error::{diagnostic::Range, ErrorKind, Message, Position, Style}; /// Config Expr type check state. /// @@ -33,7 +33,7 @@ impl<'ctx> Resolver<'ctx> { pub(crate) fn new_config_expr_context_item( &mut self, name: &str, - ty: Rc, + ty: TypeRef, start: Position, end: Position, ) -> ScopeObject { @@ -43,7 +43,6 @@ impl<'ctx> Resolver<'ctx> { end, ty, kind: ScopeObjectKind::Attribute, - used: false, doc: None, } } @@ -73,7 +72,15 @@ impl<'ctx> Resolver<'ctx> { let obj = obj.clone(); match obj { Some(obj) => match &obj.ty.kind { - TypeKind::Dict(_, val_ty) => Some(self.new_config_expr_context_item( + TypeKind::List(elem_type) => Some(self.new_config_expr_context_item( + key_name, + elem_type.clone(), + obj.start.clone(), + obj.end.clone(), + )), + TypeKind::Dict(DictType { + key_ty: _, val_ty, .. + }) => Some(self.new_config_expr_context_item( key_name, val_ty.clone(), obj.start.clone(), @@ -84,8 +91,8 @@ impl<'ctx> Resolver<'ctx> { Some(attr_ty_obj) => Some(self.new_config_expr_context_item( key_name, attr_ty_obj.ty.clone(), - attr_ty_obj.pos.clone(), - attr_ty_obj.pos.clone(), + attr_ty_obj.range.0.clone(), + attr_ty_obj.range.1.clone(), )), None => match &schema_ty.index_signature { Some(index_signature) => { @@ -124,12 +131,12 @@ impl<'ctx> Resolver<'ctx> { match key { Some(key) => { let names: Vec = match &key.node { - ast::Expr::Identifier(identifier) => identifier.names.clone(), + ast::Expr::Identifier(identifier) => identifier.get_names(), ast::Expr::Subscript(subscript) => { if let ast::Expr::Identifier(identifier) = &subscript.value.node { if let Some(index) = &subscript.index { if matches!(index.node, ast::Expr::NumberLit(_)) { - identifier.names.clone() + identifier.get_names() } else { return SwitchConfigContextState::KeepConfigUnchanged as usize; } @@ -152,6 +159,15 @@ impl<'ctx> Resolver<'ctx> { } } + /// Switch the context in 'config_expr_context' stack by the list index `[]` + /// + /// Returns: + /// push stack times + #[inline] + pub(crate) fn switch_list_expr_context(&mut self) -> usize { + self.switch_config_expr_context_by_names(&["[]".to_string()]) + } + /// Switch the context in 'config_expr_context' stack by name /// /// find the next item that needs to be pushed into the stack, @@ -185,7 +201,7 @@ impl<'ctx> Resolver<'ctx> { /// Pop method for the 'config_expr_context' stack /// /// Returns: - /// the item poped from stack. + /// the item popped from stack. #[inline] pub(crate) fn restore_config_expr_context(&mut self) -> Option { match self.ctx.config_expr_context.pop() { @@ -242,9 +258,7 @@ impl<'ctx> Resolver<'ctx> { if !name.is_empty() { if let Some(Some(obj)) = self.ctx.config_expr_context.last() { let obj = obj.clone(); - if let TypeKind::Schema(schema_ty) = &obj.ty.kind { - self.check_config_attr(name, &key.get_pos(), schema_ty); - } + self.must_check_config_attr(name, &key.get_span_pos(), &obj.ty); } } } @@ -267,13 +281,13 @@ impl<'ctx> Resolver<'ctx> { if let Some(Some(_)) = self.ctx.config_expr_context.last() { let mut has_index = false; let names: Vec = match &key.node { - ast::Expr::Identifier(identifier) => identifier.names.clone(), + ast::Expr::Identifier(identifier) => identifier.get_names(), ast::Expr::Subscript(subscript) => { if let ast::Expr::Identifier(identifier) = &subscript.value.node { if let Some(index) = &subscript.index { if matches!(index.node, ast::Expr::NumberLit(_)) { has_index = true; - identifier.names.clone() + identifier.get_names() } else { return; } @@ -301,30 +315,96 @@ impl<'ctx> Resolver<'ctx> { } if let Some(Some(obj_last)) = self.ctx.config_expr_context.last() { let ty = obj_last.ty.clone(); - let pos = obj_last.start.clone(); - self.must_assignable_to(val_ty, ty, key.get_pos(), Some(pos)); + self.must_assignable_to( + val_ty, + ty, + key.get_span_pos(), + Some(obj_last.get_span_pos()), + ); } self.clear_config_expr_context(stack_depth, false); } } } + pub(crate) fn get_config_attr_err_suggestion( + &self, + attr: &str, + schema_ty: &SchemaType, + ) -> (Vec, String) { + let mut suggestion = String::new(); + // Calculate the closest miss attributes. + let suggs = suggestions::provide_suggestions(attr, schema_ty.attrs.keys()); + if suggs.len() > 0 { + suggestion = format!(", did you mean '{:?}'?", suggs); + } + (suggs, suggestion) + } + /// Check config attr has been defined. - pub(crate) fn check_config_attr(&mut self, attr: &str, pos: &Position, schema_ty: &SchemaType) { + pub(crate) fn must_check_config_attr(&mut self, attr: &str, range: &Range, ty: &TypeRef) { + if let TypeKind::Schema(schema_ty) = &ty.kind { + self.check_config_attr(attr, range, schema_ty) + } else if let TypeKind::Union(types) = &ty.kind { + let mut schema_names = vec![]; + let mut total_suggs = vec![]; + for ty in types { + if let TypeKind::Schema(schema_ty) = &ty.kind { + if schema_ty.get_obj_of_attr(attr).is_none() + && !schema_ty.is_mixin + && schema_ty.index_signature.is_none() + { + let mut suggs = + suggestions::provide_suggestions(attr, schema_ty.attrs.keys()); + total_suggs.append(&mut suggs); + schema_names.push(schema_ty.name.clone()); + } else { + // If there is a schema attribute that meets the condition, the type check passes + return; + } + } + } + if !schema_names.is_empty() { + self.handler.add_compile_error_with_suggestions( + &format!( + "Cannot add member '{}' to '{}'{}", + attr, + if schema_names.len() > 1 { + format!("schemas {:?}", schema_names) + } else { + format!("schema {}", schema_names[0]) + }, + if total_suggs.is_empty() { + "".to_string() + } else { + format!(", did you mean '{:?}'?", total_suggs) + }, + ), + range.clone(), + Some(total_suggs), + ); + } + } + } + + /// Check config attr has been defined. + pub(crate) fn check_config_attr(&mut self, attr: &str, range: &Range, schema_ty: &SchemaType) { let runtime_type = kclvm_runtime::schema_runtime_type(&schema_ty.name, &schema_ty.pkgpath); match self.ctx.schema_mapping.get(&runtime_type) { Some(schema_mapping_ty) => { - let schema_ty = schema_mapping_ty.borrow(); - if schema_ty.get_obj_of_attr(attr).is_none() - && !schema_ty.is_mixin - && schema_ty.index_signature.is_none() + let schema_ty_ref = schema_mapping_ty.borrow(); + if schema_ty_ref.get_obj_of_attr(attr).is_none() + && !schema_ty_ref.is_mixin + && schema_ty_ref.index_signature.is_none() { - self.handler.add_compile_error( + let (suggs, msg) = self.get_config_attr_err_suggestion(attr, schema_ty); + self.handler.add_compile_error_with_suggestions( &format!( - "Cannot add member '{}' to schema '{}'", - attr, schema_ty.name + "Cannot add member '{}' to schema '{}'{}", + attr, schema_ty_ref.name, msg, ), - pos.clone(), + range.clone(), + Some(suggs), ); } } @@ -333,12 +413,14 @@ impl<'ctx> Resolver<'ctx> { && !schema_ty.is_mixin && schema_ty.index_signature.is_none() { - self.handler.add_compile_error( + let (suggs, msg) = self.get_config_attr_err_suggestion(attr, schema_ty); + self.handler.add_compile_error_with_suggestions( &format!( - "Cannot add member '{}' to schema '{}'", - attr, schema_ty.name + "Cannot add member '{}' to schema '{}'{}", + attr, schema_ty.name, msg, ), - pos.clone(), + range.clone(), + Some(suggs), ); } } @@ -350,7 +432,7 @@ impl<'ctx> Resolver<'ctx> { &mut self, schema_ty: &SchemaType, attr: &str, - ) -> (bool, Rc) { + ) -> (bool, TypeRef) { let runtime_type = kclvm_runtime::schema_runtime_type(&schema_ty.name, &schema_ty.pkgpath); match self.ctx.schema_mapping.get(&runtime_type) { Some(schema_mapping_ty) => { @@ -383,13 +465,18 @@ impl<'ctx> Resolver<'ctx> { &mut self, entries: &'ctx [ast::NodeRef], ) -> TypeRef { - self.enter_scope( - self.ctx.start_pos.clone(), - self.ctx.end_pos.clone(), - ScopeKind::Config, - ); + let (start, end) = match entries.len() { + 0 => (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()), + 1 => entries[0].get_span_pos(), + _ => ( + entries.first().unwrap().get_pos(), + entries.last().unwrap().get_end_pos(), + ), + }; + self.enter_scope(start, end, ScopeKind::Config); let mut key_types: Vec = vec![]; let mut val_types: Vec = vec![]; + let mut attrs: IndexMap = IndexMap::new(); for item in entries { let key = &item.node.key; let value = &item.node.value; @@ -406,22 +493,33 @@ impl<'ctx> Resolver<'ctx> { val_ty = Type::dict_ref(self.str_ty(), val_ty.clone()); } let key_ty = if identifier.names.len() == 1 { - let name = &identifier.names[0]; + let name = &identifier.names[0].node; let key_ty = if self.ctx.local_vars.contains(name) { self.expr(key) } else { - Rc::new(Type::str_lit(name)) + Arc::new(Type::str_lit(name)) }; - self.check_attr_ty(&key_ty, key.get_pos()); + self.check_attr_ty(&key_ty, key.get_span_pos()); + let ty = if let Some(attr) = attrs.get(name) { + sup(&[attr.ty.clone(), val_ty.clone()]) + } else { + val_ty.clone() + }; + attrs.insert( + name.to_string(), + Attr { + ty: self.ctx.ty_ctx.infer_to_variable_type(ty.clone()), + range: key.get_span_pos(), + }, + ); self.insert_object( name, ScopeObject { name: name.to_string(), start: key.get_pos(), end: key.get_end_pos(), - ty: val_ty.clone(), + ty, kind: ScopeObjectKind::Attribute, - used: false, doc: None, }, ); @@ -445,17 +543,28 @@ impl<'ctx> Resolver<'ctx> { _ => { let key_ty = self.expr(key); let val_ty = self.expr(value); - self.check_attr_ty(&key_ty, key.get_pos()); + self.check_attr_ty(&key_ty, key.get_span_pos()); if let ast::Expr::StringLit(string_lit) = &key.node { + let ty = if let Some(attr) = attrs.get(&string_lit.value) { + sup(&[attr.ty.clone(), val_ty.clone()]) + } else { + val_ty.clone() + }; + attrs.insert( + string_lit.value.clone(), + Attr { + ty: self.ctx.ty_ctx.infer_to_variable_type(ty.clone()), + range: key.get_span_pos(), + }, + ); self.insert_object( &string_lit.value, ScopeObject { name: string_lit.value.clone(), start: key.get_pos(), end: key.get_end_pos(), - ty: val_ty.clone(), + ty, kind: ScopeObjectKind::Attribute, - used: false, doc: None, }, ); @@ -471,7 +580,7 @@ impl<'ctx> Resolver<'ctx> { TypeKind::None | TypeKind::Any => { val_types.push(val_ty.clone()); } - TypeKind::Dict(key_ty, val_ty) => { + TypeKind::Dict(DictType { key_ty, val_ty, .. }) => { key_types.push(key_ty.clone()); val_types.push(val_ty.clone()); } @@ -500,7 +609,7 @@ impl<'ctx> Resolver<'ctx> { "only dict and schema can be used ** unpack, got '{}'", val_ty.ty_str() ), - value.get_pos(), + value.get_span_pos(), ); } } @@ -515,13 +624,14 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalAttributeError, &[Message { - pos: value.get_pos(), + range: value.get_span_pos(), style: Style::LineAndColumn, message: format!( "only list type can in inserted, got '{}'", val_ty.ty_str() ), note: None, + suggested_replacement: None, }], ); } @@ -530,6 +640,6 @@ impl<'ctx> Resolver<'ctx> { self.leave_scope(); let key_ty = sup(&key_types); let val_ty = sup(&val_types); - Type::dict_ref(key_ty, val_ty) + Type::dict_ref_with_attrs(key_ty, val_ty, attrs) } } diff --git a/kclvm/sema/src/resolver/doc.rs b/kclvm/sema/src/resolver/doc.rs index 1dd8c85c5..16074431e 100644 --- a/kclvm/sema/src/resolver/doc.rs +++ b/kclvm/sema/src/resolver/doc.rs @@ -1,19 +1,25 @@ -use regex::Regex; -use std::collections::HashSet; +use kclvm_ast::ast::SchemaStmt; +use pcre2::bytes::Regex; +use std::collections::{HashMap, HashSet}; use std::iter::Iterator; +use std::str; + +lazy_static::lazy_static! { + static ref RE: Regex = Regex::new(r#"(?s)^(['\"]{3})(.*?)(['\"]{3})$"#).unwrap(); +} /// strip leading and trailing triple quotes from the original docstring content fn strip_quotes(original: &mut String) { let quote = original.chars().next().unwrap(); - let pattern = format!("(?s)^{char}{{3}}(.*?){char}{{3}}$", char = quote); - let re = Regex::new(&pattern).unwrap(); - let caps = re.captures(&original); - let result = match caps { - Some(caps) => caps, - None => return, - }; - let content = result[1].to_owned(); - *original = content; + if quote != '"' && quote != '\'' { + return; + } + if let Ok(Some(mat)) = RE.find(original.as_bytes()) { + let content = str::from_utf8(&original.as_bytes()[mat.start() + 3..mat.end() - 3]) + .unwrap() + .to_owned(); + *original = content; + } } fn expand_tabs(s: &str, spaces_per_tab: usize) -> String { @@ -35,10 +41,14 @@ fn clean_doc(doc: &mut String) { .unwrap_or(0); lines[1..].iter_mut().for_each(|line| { - *line = if line.len() > 0 { - &line[margin..] + *line = if line.trim().len() > 0 { + if let Some(sub) = line.get(margin..) { + sub + } else { + line.trim() + } } else { - line + line.trim() }; // remove command indentation }); @@ -212,9 +222,9 @@ fn parse_attr_list(content: String) -> Vec { while !r.eof() { let header = r.read(); let header = header.trim(); - if header.contains(" : ") { - let parts: Vec<&str> = header.split(" : ").collect(); - let arg_name = parts[0]; + if header.contains(": ") { + let parts: Vec<&str> = header.split(": ").collect(); + let arg_name = parts[0].trim(); let desc_lines = r .read_to_next_unindented_line() @@ -248,9 +258,9 @@ fn parse_summary(doc: &mut Reader) -> String { /// parse the schema docstring to Doc. /// The summary of the schema content will be concatenated to a single line string by whitespaces. /// The description of each attribute will be returned as separate lines. -pub(crate) fn parse_doc_string(ori: &String) -> Doc { +pub fn parse_doc_string(ori: &String) -> Doc { if ori.is_empty() { - return Doc::new("".to_string(), vec![]); + return Doc::new("".to_string(), vec![], HashMap::new()); } let mut ori = ori.clone(); strip_quotes(&mut ori); @@ -265,25 +275,79 @@ pub(crate) fn parse_doc_string(ori: &String) -> Doc { let attrs = parse_attr_list(attr_content); - Doc::new(summary, attrs) + let mut examples = HashMap::new(); + let example_section = read_to_next_section(&mut doc); + if !example_section.is_empty() { + let default_example_content = match example_section.len() { + 0 | 1 | 2 => "".to_string(), + _ => example_section[2..].join("\n"), + }; + examples.insert( + "Default example".to_string(), + Example::new("".to_string(), "".to_string(), default_example_content), + ); + } + Doc::new(summary, attrs, examples) } /// The Doc struct contains a summary of schema and all the attributes described in the the docstring. -#[derive(Debug)] -pub(crate) struct Doc { +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Doc { pub summary: String, pub attrs: Vec, + pub examples: HashMap, } impl Doc { - fn new(summary: String, attrs: Vec) -> Self { - Self { summary, attrs } + pub fn new(summary: String, attrs: Vec, examples: HashMap) -> Self { + Self { + summary, + attrs, + examples, + } + } + pub fn new_from_schema_stmt(schema: &SchemaStmt) -> Self { + let attrs = schema + .get_left_identifier_list() + .iter() + .map(|(_, _, attr_name)| attr_name.clone()) + .collect::>(); + Self { + summary: "".to_string(), + attrs: attrs + .iter() + .map(|name| Attribute::new(name.clone(), vec![])) + .collect(), + examples: HashMap::new(), + } + } + + pub fn to_doc_string(self) -> String { + let summary = self.summary; + let attrs_string = self + .attrs + .iter() + .map(|attr| format!("{}: {}", attr.name, attr.desc.join("\n"))) + .collect::>() + .join("\n"); + let examples_string = self + .examples + .values() + .map(|example| { + format!( + "{}\n{}\n{}", + example.summary, example.description, example.value + ) + }) + .collect::>() + .join("\n"); + format!("{summary}\n\nAttributes\n----------\n{attrs_string}\n\nExamples\n--------{examples_string}\n") } } /// The Attribute struct contains the attribute name and the corresponding description. -#[derive(Debug)] -pub(crate) struct Attribute { +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Attribute { pub name: String, pub desc: Vec, } @@ -294,10 +358,28 @@ impl Attribute { } } +/// The Example struct contains the example summary and the literal content +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Example { + pub summary: String, + pub description: String, + pub value: String, +} + +impl Example { + fn new(summary: String, description: String, value: String) -> Self { + Self { + summary, + description, + value, + } + } +} + #[cfg(test)] mod tests { use super::{clean_doc, is_at_section, read_to_next_section, strip_quotes, Reader}; - use crate::resolver::doc::parse_doc_string; + use crate::resolver::doc::{parse_doc_string, Example}; use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; @@ -345,11 +427,11 @@ de", A Server-level attribute. The name of the long-running service. See also: kusion_models/core/v1/metadata.k. - labels : {str:str}, optional + labels: {str:str}, optional A Server-level attribute. The labels of the long-running service. See also: kusion_models/core/v1/metadata.k. - + Examples ---------------------- myCustomApp = AppConfiguration { @@ -383,7 +465,7 @@ name : str, required A Server-level attribute. The name of the long-running service. See also: kusion_models/core/v1/metadata.k. -labels : {str:str}, optional +labels: {str:str}, optional A Server-level attribute. The labels of the long-running service. See also: kusion_models/core/v1/metadata.k. @@ -577,5 +659,17 @@ unindented line "See also: kusion_models/core/v1/metadata.k.".to_string(), ] ); + assert!(doc.examples.contains_key("Default example")); + assert_eq!( + doc.examples.get("Default example"), + Some(&Example::new( + "".to_string(), + "".to_string(), + "myCustomApp = AppConfiguration { + name = \"componentName\" +}" + .to_string() + )) + ); } } diff --git a/kclvm/sema/src/resolver/global.rs b/kclvm/sema/src/resolver/global.rs index d873e99f8..f0921f674 100644 --- a/kclvm/sema/src/resolver/global.rs +++ b/kclvm/sema/src/resolver/global.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::rc::Rc; +use std::sync::Arc; use crate::info::is_private_field; use crate::resolver::Resolver; @@ -9,7 +9,7 @@ use crate::ty::{ }; use indexmap::IndexMap; use kclvm_ast::ast; -use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_ast_pretty::{print_ast_node, print_schema_expr, ASTNode}; use kclvm_error::*; use super::doc::parse_doc_string; @@ -39,24 +39,42 @@ impl<'ctx> Resolver<'ctx> { let (name, doc, is_mixin, is_protocol, is_rule) = match &stmt.node { ast::Stmt::Schema(schema_stmt) => ( &schema_stmt.name.node, - &schema_stmt.doc, + { + if let Some(doc) = &schema_stmt.doc { + doc.node.clone() + } else { + "".to_string() + } + }, schema_stmt.is_mixin, schema_stmt.is_protocol, false, ), - ast::Stmt::Rule(rule_stmt) => { - (&rule_stmt.name.node, &rule_stmt.doc, false, false, true) - } + ast::Stmt::Rule(rule_stmt) => ( + &rule_stmt.name.node, + { + if let Some(doc) = &rule_stmt.doc { + doc.node.clone() + } else { + "".to_string() + } + }, + false, + false, + true, + ), + _ => continue, }; if self.contains_object(name) { self.handler.add_error( ErrorKind::UniqueKeyError, &[Message { - pos: start.clone(), + range: stmt.get_span_pos(), style: Style::LineAndColumn, message: format!("unique key error name '{}'", name), note: None, + suggested_replacement: None, }], ); continue; @@ -67,6 +85,7 @@ impl<'ctx> Resolver<'ctx> { pkgpath: self.ctx.pkgpath.clone(), filename: self.ctx.filename.clone(), doc: parsed_doc.summary.clone(), + examples: parsed_doc.examples, is_instance: false, is_mixin, is_protocol, @@ -79,7 +98,7 @@ impl<'ctx> Resolver<'ctx> { doc: parsed_doc.summary.clone(), params: vec![], self_ty: None, - return_ty: Rc::new(Type::VOID), + return_ty: Arc::new(Type::VOID), is_variadic: false, kw_only_index: None, }), @@ -92,9 +111,8 @@ impl<'ctx> Resolver<'ctx> { name: name.to_string(), start, end, - ty: Rc::new(Type::schema(schema_ty.clone())), + ty: Arc::new(Type::schema(schema_ty.clone())), kind: ScopeObjectKind::Definition, - used: false, doc: Some(parsed_doc.summary.clone()), }, ) @@ -137,9 +155,8 @@ impl<'ctx> Resolver<'ctx> { name: schema_ty.name.to_string(), start, end, - ty: Rc::new(Type::schema(schema_ty.clone())), + ty: Arc::new(Type::schema(schema_ty.clone())), kind: ScopeObjectKind::Definition, - used: false, doc: Some(schema_ty.doc), }, ) @@ -170,17 +187,19 @@ impl<'ctx> Resolver<'ctx> { } } None => { + let pos = Position { + filename: self.ctx.filename.clone(), + line: 1, + column: None, + }; self.handler.add_error( ErrorKind::CannotFindModule, &[Message { - pos: Position { - filename: self.ctx.filename.clone(), - line: 1, - column: None, - }, + range: (pos.clone(), pos), style: Style::Line, message: format!("pkgpath {} not found in the program", self.ctx.pkgpath), note: None, + suggested_replacement: None, }], ); } @@ -198,7 +217,7 @@ impl<'ctx> Resolver<'ctx> { self.init_scope_with_assign_stmt(assign_stmt, unique_check) } ast::Stmt::Unification(unification_stmt) => { - self.init_scope_with_unification_stmt(unification_stmt, unique_check) + self.init_scope_with_unification_stmt(unification_stmt) } ast::Stmt::If(if_stmt) => { self.init_scope_with_stmts(&if_stmt.body, unique_check); @@ -216,49 +235,52 @@ impl<'ctx> Resolver<'ctx> { ) { for target in &assign_stmt.targets { if target.node.names.is_empty() { - self.handler - .add_compile_error("missing target in the assign statement", target.get_pos()); + self.handler.add_compile_error( + "missing target in the assign statement", + target.get_span_pos(), + ); continue; } - let name = &target.node.names[0]; + let name = &target.node.names[0].node; let (start, end) = target.get_span_pos(); if self.contains_object(name) && !is_private_field(name) && unique_check { self.handler.add_error( ErrorKind::ImmutableError, &[ Message { - pos: start.clone(), + range: target.get_span_pos(), style: Style::LineAndColumn, message: format!( "Can not change the value of '{}', because it was declared immutable", name ), note: None, + suggested_replacement: None, }, Message { - pos: self + range: self .scope .borrow() .elems .get(name) .unwrap() .borrow() - .start - .clone(), + .get_span_pos(), style: Style::LineAndColumn, message: format!("The variable '{}' is declared here", name), note: Some(format!( "change the variable name to '_{}' to make it mutable", name )), + suggested_replacement: None, }, ], ); continue; } let ty = if let Some(ty_annotation) = &assign_stmt.ty { - let ty = &ty_annotation.node; - let ty = self.parse_ty_with_scope(ty, ty_annotation.get_pos()); + let ty = + self.parse_ty_with_scope(Some(&ty_annotation), ty_annotation.get_span_pos()); if let Some(obj) = self.scope.borrow().elems.get(name) { let obj = obj.borrow(); if !is_upper_bound(obj.ty.clone(), ty.clone()) { @@ -266,7 +288,7 @@ impl<'ctx> Resolver<'ctx> { ErrorKind::TypeError, &[ Message { - pos: start.clone(), + range: target.get_span_pos(), style: Style::LineAndColumn, message: format!( "can not change the type of '{}' to {}", @@ -274,12 +296,14 @@ impl<'ctx> Resolver<'ctx> { obj.ty.ty_str() ), note: None, + suggested_replacement: None, }, Message { - pos: obj.start.clone(), + range: obj.get_span_pos(), style: Style::LineAndColumn, message: format!("expected {}", obj.ty.ty_str()), note: None, + suggested_replacement: None, }, ], ); @@ -299,59 +323,20 @@ impl<'ctx> Resolver<'ctx> { end, ty, kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); } } - fn init_scope_with_unification_stmt( - &mut self, - unification_stmt: &'ctx ast::UnificationStmt, - unique_check: bool, - ) { + fn init_scope_with_unification_stmt(&mut self, unification_stmt: &'ctx ast::UnificationStmt) { let target = &unification_stmt.target; if target.node.names.is_empty() { return; } - let name = &target.node.names[0]; + let name = &target.node.names[0].node; let (start, end) = target.get_span_pos(); - if self.contains_object(name) && !is_private_field(name) && unique_check { - self.handler.add_error( - ErrorKind::ImmutableError, - &[ - Message { - pos: start, - style: Style::LineAndColumn, - message: format!( - "Can not change the value of '{}', because it was declared immutable", - name - ), - note: None, - }, - Message { - pos: self - .scope - .borrow() - .elems - .get(name) - .unwrap() - .borrow() - .start - .clone(), - style: Style::LineAndColumn, - message: format!("The variable '{}' is declared here", name), - note: Some(format!( - "change the variable name to '_{}' to make it mutable", - name - )), - }, - ], - ); - return; - } - let ty = self.walk_identifier(&unification_stmt.value.node.name.node); + let ty = self.walk_identifier_expr(&unification_stmt.value.node.name); self.insert_object( name, ScopeObject { @@ -360,7 +345,6 @@ impl<'ctx> Resolver<'ctx> { end, ty, kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); @@ -371,7 +355,7 @@ impl<'ctx> Resolver<'ctx> { rule_stmt: &'ctx ast::RuleStmt, ) -> Option> { if let Some(host_name) = &rule_stmt.for_host_name { - let ty = self.walk_identifier(&host_name.node); + let ty = self.walk_identifier_expr(&host_name); match &ty.kind { TypeKind::Schema(schema_ty) if schema_ty.is_protocol && !schema_ty.is_instance => { Some(Box::new(schema_ty.clone())) @@ -380,13 +364,14 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: host_name.get_pos(), + range: host_name.get_span_pos(), style: Style::LineAndColumn, message: format!( "invalid schema inherit object type, expect protocol, got '{}'", ty.ty_str() ), note: None, + suggested_replacement: None, }], ); None @@ -406,16 +391,17 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: host_name.get_pos(), + range: host_name.get_span_pos(), style: Style::LineAndColumn, message: "only schema mixin can inherit from protocol".to_string(), note: None, + suggested_replacement: None, }], ); return None; } // Mixin type check with protocol - let ty = self.walk_identifier(&host_name.node); + let ty = self.walk_identifier_expr(&host_name); match &ty.kind { TypeKind::Schema(schema_ty) if schema_ty.is_protocol && !schema_ty.is_instance => { Some(Box::new(schema_ty.clone())) @@ -424,13 +410,14 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: host_name.get_pos(), + range: host_name.get_span_pos(), style: Style::LineAndColumn, message: format!( "invalid schema inherit object type, expect protocol, got '{}'", ty.ty_str() ), note: None, + suggested_replacement: None, }], ); None @@ -446,7 +433,7 @@ impl<'ctx> Resolver<'ctx> { schema_stmt: &'ctx ast::SchemaStmt, ) -> Option> { if let Some(parent_name) = &schema_stmt.parent_name { - let ty = self.walk_identifier(&parent_name.node); + let ty = self.walk_identifier_expr(&parent_name); match &ty.kind { TypeKind::Schema(schema_ty) if !schema_ty.is_protocol && !schema_ty.is_mixin && !schema_ty.is_instance => @@ -457,13 +444,14 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: parent_name.get_pos(), + range: parent_name.get_span_pos(), style: Style::LineAndColumn, message: format!( "invalid schema inherit object type, expect schema, got '{}'", ty.ty_str() ), note: None, + suggested_replacement: None, }], ); None @@ -482,31 +470,31 @@ impl<'ctx> Resolver<'ctx> { should_add_schema_ref: bool, ) -> SchemaType { let name = &schema_stmt.name.node; - let pos = schema_stmt.name.get_end_pos(); if RESERVED_TYPE_IDENTIFIERS.contains(&name.as_str()) { self.handler.add_compile_error( &format!( "schema name '{}' cannot be the same as the built-in types ({:?})", name, RESERVED_TYPE_IDENTIFIERS ), - pos.clone(), + schema_stmt.name.get_span_pos(), ); } if schema_stmt.is_protocol && !name.ends_with(PROTOCOL_SUFFIX) { self.handler.add_error( ErrorKind::CompileError, &[Message { - pos: pos.clone(), + range: schema_stmt.name.get_span_pos(), style: Style::LineAndColumn, message: format!("schema protocol name must end with '{}'", PROTOCOL_SUFFIX), note: None, + suggested_replacement: None, }], ); } if schema_stmt.is_protocol && !schema_stmt.has_only_attribute_definitions() { self.handler.add_compile_error( "a protocol is only allowed to define attributes in it", - pos.clone(), + schema_stmt.name.get_span_pos(), ); } let parent_name = parent_ty @@ -516,10 +504,11 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: pos.clone(), + range: schema_stmt.name.get_span_pos(), style: Style::LineAndColumn, message: format!("mixin inheritance {} is prohibited", parent_name), note: None, + suggested_replacement: None, }], ); } @@ -534,21 +523,22 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IndexSignatureError, &[Message { - pos: index_signature.get_pos(), + range: index_signature.get_span_pos(), style: Style::LineAndColumn, message: format!("index signature attribute name '{}' cannot have the same name as schema attributes", index_sign_name), note: None, + suggested_replacement: None, }], ); } } let key_ty = self.parse_ty_str_with_scope( - &index_signature.node.key_type.node, - index_signature.node.key_type.get_pos(), + &index_signature.node.key_ty.node.to_string(), + index_signature.node.key_ty.get_span_pos(), ); let val_ty = self.parse_ty_with_scope( - &index_signature.node.value_ty.node, - index_signature.node.value_type.get_pos(), + Some(&index_signature.node.value_ty), + index_signature.node.value_ty.get_span_pos(), ); if !self .ctx @@ -558,10 +548,11 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IndexSignatureError, &[Message { - pos: pos.clone(), + range: schema_stmt.name.get_span_pos(), style: Style::LineAndColumn, message: format!("invalid index signature key type: '{}'", key_ty.ty_str()), note: None, + suggested_replacement: None, }], ); } @@ -576,45 +567,59 @@ impl<'ctx> Resolver<'ctx> { }; // Schema attributes let mut attr_obj_map: IndexMap = IndexMap::default(); - attr_obj_map.insert( - kclvm_runtime::SCHEMA_SETTINGS_ATTR_NAME.to_string(), - SchemaAttr { - is_optional: true, - has_default: false, - ty: Type::dict_ref(self.str_ty(), self.any_ty()), - pos: Position { - filename: self.ctx.filename.clone(), - line: pos.line, - column: pos.column, - }, - doc: None, - }, + let parsed_doc = parse_doc_string( + &schema_stmt + .doc + .as_ref() + .map(|doc| doc.node.clone()) + .unwrap_or_default(), ); - let parsed_doc = parse_doc_string(&schema_stmt.doc); for stmt in &schema_stmt.body { - let pos = stmt.get_pos(); - let (name, ty, is_optional, has_default) = match &stmt.node { + let (name, ty, is_optional, default, decorators, range) = match &stmt.node { ast::Stmt::Unification(unification_stmt) => { let name = unification_stmt.value.node.name.node.get_name(); - let ty = self.parse_ty_str_with_scope(&name, pos.clone()); - let is_optional = true; - let has_default = true; + let ty = self.parse_ty_str_with_scope(&name, stmt.get_span_pos()); + let is_optional = false; + let default = if self.options.resolve_val { + print_schema_expr(&unification_stmt.value.node) + } else { + "".to_string() + }; ( unification_stmt.target.node.get_name(), ty, is_optional, - has_default, + Some(default), + vec![], + stmt.get_span_pos(), ) } ast::Stmt::SchemaAttr(schema_attr) => { let name = schema_attr.name.node.clone(); - let ty = self.parse_ty_with_scope( - &schema_attr.ty.node.clone(), - schema_attr.ty.get_pos(), - ); + let ty = self + .parse_ty_with_scope(Some(&schema_attr.ty), schema_attr.ty.get_span_pos()); let is_optional = schema_attr.is_optional; - let has_default = schema_attr.value.is_some(); - (name, ty, is_optional, has_default) + let default = schema_attr.value.as_ref().map(|v| { + if self.options.resolve_val { + print_ast_node(ASTNode::Expr(v)) + } else { + "".to_string() + } + }); + // Schema attribute decorators + let decorators = self.resolve_decorators( + &schema_attr.decorators, + DecoratorTarget::Attribute, + &name, + ); + ( + name, + ty, + is_optional, + default, + decorators, + stmt.get_span_pos(), + ) } _ => continue, }; @@ -635,10 +640,12 @@ impl<'ctx> Resolver<'ctx> { name.clone(), SchemaAttr { is_optional: existed_attr.map_or(is_optional, |attr| attr.is_optional), - has_default, + has_default: default.is_some(), + default, ty: ty.clone(), - pos: pos.clone(), + range: range.clone(), doc: doc_str, + decorators, }, ); } @@ -652,7 +659,7 @@ impl<'ctx> Resolver<'ctx> { attr_obj_map.get(&name).unwrap().ty.clone().ty_str(), ty.ty_str() ), - pos.clone(), + stmt.get_span_pos(), ); } if is_optional && !attr_obj_map.get(&name).unwrap().is_optional { @@ -661,7 +668,7 @@ impl<'ctx> Resolver<'ctx> { "can't change the required schema attribute of '{}' to optional", name ), - pos.clone(), + stmt.get_span_pos(), ); } if let Some(ref index_signature_obj) = index_signature { @@ -671,10 +678,11 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IndexSignatureError, &[Message { - pos: pos.clone(), + range: stmt.get_span_pos(), style: Style::LineAndColumn, message: format!("the type '{}' of schema attribute '{}' does not meet the index signature definition {}", ty.ty_str(), name, index_signature_obj.ty_str()), note: None, + suggested_replacement: None, }], ); } @@ -683,22 +691,23 @@ impl<'ctx> Resolver<'ctx> { // Mixin types let mut mixin_types: Vec = vec![]; for mixin in &schema_stmt.mixins { - let mixin_names = &mixin.node.names; + let mixin_names = &mixin.node.get_names(); if !mixin_names[mixin_names.len() - 1].ends_with(MIXIN_SUFFIX) { self.handler.add_error( ErrorKind::NameError, &[Message { - pos: mixin.get_pos(), + range: mixin.get_span_pos(), style: Style::LineAndColumn, message: format!( "a valid mixin name should end with 'Mixin', got '{}'", mixin_names[mixin_names.len() - 1] ), note: None, + suggested_replacement: None, }], ); } - let ty = self.walk_identifier(&mixin.node); + let ty = self.walk_identifier_expr(&mixin); let mixin_ty = match &ty.kind { TypeKind::Schema(schema_ty) if !schema_ty.is_protocol && schema_ty.is_mixin && !schema_ty.is_instance => @@ -709,13 +718,14 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: mixin.get_pos(), + range: mixin.get_span_pos(), style: Style::LineAndColumn, message: format!( "illegal schema mixin object type, expected mixin, got '{}'", ty.ty_str() ), note: None, + suggested_replacement: None, }], ); None @@ -736,22 +746,21 @@ impl<'ctx> Resolver<'ctx> { if let Some(args) = &schema_stmt.args { for (i, para) in args.node.args.iter().enumerate() { let name = para.node.get_name(); - let pos = para.get_pos(); if schema_attr_names.contains(&name) { self.handler.add_compile_error( &format!( "Unexpected parameter name '{}' with the same name as the schema attribute", name ), - pos.clone(), + para.get_span_pos(), ); } - let ty = args.node.get_arg_type(i); - let ty = self.parse_ty_with_scope(&ty, pos); + let ty = args.node.get_arg_type_node(i); + let ty = self.parse_ty_with_scope(ty, para.get_span_pos()); params.push(Parameter { name, ty: ty.clone(), - has_default: args.node.defaults.get(i).is_some(), + has_default: args.node.defaults.get(i).map_or(false, |arg| arg.is_some()), }); } } @@ -769,7 +778,7 @@ impl<'ctx> Resolver<'ctx> { "There is a circular reference between schema {} and {}", name, parent_ty.name, ), - schema_stmt.get_pos(), + schema_stmt.get_span_pos(), ); } } @@ -784,6 +793,7 @@ impl<'ctx> Resolver<'ctx> { pkgpath: self.ctx.pkgpath.clone(), filename: self.ctx.filename.clone(), doc: parsed_doc.summary.clone(), + examples: parsed_doc.examples, is_instance: false, is_mixin: schema_stmt.is_mixin, is_protocol: schema_stmt.is_protocol, @@ -796,7 +806,7 @@ impl<'ctx> Resolver<'ctx> { doc: parsed_doc.summary.clone(), params, self_ty: None, - return_ty: Rc::new(Type::ANY), + return_ty: Arc::new(Type::ANY), is_variadic: false, kw_only_index: None, }), @@ -805,7 +815,7 @@ impl<'ctx> Resolver<'ctx> { }; self.ctx .schema_mapping - .insert(schema_runtime_ty, Rc::new(RefCell::new(schema_ty.clone()))); + .insert(schema_runtime_ty, Arc::new(RefCell::new(schema_ty.clone()))); schema_ty } @@ -816,20 +826,19 @@ impl<'ctx> Resolver<'ctx> { should_add_schema_ref: bool, ) -> SchemaType { let name = &rule_stmt.name.node; - let pos = rule_stmt.name.get_end_pos(); if RESERVED_TYPE_IDENTIFIERS.contains(&name.as_str()) { self.handler.add_compile_error( &format!( "rule name '{}' cannot be the same as the built-in types ({:?})", name, RESERVED_TYPE_IDENTIFIERS ), - pos, + rule_stmt.name.get_span_pos(), ); } // Parent types let mut parent_types: Vec = vec![]; for rule in &rule_stmt.parent_rules { - let ty = self.walk_identifier(&rule.node); + let ty = self.walk_identifier_expr(&rule); let parent_ty = match &ty.kind { TypeKind::Schema(schema_ty) if schema_ty.is_rule && !schema_ty.is_instance => { Some(schema_ty.clone()) @@ -838,10 +847,11 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalInheritError, &[Message { - pos: rule.get_pos(), + range: rule.get_span_pos(), style: Style::LineAndColumn, message: format!("illegal rule type '{}'", ty.ty_str()), note: None, + suggested_replacement: None, }], ); None @@ -856,9 +866,8 @@ impl<'ctx> Resolver<'ctx> { if let Some(args) = &rule_stmt.args { for (i, para) in args.node.args.iter().enumerate() { let name = para.node.get_name(); - let pos = para.get_pos(); - let ty = args.node.get_arg_type(i); - let ty = self.parse_ty_with_scope(&ty, pos); + let ty = args.node.get_arg_type_node(i); + let ty = self.parse_ty_with_scope(ty, para.get_span_pos()); params.push(Parameter { name, ty: ty.clone(), @@ -880,7 +889,7 @@ impl<'ctx> Resolver<'ctx> { "There is a circular reference between rule {} and {}", name, parent_ty.name, ), - rule_stmt.get_pos(), + rule_stmt.get_span_pos(), ); } } @@ -890,11 +899,24 @@ impl<'ctx> Resolver<'ctx> { DecoratorTarget::Schema, &rule_stmt.name.node, ); + + let parsed_doc = parse_doc_string( + &rule_stmt + .doc + .as_ref() + .map(|doc| doc.node.clone()) + .unwrap_or_default(), + ); + let index_signature = match &protocol_ty { + Some(ty) => ty.index_signature.clone(), + None => None, + }; SchemaType { name: rule_stmt.name.node.clone(), pkgpath: self.ctx.pkgpath.clone(), filename: self.ctx.filename.clone(), - doc: rule_stmt.doc.clone(), + doc: parsed_doc.summary.clone(), + examples: parsed_doc.examples, is_instance: false, is_mixin: false, is_protocol: false, @@ -904,14 +926,18 @@ impl<'ctx> Resolver<'ctx> { mixins: parent_types, attrs: IndexMap::default(), func: Box::new(FunctionType { - doc: rule_stmt.doc.clone(), + doc: rule_stmt + .doc + .as_ref() + .map(|doc| doc.node.clone()) + .unwrap_or_default(), params, self_ty: None, - return_ty: Rc::new(Type::ANY), + return_ty: Arc::new(Type::ANY), is_variadic: false, kw_only_index: None, }), - index_signature: None, + index_signature, decorators, } } diff --git a/kclvm/sema/src/resolver/import.rs b/kclvm/sema/src/resolver/import.rs index e3901fa1b..0bf2d3717 100644 --- a/kclvm/sema/src/resolver/import.rs +++ b/kclvm/sema/src/resolver/import.rs @@ -1,17 +1,21 @@ use crate::plugin::PLUGIN_MODULE_PREFIX; +use crate::resolver::scope::Module; use crate::resolver::Resolver; use crate::ty::ModuleKind; use crate::{ builtin::system_module::STANDARD_SYSTEM_MODULES, ty::{Type, TypeKind}, }; -use indexmap::IndexMap; +use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast; use kclvm_error::*; -use std::{cell::RefCell, path::Path, rc::Rc}; +use std::rc::Rc; +use std::sync::Arc; +use std::{cell::RefCell, path::Path}; use super::scope::{Scope, ScopeKind, ScopeObject, ScopeObjectKind}; use kclvm_ast::pos::GetPos; +use kclvm_utils::pkgpath::parse_external_pkg_name; impl<'ctx> Resolver<'ctx> { /// Check import error @@ -21,7 +25,7 @@ impl<'ctx> Resolver<'ctx> { for m in modules { for stmt in &m.body { if let ast::Stmt::Import(import_stmt) = &stmt.node { - let pkgpath = &import_stmt.path; + let pkgpath = &import_stmt.path.node; // System module. if STANDARD_SYSTEM_MODULES.contains(&pkgpath.as_str()) { continue; @@ -36,11 +40,7 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::CannotFindModule, &[Message { - pos: Position { - filename: m.filename.clone(), - line: stmt.line, - column: None, - }, + range: stmt.get_span_pos(), style: Style::Line, message: format!( "Cannot find the module {} from {}", @@ -48,25 +48,37 @@ impl<'ctx> Resolver<'ctx> { real_path.to_str().unwrap() ), note: None, + suggested_replacement: None, }], ); + + let mut suggestions = + vec![format!("find more package on 'https://artifacthub.io'")]; + + if let Ok(pkg_name) = parse_external_pkg_name(pkgpath) { + suggestions.insert( + 0, + format!( + "try 'kcl mod add {}' to download the package not found", + pkg_name + ), + ); + } + self.handler.add_suggestions(suggestions); } else { let file = real_path.to_str().unwrap().to_string(); if real_path.is_file() && main_files.contains(&file) { self.handler.add_error( ErrorKind::CompileError, &[Message { - pos: Position { - filename: self.ctx.filename.clone(), - line: stmt.line, - column: None, - }, + range: stmt.get_span_pos(), style: Style::Line, message: format!( "Cannot import {} in the main package", file ), note: None, + suggested_replacement: None, }], ); } @@ -98,16 +110,30 @@ impl<'ctx> Resolver<'ctx> { { match self.ctx.import_names.get_mut(&self.ctx.filename) { Some(mapping) => { + // 'import sub as s' and 'import sub.sub as s' will raise this error. + // 'import sub' and 'import sub' will not raise this error. + // 'import sub as s' and 'import sub as s' will not raise this error. + if let Some(path) = mapping.get(&import_stmt.name) { + if path != &import_stmt.path.node { + self.handler.add_compile_error( + &format!( + "the name '{}' is defined multiple times, '{}' must be defined only once", + import_stmt.name, import_stmt.name + ), + stmt.get_span_pos(), + ); + } + } mapping.insert( import_stmt.name.to_string(), - import_stmt.path.to_string(), + import_stmt.path.node.to_string(), ); } None => { let mut mapping = IndexMap::default(); mapping.insert( import_stmt.name.to_string(), - import_stmt.path.to_string(), + import_stmt.path.node.to_string(), ); self.ctx .import_names @@ -115,16 +141,25 @@ impl<'ctx> Resolver<'ctx> { } } let mut scope = self.scope.borrow_mut(); - let is_user_module = match scope.elems.get(&import_stmt.path) { + let is_user_module = match scope.elems.get(&import_stmt.path.node) { Some(scope_obj) => { let mut obj = scope_obj.borrow_mut(); + match &mut obj.kind { + ScopeObjectKind::Module(m) => { + m.import_stmts.push((stmt.clone(), false)) + }, + _ => bug!( + "invalid module type in the import check function {}", + scope_obj.borrow().ty.ty_str() + ) + } match &obj.ty.kind { TypeKind::Module(module_ty) => { let mut module_ty = module_ty.clone(); module_ty .imported .push(self.ctx.filename.to_string()); - obj.ty = Rc::new(Type::module( + obj.ty = Arc::new(Type::module( &module_ty.pkgpath, &module_ty.imported, module_ty.kind.clone(), @@ -138,34 +173,40 @@ impl<'ctx> Resolver<'ctx> { } } None => { - let kind = - if import_stmt.path.starts_with(PLUGIN_MODULE_PREFIX) { - ModuleKind::Plugin - } else if STANDARD_SYSTEM_MODULES - .contains(&import_stmt.path.as_str()) - { - ModuleKind::System - } else { - ModuleKind::User - }; + let kind = if import_stmt + .path + .node + .starts_with(PLUGIN_MODULE_PREFIX) + { + ModuleKind::Plugin + } else if STANDARD_SYSTEM_MODULES + .contains(&import_stmt.path.node.as_str()) + { + ModuleKind::System + } else { + ModuleKind::User + }; let ty = Type::module( - &import_stmt.path, + &import_stmt.path.node, &[self.ctx.filename.clone()], kind.clone(), ); let (start, end) = stmt.get_span_pos(); + scope.elems.insert( - import_stmt.path.to_string(), + import_stmt.path.node.to_string(), Rc::new(RefCell::new(ScopeObject { - name: import_stmt.path.to_string(), + name: import_stmt.path.node.to_string(), start, end, - ty: Rc::new(ty), - kind: ScopeObjectKind::Module, - used: false, + ty: Arc::new(ty), + kind: ScopeObjectKind::Module(Module { + import_stmts: vec![(stmt.clone(), false)], + }), doc: None, })), ); + matches!(kind, ModuleKind::User) } }; @@ -177,19 +218,19 @@ impl<'ctx> Resolver<'ctx> { let current_filename = self.ctx.filename.clone(); self.ctx .ty_ctx - .add_dependencies(&self.ctx.pkgpath, &import_stmt.path); + .add_dependencies(&self.ctx.pkgpath, &import_stmt.path.node); if self.ctx.ty_ctx.is_cyclic() { self.handler.add_compile_error( &format!( "There is a circular import reference between module {} and {}", - self.ctx.pkgpath, import_stmt.path, + self.ctx.pkgpath, import_stmt.path.node, ), - stmt.get_pos(), + stmt.get_span_pos(), ); } // Switch pkgpath context - if !self.scope_map.contains_key(&import_stmt.path) { - self.check(&import_stmt.path); + if !self.scope_map.contains_key(&import_stmt.path.node) { + self.check(&import_stmt.path.node); } // Restore the current context self.change_package_context(¤t_pkgpath, ¤t_filename); @@ -213,7 +254,7 @@ impl<'ctx> Resolver<'ctx> { elems: IndexMap::default(), start: Position::dummy_pos(), end: Position::dummy_pos(), - kind: ScopeKind::Package(vec![]), + kind: ScopeKind::Package(IndexSet::new()), })); self.scope_map .insert(pkgpath.to_string(), Rc::clone(&scope)); @@ -222,9 +263,6 @@ impl<'ctx> Resolver<'ctx> { self.ctx.pkgpath = pkgpath.to_string(); self.ctx.filename = filename.to_string(); let scope = self.scope_map.get(pkgpath).unwrap().clone(); - if let ScopeKind::Package(files) = &mut scope.borrow_mut().kind { - files.push(filename.to_string()) - } self.scope = scope; } } diff --git a/kclvm/sema/src/resolver/loop.rs b/kclvm/sema/src/resolver/loop.rs index 315f0caca..d251314f2 100644 --- a/kclvm/sema/src/resolver/loop.rs +++ b/kclvm/sema/src/resolver/loop.rs @@ -1,20 +1,16 @@ -use std::rc::Rc; - use crate::resolver::Resolver; -use crate::ty::{sup, Type, TypeKind}; +use crate::ty::{sup, DictType, TypeKind, TypeRef}; use kclvm_ast::ast; -use kclvm_ast::pos::GetPos; -use kclvm_error::Position; +use kclvm_error::diagnostic::Range; impl<'ctx> Resolver<'ctx> { /// Do loop type check including quant and comp for expression. pub(crate) fn do_loop_type_check( &mut self, - target_node: &'ctx ast::NodeRef, - first_var_name: Option, - second_var_name: Option, - iter_ty: Rc, - iter_pos: Position, + first_var_name: Option<&ast::Node>, + second_var_name: Option<&ast::Node>, + iter_ty: TypeRef, + iter_range: Range, ) { let types = match &iter_ty.kind { TypeKind::Union(types) => types.clone(), @@ -26,7 +22,7 @@ impl<'ctx> Resolver<'ctx> { if !(iter_ty.is_iterable() || iter_ty.is_any()) { self.handler.add_compile_error( &format!("'{}' object is not iterable", iter_ty.ty_str()), - iter_pos.clone(), + iter_range.clone(), ); } match &iter_ty.kind { @@ -35,37 +31,37 @@ impl<'ctx> Resolver<'ctx> { first_var_ty = sup(&[self.int_ty(), first_var_ty.clone()]); second_var_ty = sup(&[item_ty.clone(), second_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); self.set_type_to_scope( - second_var_name.as_ref().unwrap(), + &second_var_name.unwrap().node, second_var_ty.clone(), - target_node.get_pos(), + &second_var_name.unwrap(), ); } else { first_var_ty = sup(&[item_ty.clone(), first_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); } } - TypeKind::Dict(key_ty, val_ty) => { + TypeKind::Dict(DictType { key_ty, val_ty, .. }) => { first_var_ty = sup(&[key_ty.clone(), first_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); if second_var_name.is_some() { second_var_ty = sup(&[val_ty.clone(), second_var_ty.clone()]); self.set_type_to_scope( - second_var_name.as_ref().unwrap(), + &second_var_name.unwrap().node, second_var_ty.clone(), - target_node.get_pos(), + &second_var_name.unwrap(), ); } } @@ -73,16 +69,16 @@ impl<'ctx> Resolver<'ctx> { let (key_ty, val_ty) = (schema_ty.key_ty(), schema_ty.val_ty()); first_var_ty = sup(&[key_ty, first_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); if second_var_name.is_some() { second_var_ty = sup(&[val_ty, second_var_ty.clone()]); self.set_type_to_scope( - second_var_name.as_ref().unwrap(), + &second_var_name.unwrap().node, second_var_ty.clone(), - target_node.get_pos(), + &second_var_name.unwrap(), ); } } @@ -91,21 +87,21 @@ impl<'ctx> Resolver<'ctx> { first_var_ty = sup(&[self.int_ty(), first_var_ty.clone()]); second_var_ty = sup(&[self.str_ty(), second_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); self.set_type_to_scope( - second_var_name.as_ref().unwrap(), + &second_var_name.unwrap().node, second_var_ty.clone(), - target_node.get_pos(), + &second_var_name.unwrap(), ); } else { first_var_ty = sup(&[self.str_ty(), first_var_ty.clone()]); self.set_type_to_scope( - first_var_name.as_ref().unwrap(), + &first_var_name.unwrap().node, first_var_ty.clone(), - target_node.get_pos(), + &first_var_name.unwrap(), ); } } diff --git a/kclvm/sema/src/resolver/mod.rs b/kclvm/sema/src/resolver/mod.rs index bd5f4a7d8..805bf3989 100644 --- a/kclvm/sema/src/resolver/mod.rs +++ b/kclvm/sema/src/resolver/mod.rs @@ -2,7 +2,7 @@ mod arg; mod attr; mod calculation; mod config; -mod doc; +pub mod doc; mod format; pub mod global; mod import; @@ -11,27 +11,30 @@ mod node; mod para; mod schema; pub mod scope; -mod ty; +pub(crate) mod ty; mod ty_alias; +mod ty_erasure; mod var; #[cfg(test)] mod tests; use indexmap::IndexMap; +use kclvm_error::diagnostic::Range; +use std::sync::{Arc, Mutex}; use std::{cell::RefCell, rc::Rc}; use crate::lint::{CombinedLintPass, Linter}; use crate::pre_process::pre_process_program; use crate::resolver::scope::ScopeObject; -use crate::resolver::ty_alias::process_program_type_alias; +use crate::resolver::ty_alias::type_alias_pass; +use crate::resolver::ty_erasure::type_func_erasure_pass; +use crate::ty::TypeContext; use crate::{resolver::scope::Scope, ty::SchemaType}; use kclvm_ast::ast::Program; use kclvm_error::*; -use crate::ty::TypeContext; - -use self::scope::{builtin_scope, ProgramScope}; +use self::scope::{builtin_scope, CachedScope, NodeTyMap, ProgramScope}; /// Resolver is responsible for program semantic checking, mainly /// including type checking and contract model checking. @@ -40,6 +43,7 @@ pub struct Resolver<'ctx> { pub scope_map: IndexMap>>, pub scope: Rc>, pub scope_level: usize, + pub node_ty_map: NodeTyMap, pub builtin_scope: Rc>, pub ctx: Context, pub options: Options, @@ -57,6 +61,7 @@ impl<'ctx> Resolver<'ctx> { builtin_scope, scope, scope_level: 0, + node_ty_map: IndexMap::default(), ctx: Context::default(), options, handler: Handler::default(), @@ -65,13 +70,16 @@ impl<'ctx> Resolver<'ctx> { } /// The check main function. - pub(crate) fn check(&mut self, pkgpath: &str) -> ProgramScope { + pub(crate) fn check(&mut self, pkgpath: &str) { self.check_import(pkgpath); self.init_global_types(); match self.program.pkgs.get(pkgpath) { Some(modules) => { for module in modules { self.ctx.filename = module.filename.to_string(); + if let scope::ScopeKind::Package(files) = &mut self.scope.borrow_mut().kind { + files.insert(module.filename.to_string()); + } for stmt in &module.body { self.stmt(&stmt); } @@ -82,15 +90,16 @@ impl<'ctx> Resolver<'ctx> { } None => {} } - ProgramScope { - scope_map: self.scope_map.clone(), - import_names: self.ctx.import_names.clone(), - handler: self.handler.clone(), - } } pub(crate) fn check_and_lint(&mut self, pkgpath: &str) -> ProgramScope { - let mut scope = self.check(pkgpath); + self.check(pkgpath); + let mut scope = ProgramScope { + scope_map: self.scope_map.clone(), + import_names: self.ctx.import_names.clone(), + node_ty_map: self.node_ty_map.clone(), + handler: self.handler.clone(), + }; self.lint_check_scope_map(); for diag in &self.linter.handler.diagnostics { scope.handler.diagnostics.insert(diag.clone()); @@ -109,13 +118,13 @@ pub struct Context { /// What schema are we in. pub schema: Option>>, /// What schema are we in. - pub schema_mapping: IndexMap>>, + pub schema_mapping: IndexMap>>, /// For loop local vars. pub local_vars: Vec, /// Import pkgpath and name pub import_names: IndexMap>, /// Global names at top level of the program. - pub global_names: IndexMap>, + pub global_names: IndexMap>, /// Are we resolving the left value. pub l_value: bool, /// Are we resolving the statement start position. @@ -132,28 +141,67 @@ pub struct Context { pub type_alias_mapping: IndexMap>, } -/// Resolve options -#[derive(Clone, Debug, Default)] +/// Resolve options. +/// - lint_check: whether to run lint passes +/// - resolve_val: whether to resolve and print their AST to value for some nodes. +#[derive(Clone, Debug)] pub struct Options { - pub raise_err: bool, - pub config_auto_fix: bool, pub lint_check: bool, + pub resolve_val: bool, + pub merge_program: bool, + pub type_erasure: bool, } -/// Resolve program -pub fn resolve_program(program: &mut Program) -> ProgramScope { - pre_process_program(program); - let mut resolver = Resolver::new( - program, - Options { - raise_err: true, - config_auto_fix: false, +impl Default for Options { + fn default() -> Self { + Self { lint_check: true, - }, - ); + resolve_val: false, + merge_program: true, + type_erasure: true, + } + } +} + +/// Resolve program with default options. +#[inline] +pub fn resolve_program(program: &mut Program) -> ProgramScope { + resolve_program_with_opts(program, Options::default(), None) +} + +/// Resolve program with options. See [Options] +pub fn resolve_program_with_opts( + program: &mut Program, + opts: Options, + cached_scope: Option>>, +) -> ProgramScope { + pre_process_program(program, &opts); + let mut resolver = Resolver::new(program, opts.clone()); resolver.resolve_import(); + if let Some(cached_scope) = cached_scope.as_ref() { + if let Ok(mut cached_scope) = cached_scope.try_lock() { + cached_scope.update(program); + resolver.scope_map = cached_scope.scope_map.clone(); + resolver.scope_map.remove(kclvm_ast::MAIN_PKG); + resolver.node_ty_map = cached_scope.node_ty_map.clone() + } + } let scope = resolver.check_and_lint(kclvm_ast::MAIN_PKG); - let type_alias_mapping = resolver.ctx.type_alias_mapping.clone(); - process_program_type_alias(program, type_alias_mapping); + if let Some(cached_scope) = cached_scope.as_ref() { + if let Ok(mut cached_scope) = cached_scope.try_lock() { + cached_scope.update(program); + cached_scope.scope_map = scope.scope_map.clone(); + cached_scope.node_ty_map = scope.node_ty_map.clone(); + cached_scope.scope_map.remove(kclvm_ast::MAIN_PKG); + } + } + + if opts.type_erasure { + let type_alias_mapping = resolver.ctx.type_alias_mapping.clone(); + // Erase all the function type to a named type "function" + type_func_erasure_pass(program); + // Erase types with their type alias + type_alias_pass(program, type_alias_mapping); + } scope } diff --git a/kclvm/sema/src/resolver/node.rs b/kclvm/sema/src/resolver/node.rs index c6083e8eb..9774ce2c5 100644 --- a/kclvm/sema/src/resolver/node.rs +++ b/kclvm/sema/src/resolver/node.rs @@ -3,19 +3,18 @@ use kclvm_ast::ast; use kclvm_ast::pos::GetPos; use kclvm_ast::walker::MutSelfTypedResultWalker; use kclvm_error::*; -use std::rc::Rc; +use std::sync::Arc; use crate::info::is_private_field; use crate::ty::{ - sup, DecoratorTarget, Parameter, Type, TypeInferMethods, TypeKind, RESERVED_TYPE_IDENTIFIERS, + sup, DictType, FunctionType, Parameter, Type, TypeInferMethods, TypeKind, TypeRef, + RESERVED_TYPE_IDENTIFIERS, }; use super::format::VALID_FORMAT_SPEC_SET; use super::scope::{ScopeKind, ScopeObject, ScopeObjectKind}; use super::ty::ty_str_replace_pkgpath; use super::Resolver; - -pub type TypeRef = Rc; /// ResolvedResult denotes the result, when the result is error, /// put the message string into the diagnostic vector. pub type ResolvedResult = TypeRef; @@ -34,7 +33,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if expr_types.len() > 1 { self.handler.add_compile_error( "expression statement can only have one expression", - expr_stmt.exprs[1].get_pos(), + expr_stmt.exprs[1].get_span_pos(), ); } ty @@ -51,30 +50,33 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if names.len() > 1 { self.handler.add_compile_error( "unification identifier can not be selected", - unification_stmt.target.get_pos(), + unification_stmt.target.get_span_pos(), ); } let (start, end) = unification_stmt.value.get_span_pos(); if names.is_empty() { - self.handler - .add_compile_error("missing target in the unification statement", start); + self.handler.add_compile_error( + "missing target in the unification statement", + unification_stmt.value.get_span_pos(), + ); return self.any_ty(); } self.ctx.l_value = true; let expected_ty = self.walk_identifier_expr(&unification_stmt.target); self.ctx.l_value = false; - let obj = self.new_config_expr_context_item(&names[0], expected_ty.clone(), start, end); + let obj = + self.new_config_expr_context_item(&names[0].node, expected_ty.clone(), start, end); let init_stack_depth = self.switch_config_expr_context(Some(obj)); let ty = self.walk_schema_expr(&unification_stmt.value.node); self.clear_config_expr_context(init_stack_depth as usize, false); self.must_assignable_to( ty.clone(), expected_ty.clone(), - unification_stmt.target.get_pos(), + unification_stmt.target.get_span_pos(), None, ); if !ty.is_any() && expected_ty.is_any() { - self.set_type_to_scope(&names[0], ty, unification_stmt.target.get_pos()); + self.set_type_to_scope(&names[0].node, ty, &names[0]); } expected_ty } @@ -82,14 +84,14 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx ast::TypeAliasStmt) -> Self::Result { let (start, end) = type_alias_stmt.type_name.get_span_pos(); let mut ty = self - .parse_ty_with_scope(&type_alias_stmt.ty.node, start.clone()) + .parse_ty_with_scope(Some(&type_alias_stmt.ty), (start.clone(), end.clone())) .as_ref() .clone(); if let TypeKind::Schema(schema_ty) = &mut ty.kind { schema_ty.is_instance = false; } ty.is_type_alias = true; - let ty = Rc::new(ty); + let ty = Arc::new(ty); let ty_str = ty.into_type_annotation_str(); let name = type_alias_stmt.type_name.node.get_name(); let mut mapping = IndexMap::default(); @@ -102,7 +104,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { "type alias '{}' cannot be the same as the built-in types ({:?})", name, RESERVED_TYPE_IDENTIFIERS ), - start.clone(), + type_alias_stmt.type_name.get_span_pos(), ); } self.insert_object( @@ -113,10 +115,13 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { end, ty: ty.clone(), kind: ScopeObjectKind::TypeAlias, - used: false, doc: None, }, ); + self.node_ty_map.insert( + self.get_node_key(type_alias_stmt.type_name.id.clone()), + ty.clone(), + ); ty } @@ -132,41 +137,55 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if target.node.names.is_empty() { continue; } - let name = &target.node.names[0]; + let name = &target.node.names[0].node; // Add global names. if (is_private_field(name) || is_config || !self.contains_global_name(name)) && self.scope_level == 0 { - self.insert_global_name(name, &target.get_pos()); + self.insert_global_name(name, &target.get_span_pos()); } if target.node.names.len() == 1 { self.ctx.l_value = true; let expected_ty = self.walk_identifier_expr(target); self.ctx.l_value = false; - if let TypeKind::Schema(ty) = &expected_ty.kind { - let obj = self.new_config_expr_context_item( - &ty.name, - expected_ty.clone(), - start.clone(), - end.clone(), - ); - let init_stack_depth = self.switch_config_expr_context(Some(obj)); - value_ty = self.expr(&assign_stmt.value); - self.clear_config_expr_context(init_stack_depth as usize, false) - } else { - value_ty = self.expr(&assign_stmt.value); + match &expected_ty.kind { + TypeKind::Schema(ty) => { + let obj = self.new_config_expr_context_item( + &ty.name, + expected_ty.clone(), + start.clone(), + end.clone(), + ); + let init_stack_depth = self.switch_config_expr_context(Some(obj)); + value_ty = self.expr(&assign_stmt.value); + self.clear_config_expr_context(init_stack_depth as usize, false) + } + TypeKind::List(_) | TypeKind::Dict(_) | TypeKind::Union(_) => { + let obj = self.new_config_expr_context_item( + "[]", + expected_ty.clone(), + start.clone(), + end.clone(), + ); + let init_stack_depth = self.switch_config_expr_context(Some(obj)); + value_ty = self.expr(&assign_stmt.value); + self.check_assignment_type_annotation(assign_stmt, value_ty.clone()); + self.clear_config_expr_context(init_stack_depth as usize, false) + } + _ => { + value_ty = self.expr(&assign_stmt.value); + // Check type annotation if exists. + self.check_assignment_type_annotation(assign_stmt, value_ty.clone()); + } } self.must_assignable_to( value_ty.clone(), expected_ty.clone(), - target.get_pos(), + target.get_span_pos(), None, ); - if !value_ty.is_any() - && expected_ty.is_any() - && assign_stmt.type_annotation.is_none() - { - self.set_type_to_scope(name, value_ty.clone(), target.get_pos()); + if !value_ty.is_any() && expected_ty.is_any() && assign_stmt.ty.is_none() { + self.set_type_to_scope(name, value_ty.clone(), &target.node.names[0]); if let Some(schema_ty) = &self.ctx.schema { let mut schema_ty = schema_ty.borrow_mut(); schema_ty.set_type_of_attr( @@ -176,12 +195,14 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { } } } else { - self.lookup_type_from_scope(name, target.get_pos()); + self.lookup_type_from_scope(name, target.get_span_pos()); self.ctx.l_value = true; let expected_ty = self.walk_identifier_expr(target); self.ctx.l_value = false; value_ty = self.expr(&assign_stmt.value); - self.must_assignable_to(value_ty.clone(), expected_ty, target.get_pos(), None) + // Check type annotation if exists. + self.check_assignment_type_annotation(assign_stmt, value_ty.clone()); + self.must_assignable_to(value_ty.clone(), expected_ty, target.get_span_pos(), None) } } value_ty @@ -191,28 +212,30 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { self.ctx.l_value = false; if !aug_assign_stmt.target.node.names.is_empty() { let is_config = matches!(aug_assign_stmt.value.node, ast::Expr::Schema(_)); - let name = &aug_assign_stmt.target.node.names[0]; + let name = &aug_assign_stmt.target.node.names[0].node; // Add global names. if is_private_field(name) || is_config || !self.contains_global_name(name) { if self.scope_level == 0 { - self.insert_global_name(name, &aug_assign_stmt.target.get_pos()); + self.insert_global_name(name, &aug_assign_stmt.target.get_span_pos()); } } else { let mut msgs = vec![Message { - pos: aug_assign_stmt.target.get_pos(), + range: aug_assign_stmt.target.get_span_pos(), style: Style::LineAndColumn, message: format!("Immutable variable '{}' is modified during compiling", name), note: None, + suggested_replacement: None, }]; if let Some(pos) = self.get_global_name_pos(name) { msgs.push(Message { - pos: pos.clone(), + range: pos.clone(), style: Style::LineAndColumn, message: format!("The variable '{}' is declared here firstly", name), note: Some(format!( "change the variable name to '_{}' to make it mutable", name )), + suggested_replacement: None, }) } self.handler.add_error(ErrorKind::ImmutableError, &msgs); @@ -224,13 +247,18 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { Ok(op) => op, Err(msg) => bug!("{}", msg), }; - let new_target_ty = self.binary(left_ty, right_ty, &op, aug_assign_stmt.target.get_pos()); + let new_target_ty = self.binary( + left_ty, + right_ty, + &op, + aug_assign_stmt.target.get_span_pos(), + ); self.ctx.l_value = true; let expected_ty = self.walk_identifier_expr(&aug_assign_stmt.target); self.must_assignable_to( new_target_ty.clone(), expected_ty, - aug_assign_stmt.target.get_pos(), + aug_assign_stmt.target.get_span_pos(), None, ); self.ctx.l_value = false; @@ -268,69 +296,64 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_quant_expr(&mut self, quant_expr: &'ctx ast::QuantExpr) -> Self::Result { let iter_ty = self.expr(&quant_expr.target); - if iter_ty.is_any() { - iter_ty - } else { - let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); - self.enter_scope(start, end, ScopeKind::Loop); - let (mut key_name, mut val_name) = (None, None); - let mut target_node = None; - for (i, target) in quant_expr.variables.iter().enumerate() { - if target.node.names.is_empty() { - continue; - } - if target.node.names.len() > 1 { - self.handler.add_compile_error( - "loop variables can only be ordinary identifiers", - target.get_pos(), - ); - } - target_node = Some(target); - let name = &target.node.names[0]; - if i == 0 { - key_name = Some(name.to_string()); - } else if i == 1 { - val_name = Some(name.to_string()) - } else { - self.handler.add_compile_error( - &format!( - "the number of loop variables is {}, which can only be 1 or 2", - quant_expr.variables.len() - ), - target.get_pos(), - ); - break; - } - self.ctx.local_vars.push(name.to_string()); - let (start, end) = target.get_span_pos(); - self.insert_object( - name, - ScopeObject { - name: name.to_string(), - start, - end, - ty: self.any_ty(), - kind: ScopeObjectKind::Variable, - used: false, - doc: None, - }, + let (start, mut end) = quant_expr.test.get_span_pos(); + if let Some(if_cond) = &quant_expr.if_cond { + end = if_cond.get_end_pos(); + } + self.enter_scope(start, end, ScopeKind::Loop); + let (mut key_name, mut val_name) = (None, None); + for (i, target) in quant_expr.variables.iter().enumerate() { + if target.node.names.is_empty() { + continue; + } + if target.node.names.len() > 1 { + self.handler.add_compile_error( + "loop variables can only be ordinary identifiers", + target.get_span_pos(), ); } - self.do_loop_type_check( - target_node.unwrap(), - key_name, - val_name, - iter_ty.clone(), - quant_expr.target.get_pos(), - ); - self.expr_or_any_type(&quant_expr.if_cond); - let item_ty = self.expr(&quant_expr.test); - self.leave_scope(); - match &quant_expr.op { - ast::QuantOperation::All | ast::QuantOperation::Any => self.bool_ty(), - ast::QuantOperation::Filter => iter_ty, - ast::QuantOperation::Map => Rc::new(Type::list(item_ty)), + let name = &target.node.names[0]; + if i == 0 { + key_name = Some(name); + } else if i == 1 { + val_name = Some(name) + } else { + self.handler.add_compile_error( + &format!( + "the number of loop variables is {}, which can only be 1 or 2", + quant_expr.variables.len() + ), + target.get_span_pos(), + ); + break; } + self.ctx.local_vars.push(name.node.to_string()); + let (start, end) = target.get_span_pos(); + self.insert_object( + &name.node, + ScopeObject { + name: name.node.to_string(), + start, + end, + ty: self.any_ty(), + kind: ScopeObjectKind::Variable, + doc: None, + }, + ); + } + self.do_loop_type_check( + key_name, + val_name, + iter_ty.clone(), + quant_expr.target.get_span_pos(), + ); + self.expr_or_any_type(&quant_expr.if_cond); + let item_ty = self.expr(&quant_expr.test); + self.leave_scope(); + match &quant_expr.op { + ast::QuantOperation::All | ast::QuantOperation::Any => self.bool_ty(), + ast::QuantOperation::Filter => iter_ty, + ast::QuantOperation::Map => Arc::new(Type::list(item_ty)), } } @@ -338,8 +361,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { self.ctx.local_vars.clear(); let (start, end) = schema_attr.name.get_span_pos(); let name = if schema_attr.name.node.contains('.') { - self.handler - .add_compile_error("schema attribute can not be selected", start.clone()); + self.handler.add_compile_error( + "schema attribute can not be selected", + schema_attr.name.get_span_pos(), + ); schema_attr.name.node.split('.').collect::>()[0] } else { &schema_attr.name.node @@ -350,6 +375,11 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { .get_type_of_attr(name) .map_or(self.any_ty(), |ty| ty); + self.node_ty_map.insert( + self.get_node_key(schema_attr.name.id.clone()), + expected_ty.clone(), + ); + let doc_str = schema .borrow() .attrs @@ -357,8 +387,6 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { .map(|attr| attr.doc.clone()) .flatten(); - // Schema attribute decorators - self.resolve_decorators(&schema_attr.decorators, DecoratorTarget::Attribute, name); self.insert_object( name, ScopeObject { @@ -367,7 +395,6 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { end, ty: expected_ty.clone(), kind: ScopeObjectKind::Attribute, - used: false, doc: doc_str, }, ); @@ -383,17 +410,31 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { } else { self.expr(value) }; - let pos = schema_attr.name.get_pos(); match &schema_attr.op { Some(bin_or_aug) => match bin_or_aug { // Union - ast::BinOrAugOp::Aug(ast::AugOp::BitOr) => { + ast::AugOp::BitOr => { let op = ast::BinOp::BitOr; - let value_ty = self.binary(value_ty, expected_ty.clone(), &op, pos.clone()); - self.must_assignable_to(value_ty, expected_ty, pos, None); + let value_ty = self.binary( + value_ty, + expected_ty.clone(), + &op, + schema_attr.name.get_span_pos(), + ); + self.must_assignable_to( + value_ty, + expected_ty, + schema_attr.name.get_span_pos(), + None, + ); } // Assign - _ => self.must_assignable_to(value_ty, expected_ty, pos, None), + _ => self.must_assignable_to( + value_ty, + expected_ty, + schema_attr.name.get_span_pos(), + None, + ), }, None => bug!("invalid ast schema attr op kind"), } @@ -411,47 +452,58 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_unary_expr(&mut self, unary_expr: &'ctx ast::UnaryExpr) -> Self::Result { let operand_ty = self.expr(&unary_expr.operand); - self.unary(operand_ty, &unary_expr.op, unary_expr.operand.get_pos()) + self.unary( + operand_ty, + &unary_expr.op, + unary_expr.operand.get_span_pos(), + ) } fn walk_binary_expr(&mut self, binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { let left_ty = self.expr(&binary_expr.left); let mut right_ty = self.expr(&binary_expr.right); - let pos = binary_expr.left.get_pos(); match &binary_expr.op { - ast::BinOrCmpOp::Bin(bin_op) => match bin_op { - ast::BinOp::As => { - if let ast::Expr::Identifier(identifier) = &binary_expr.right.node { - right_ty = self.parse_ty_str_with_scope( - &identifier.get_name(), - binary_expr.right.get_pos(), - ); - if right_ty.is_schema() { - let mut schema_ty = right_ty.into_schema_type(); - schema_ty.is_instance = true; - right_ty = Rc::new(Type::schema(schema_ty)); - } - let ty_annotation_str = right_ty.into_type_annotation_str(); - self.add_type_alias( - &identifier.get_name(), - &ty_str_replace_pkgpath(&ty_annotation_str, &self.ctx.pkgpath), - ); - } else { - self.handler - .add_compile_error("keyword 'as' right operand must be a type", pos); - return left_ty; + ast::BinOp::As => { + if let ast::Expr::Identifier(identifier) = &binary_expr.right.node { + right_ty = self.parse_ty_str_with_scope( + &identifier.get_name(), + binary_expr.right.get_span_pos(), + ); + if right_ty.is_schema() { + let mut schema_ty = right_ty.into_schema_type(); + schema_ty.is_instance = true; + right_ty = Arc::new(Type::schema(schema_ty)); } - self.binary(left_ty, right_ty, bin_op, pos) + let ty_annotation_str = right_ty.into_type_annotation_str(); + self.add_type_alias( + &identifier.get_name(), + &ty_str_replace_pkgpath(&ty_annotation_str, &self.ctx.pkgpath), + ); + } else { + self.handler.add_compile_error( + "keyword 'as' right operand must be a type", + binary_expr.left.get_span_pos(), + ); + return left_ty; } - _ => self.binary(left_ty, right_ty, bin_op, pos), - }, - ast::BinOrCmpOp::Cmp(cmp_op) => self.compare(left_ty, right_ty, cmp_op, pos), + self.binary( + left_ty, + right_ty, + &binary_expr.op, + binary_expr.left.get_span_pos(), + ) + } + _ => self.binary( + left_ty, + right_ty, + &binary_expr.op, + binary_expr.left.get_span_pos(), + ), } } fn walk_selector_expr(&mut self, selector_expr: &'ctx ast::SelectorExpr) -> Self::Result { let mut value_ty = self.expr(&selector_expr.value); - let pos = selector_expr.attr.get_pos(); if value_ty.is_module() && selector_expr.has_question { let attr = selector_expr.attr.node.get_name(); self.handler.add_compile_error( @@ -460,56 +512,77 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { attr, attr ), - selector_expr.value.get_pos(), + selector_expr.value.get_span_pos(), ); } for name in &selector_expr.attr.node.names { - value_ty = self.load_attr(value_ty.clone(), name, pos.clone()); + value_ty = self.load_attr( + value_ty.clone(), + &name.node, + selector_expr.attr.get_span_pos(), + ); + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), value_ty.clone()); } + + if let TypeKind::Function(func) = &value_ty.kind { + self.insert_object( + &selector_expr.attr.node.get_name(), + ScopeObject { + name: selector_expr.attr.node.get_name(), + start: selector_expr.attr.get_pos(), + end: selector_expr.attr.get_end_pos(), + ty: value_ty.clone(), + kind: ScopeObjectKind::FunctionCall, + doc: Some(func.doc.clone()), + }, + ) + } + value_ty } fn walk_call_expr(&mut self, call_expr: &'ctx ast::CallExpr) -> Self::Result { let call_ty = self.expr(&call_expr.func); - let pos = call_expr.func.get_pos(); + let range = call_expr.func.get_span_pos(); if call_ty.is_any() { self.do_arguments_type_check( - &call_expr.func.node, + &call_expr.func, &call_expr.args, &call_expr.keywords, - &[], + &FunctionType::variadic_func(), ); self.any_ty() } else if let TypeKind::Function(func_ty) = &call_ty.kind { self.do_arguments_type_check( - &call_expr.func.node, + &call_expr.func, &call_expr.args, &call_expr.keywords, - &func_ty.params, + &func_ty, ); func_ty.return_ty.clone() } else if let TypeKind::Schema(schema_ty) = &call_ty.kind { if schema_ty.is_instance { self.handler.add_compile_error( &format!("schema '{}' instance is not callable", call_ty.ty_str()), - pos, + range, ); self.any_ty() } else { self.do_arguments_type_check( - &call_expr.func.node, + &call_expr.func, &call_expr.args, &call_expr.keywords, - &schema_ty.func.params, + &schema_ty.func, ); let mut return_ty = schema_ty.clone(); return_ty.is_instance = true; - Rc::new(Type::schema(return_ty)) + Arc::new(Type::schema(return_ty)) } } else { self.handler.add_compile_error( &format!("'{}' object is not callable", call_ty.ty_str()), - pos, + range, ); self.any_ty() } @@ -517,7 +590,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_subscript(&mut self, subscript: &'ctx ast::Subscript) -> Self::Result { let value_ty = self.expr(&subscript.value); - let pos = subscript.value.get_pos(); + let range = subscript.value.get_span_pos(); if value_ty.is_any() { value_ty } else { @@ -545,7 +618,9 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { } } } - TypeKind::Dict(_, val_ty) => { + TypeKind::Dict(DictType { + key_ty: _, val_ty, .. + }) => { if let Some(index) = &subscript.index { let index_key_ty = self.expr(index); if index_key_ty.is_none_or_any() { @@ -556,17 +631,17 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { "invalid dict/schema key type: '{}'", index_key_ty.ty_str() ), - pos, + range, ); self.any_ty() - } else if let ast::Expr::StringLit(string_lit) = &subscript.value.node { - self.load_attr(value_ty, &string_lit.value, pos) + } else if let TypeKind::StrLit(lit_value) = &index_key_ty.kind { + self.load_attr(value_ty, lit_value, range) } else { val_ty.clone() } } else { self.handler - .add_compile_error("unhashable type: 'slice'", pos); + .add_compile_error("unhashable type: 'slice'", range); self.any_ty() } } @@ -581,24 +656,24 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { "invalid dict/schema key type: '{}'", index_key_ty.ty_str() ), - pos, + range, ); self.any_ty() - } else if let ast::Expr::StringLit(string_lit) = &subscript.value.node { - self.load_attr(value_ty, &string_lit.value, pos) + } else if let TypeKind::StrLit(lit_value) = &index_key_ty.kind { + self.load_attr(value_ty, lit_value, range) } else { schema_ty.val_ty() } } else { self.handler - .add_compile_error("unhashable type: 'slice'", pos); + .add_compile_error("unhashable type: 'slice'", range); self.any_ty() } } _ => { self.handler.add_compile_error( &format!("'{}' object is not subscriptable", value_ty.ty_str()), - subscript.value.get_pos(), + subscript.value.get_span_pos(), ); self.any_ty() } @@ -611,12 +686,15 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { } fn walk_list_expr(&mut self, list_expr: &'ctx ast::ListExpr) -> Self::Result { + let stack_depth = self.switch_list_expr_context(); let item_type = sup(&self.exprs(&list_expr.elts).to_vec()); + self.clear_config_expr_context(stack_depth, false); Type::list_ref(item_type) } fn walk_list_comp(&mut self, list_comp: &'ctx ast::ListComp) -> Self::Result { let start = list_comp.elt.get_pos(); + let stack_depth = self.switch_list_expr_context(); let end = match list_comp.generators.last() { Some(last) => last.get_end_pos(), None => list_comp.elt.get_end_pos(), @@ -626,11 +704,14 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { self.walk_comp_clause(&comp_clause.node); } if let ast::Expr::Starred(_) = list_comp.elt.node { - self.handler - .add_compile_error("list unpacking cannot be used in list comprehension", start); + self.handler.add_compile_error( + "list unpacking cannot be used in list comprehension", + list_comp.elt.get_span_pos(), + ); } let item_ty = self.expr(&list_comp.elt); self.leave_scope(); + self.clear_config_expr_context(stack_depth, false); Type::list_ref(item_ty) } @@ -647,8 +728,10 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { } let key_ty = self.expr(key); // TODO: Naming both dict keys and schema attributes as `attribute` - self.check_attr_ty(&key_ty, start); + self.check_attr_ty(&key_ty, key.get_span_pos()); + let stack_depth = self.switch_config_expr_context_by_key(&dict_comp.entry.key); let val_ty = self.expr(&dict_comp.entry.value); + self.clear_config_expr_context(stack_depth, false); self.leave_scope(); Type::dict_ref(key_ty, val_ty) } @@ -673,7 +756,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { match &ty.kind { TypeKind::None | TypeKind::Any => (ty.clone(), true), TypeKind::List(item_ty) => (item_ty.clone(), true), - TypeKind::Dict(key_ty, _) => (key_ty.clone(), true), + TypeKind::Dict(DictType { key_ty, .. }) => (key_ty.clone(), true), TypeKind::Schema(schema_ty) => (schema_ty.key_ty(), true), TypeKind::Union(types) => { let results = types @@ -689,7 +772,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { results.iter().all(|(_, r)| *r), ) } - _ => (Rc::new(Type::ANY), false), + _ => (Arc::new(Type::ANY), false), } } let (ty, result) = starred_ty_walk_fn(&value_ty); @@ -699,7 +782,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { "only list, dict, schema object can be used * unpacked, got {}", ty.ty_str() ), - starred_expr.value.get_pos(), + starred_expr.value.get_span_pos(), ); } ty @@ -722,7 +805,6 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_comp_clause(&mut self, comp_clause: &'ctx ast::CompClause) -> Self::Result { let iter_ty = self.expr(&comp_clause.iter); let (mut key_name, mut val_name) = (None, None); - let mut target_node = None; for (i, target) in comp_clause.targets.iter().enumerate() { if target.node.names.is_empty() { continue; @@ -730,36 +812,34 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if target.node.names.len() > 1 { self.handler.add_compile_error( "loop variables can only be ordinary identifiers", - target.get_pos(), + target.get_span_pos(), ); } - target_node = Some(target); let name = &target.node.names[0]; if i == 0 { - key_name = Some(name.to_string()); + key_name = Some(name); } else if i == 1 { - val_name = Some(name.to_string()) + val_name = Some(name); } else { self.handler.add_compile_error( &format!( "the number of loop variables is {}, which can only be 1 or 2", comp_clause.targets.len() ), - target.get_pos(), + target.get_span_pos(), ); break; } - self.ctx.local_vars.push(name.to_string()); + self.ctx.local_vars.push(name.node.to_string()); let (start, end) = target.get_span_pos(); self.insert_object( - name, + &name.node, ScopeObject { - name: name.to_string(), + name: name.node.to_string(), start, end, ty: self.any_ty(), kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); @@ -767,13 +847,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if iter_ty.is_any() { iter_ty } else { - self.do_loop_type_check( - target_node.unwrap(), - key_name, - val_name, - iter_ty, - comp_clause.iter.get_pos(), - ); + self.do_loop_type_check(key_name, val_name, iter_ty, comp_clause.iter.get_span_pos()); self.exprs(&comp_clause.ifs); self.any_ty() } @@ -784,12 +858,12 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if !matches!(&schema_expr.config.node, ast::Expr::Config(_)) { self.handler.add_compile_error( "Invalid schema config expr, expect config entries, e.g., {k1 = v1, k2 = v2}", - schema_expr.config.get_pos(), + schema_expr.config.get_span_pos(), ); } - let mut pos = schema_expr.name.get_pos(); + let mut range = schema_expr.name.get_span_pos(); let ret_ty = match &def_ty.kind { - TypeKind::Dict(_, _) => { + TypeKind::Dict(DictType { .. }) => { let obj = self.new_config_expr_context_item( "", def_ty.clone(), @@ -799,7 +873,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { let init_stack_depth = self.switch_config_expr_context(Some(obj)); let config_ty = self.expr(&schema_expr.config); self.clear_config_expr_context(init_stack_depth as usize, false); - self.binary(def_ty.clone(), config_ty, &ast::BinOp::BitOr, pos) + self.binary(def_ty.clone(), config_ty, &ast::BinOp::BitOr, range) } TypeKind::Schema(schema_ty) => { if !schema_ty.is_instance { @@ -818,30 +892,39 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { ); let init_stack_depth = self.switch_config_expr_context(Some(obj)); self.expr(&schema_expr.config); + self.node_ty_map.insert( + self.get_node_key(schema_expr.config.id.clone()), + def_ty.clone(), + ); self.clear_config_expr_context(init_stack_depth as usize, false); if schema_ty.is_instance { if !schema_expr.args.is_empty() || !schema_expr.kwargs.is_empty() { self.handler.add_compile_error( "Arguments cannot be used in the schema modification expression", - pos, + range, ); } } else { - let func = ast::Expr::Identifier(schema_expr.name.node.clone()); - + let func = Box::new(ast::Node::node_with_pos( + ast::Expr::Identifier(schema_expr.name.node.clone()), + schema_expr.name.pos(), + )); self.do_arguments_type_check( &func, &schema_expr.args, &schema_expr.kwargs, - &schema_ty.func.params, + &schema_ty.func, ); } self.any_ty() } _ => { - pos.filename = self.ctx.filename.clone(); - self.handler - .add_compile_error(&format!("Invalid schema type '{}'", def_ty.ty_str()), pos); + range.0.filename = self.ctx.filename.clone(); + range.1.filename = self.ctx.filename.clone(); + self.handler.add_compile_error( + &format!("Invalid schema type '{}'", def_ty.ty_str()), + range, + ); return self.any_ty(); } }; @@ -850,7 +933,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { schema_ty.is_instance = true; } if def_ty_clone.is_schema() { - Rc::new(def_ty_clone) + Arc::new(def_ty_clone) } else { ret_ty } @@ -876,20 +959,40 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if let Some(args) = &lambda_expr.args { for (i, arg) in args.node.args.iter().enumerate() { let name = arg.node.get_name(); - let arg_ty = args.node.get_arg_type(i); - let ty = self.parse_ty_with_scope(&arg_ty, arg.get_pos()); + let arg_ty = args.node.get_arg_type_node(i); + let range = match arg_ty { + Some(arg_type_node) => arg_type_node.get_span_pos(), + None => arg.get_span_pos(), + }; + let ty = self.parse_ty_with_scope(arg_ty, range); + + // If the arguments type of a lambda is a schema type, + // It should be marked as an schema instance type. + let ty = if let TypeKind::Schema(sty) = &ty.kind { + let mut arg_ty = sty.clone(); + arg_ty.is_instance = true; + Arc::new(Type::schema(arg_ty)) + } else { + ty.clone() + }; + if let Some(name) = arg.node.names.last() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), ty.clone()); + } + + let value = &args.node.defaults[i]; params.push(Parameter { name, ty: ty.clone(), - has_default: false, + has_default: value.is_some(), }); - let value = &args.node.defaults[i]; self.expr_or_any_type(value); } } let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); if let Some(ret_annotation_ty) = &lambda_expr.return_ty { - ret_ty = self.parse_ty_with_scope(&ret_annotation_ty.node, start.clone()); + ret_ty = + self.parse_ty_with_scope(Some(&ret_annotation_ty), (start.clone(), end.clone())); } self.enter_scope(start.clone(), end.clone(), ScopeKind::Lambda); self.ctx.in_lambda_expr.push(true); @@ -903,7 +1006,6 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { end: end.clone(), ty: param.ty.clone(), kind: ScopeObjectKind::Parameter, - used: false, doc: None, }, ) @@ -911,22 +1013,25 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if let Some(stmt) = lambda_expr.body.last() { if !matches!( stmt.node, - ast::Stmt::Expr(_) | ast::Stmt::Assign(_) | ast::Stmt::AugAssign(_) + ast::Stmt::Expr(_) + | ast::Stmt::Assign(_) + | ast::Stmt::AugAssign(_) + | ast::Stmt::Assert(_) ) { self.handler.add_compile_error( "The last statement of the lambda body must be a expression e.g., x, 1, etc.", - stmt.get_pos(), + stmt.get_span_pos(), ); } } let real_ret_ty = self.stmts(&lambda_expr.body); self.leave_scope(); self.ctx.in_lambda_expr.pop(); - self.must_assignable_to(real_ret_ty.clone(), ret_ty.clone(), end, None); - if !real_ret_ty.is_any() && ret_ty.is_any() && lambda_expr.return_type_str.is_none() { + self.must_assignable_to(real_ret_ty.clone(), ret_ty.clone(), (start, end), None); + if !real_ret_ty.is_any() && ret_ty.is_any() && lambda_expr.return_ty.is_none() { ret_ty = real_ret_ty; } - Rc::new(Type::function(None, ret_ty, ¶ms, "", false, None)) + Arc::new(Type::function(None, ret_ty, ¶ms, "", false, None)) } fn walk_keyword(&mut self, keyword: &'ctx ast::Keyword) -> Self::Result { @@ -936,8 +1041,12 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { fn walk_arguments(&mut self, arguments: &'ctx ast::Arguments) -> Self::Result { for (i, arg) in arguments.args.iter().enumerate() { - let ty = arguments.get_arg_type(i); - self.parse_ty_with_scope(&ty, arg.get_pos()); + let ty = arguments.get_arg_type_node(i); + let ty = self.parse_ty_with_scope(ty, arg.get_span_pos()); + if let Some(name) = arg.node.names.last() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), ty.clone()); + } let value = &arguments.defaults[i]; self.expr_or_any_type(value); } @@ -951,21 +1060,32 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { t1.clone(), t2.clone(), &compare.ops[0], - compare.comparators[0].get_pos(), + compare.comparators[0].get_span_pos(), ); for i in 1..compare.comparators.len() - 1 { let op = &compare.ops[i + 1]; - self.compare(t1.clone(), t2.clone(), op, compare.comparators[i].get_pos()); + let t2 = self.expr(&compare.comparators[i]); + self.compare( + t1.clone(), + t2.clone(), + op, + compare.comparators[i].get_span_pos(), + ); } self.bool_ty() } fn walk_identifier(&mut self, identifier: &'ctx ast::Identifier) -> Self::Result { - self.resolve_var( - &identifier.names, + let tys = self.resolve_var( + &identifier.get_names(), &identifier.pkgpath, - self.ctx.start_pos.clone(), - ) + (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()), + ); + for (index, name) in identifier.names.iter().enumerate() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), tys[index].clone()); + } + tys.last().unwrap().clone() } fn walk_number_lit(&mut self, number_lit: &'ctx ast::NumberLit) -> Self::Result { @@ -976,28 +1096,28 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { ast::NumberLitValue::Float(float_val) => { self.handler.add_compile_error( "float literal can not be followed the unit suffix", - self.ctx.start_pos.clone(), + (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()), ); float_val as i64 } }; let binary_suffix_str: String = binary_suffix.value(); let value = kclvm_runtime::units::cal_num(raw_value, &binary_suffix_str); - Rc::new(Type::number_multiplier( + Arc::new(Type::number_multiplier( value, raw_value, &binary_suffix_str, )) } None => match number_lit.value { - ast::NumberLitValue::Int(int_val) => Rc::new(Type::int_lit(int_val)), - ast::NumberLitValue::Float(float_val) => Rc::new(Type::float_lit(float_val)), + ast::NumberLitValue::Int(int_val) => Arc::new(Type::int_lit(int_val)), + ast::NumberLitValue::Float(float_val) => Arc::new(Type::float_lit(float_val)), }, } } fn walk_string_lit(&mut self, string_lit: &'ctx ast::StringLit) -> Self::Result { - Rc::new(Type::str_lit(&string_lit.value)) + Arc::new(Type::str_lit(&string_lit.value)) } fn walk_name_constant_lit( @@ -1005,8 +1125,8 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { name_constant_lit: &'ctx ast::NameConstantLit, ) -> Self::Result { match &name_constant_lit.value { - ast::NameConstant::True => Rc::new(Type::bool_lit(true)), - ast::NameConstant::False => Rc::new(Type::bool_lit(false)), + ast::NameConstant::True => Arc::new(Type::bool_lit(true)), + ast::NameConstant::False => Arc::new(Type::bool_lit(false)), ast::NameConstant::None | ast::NameConstant::Undefined => self.none_ty(), } } @@ -1023,7 +1143,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Resolver<'ctx> { if !VALID_FORMAT_SPEC_SET.contains(&spec_lower.as_str()) { self.handler.add_compile_error( &format!("{} is a invalid format spec", spec), - formatted_value.value.get_pos(), + formatted_value.value.get_span_pos(), ); } } @@ -1063,7 +1183,10 @@ impl<'ctx> Resolver<'ctx> { self.ctx.start_pos = start; self.ctx.end_pos = end; } - self.walk_expr(&expr.node) + let ty = self.walk_expr(&expr.node); + self.node_ty_map + .insert(self.get_node_key(expr.id.clone()), ty.clone()); + ty } #[inline] @@ -1071,7 +1194,10 @@ impl<'ctx> Resolver<'ctx> { let (start, end) = stmt.get_span_pos(); self.ctx.start_pos = start; self.ctx.end_pos = end; - self.walk_stmt(&stmt.node) + let ty = self.walk_stmt(&stmt.node); + self.node_ty_map + .insert(self.get_node_key(stmt.id.clone()), ty.clone()); + ty } #[inline] @@ -1080,7 +1206,12 @@ impl<'ctx> Resolver<'ctx> { expr: &'ctx Option>, ) -> ResolvedResult { match expr { - Some(expr) => self.walk_expr(&expr.node), + Some(expr) => { + let ty = self.walk_expr(&expr.node); + self.node_ty_map + .insert(self.get_node_key(expr.id.clone()), ty.clone()); + ty + } None => self.any_ty(), } } @@ -1090,10 +1221,19 @@ impl<'ctx> Resolver<'ctx> { &mut self, identifier: &'ctx ast::NodeRef, ) -> ResolvedResult { - self.resolve_var( - &identifier.node.names, + let tys = self.resolve_var( + &identifier.node.get_names(), &identifier.node.pkgpath, - identifier.get_pos(), - ) + identifier.get_span_pos(), + ); + for (index, name) in identifier.node.names.iter().enumerate() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), tys[index].clone()); + } + let ident_ty = tys.last().unwrap().clone(); + self.node_ty_map + .insert(self.get_node_key(identifier.id.clone()), ident_ty.clone()); + + ident_ty } } diff --git a/kclvm/sema/src/resolver/para.rs b/kclvm/sema/src/resolver/para.rs index 3635ce3f6..61c79d055 100644 --- a/kclvm/sema/src/resolver/para.rs +++ b/kclvm/sema/src/resolver/para.rs @@ -17,11 +17,12 @@ impl<'ctx> Resolver<'ctx> { self.handler.add_error( ErrorKind::IllegalParameterError, &[Message { - pos: default.get_pos(), + range: default.get_span_pos(), style: Style::LineAndColumn, message: "non-default argument follows default argument" .to_string(), note: Some("A default argument".to_string()), + suggested_replacement: None, }], ); } diff --git a/kclvm/sema/src/resolver/schema.rs b/kclvm/sema/src/resolver/schema.rs index 26748162b..043716bcb 100644 --- a/kclvm/sema/src/resolver/schema.rs +++ b/kclvm/sema/src/resolver/schema.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::collections::HashMap; use std::rc::Rc; use crate::builtin::BUILTIN_DECORATORS; @@ -7,6 +8,7 @@ use crate::ty::{Decorator, DecoratorTarget, TypeKind}; use kclvm_ast::ast; use kclvm_ast::pos::GetPos; use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_ast_pretty::{print_ast_node, ASTNode}; use kclvm_error::{ErrorKind, Message, Position, Style}; use super::node::ResolvedResult; @@ -17,24 +19,38 @@ impl<'ctx> Resolver<'ctx> { &mut self, schema_stmt: &'ctx ast::SchemaStmt, ) -> ResolvedResult { - self.resolve_unique_key(&schema_stmt.name.node, &schema_stmt.name.get_pos()); - let ty = self.lookup_type_from_scope(&schema_stmt.name.node, schema_stmt.name.get_pos()); + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + self.resolve_unique_key(&schema_stmt.name.node, &schema_stmt.name.get_span_pos()); + let ty = + self.lookup_type_from_scope(&schema_stmt.name.node, schema_stmt.name.get_span_pos()); + self.node_ty_map + .insert(self.get_node_key(schema_stmt.name.id.clone()), ty.clone()); let scope_ty = if ty.is_schema() { ty.into_schema_type() } else { self.handler.add_error( ErrorKind::TypeError, &[Message { - pos: schema_stmt.get_pos(), + range: schema_stmt.get_span_pos(), style: Style::LineAndColumn, message: format!("expected schema type, got {}", ty.ty_str()), note: None, + suggested_replacement: None, }], ); return ty; }; self.ctx.schema = Some(Rc::new(RefCell::new(scope_ty.clone()))); - let (start, end) = schema_stmt.get_span_pos(); + if let Some(args) = &schema_stmt.args { + for (i, arg) in args.node.args.iter().enumerate() { + let ty = args.node.get_arg_type_node(i); + let ty = self.parse_ty_with_scope(ty, arg.get_span_pos()); + if let Some(name) = arg.node.names.last() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), ty.clone()); + } + } + } self.do_parameters_check(&schema_stmt.args); self.enter_scope( start.clone(), @@ -50,7 +66,6 @@ impl<'ctx> Resolver<'ctx> { end: end.clone(), ty: param.ty.clone(), kind: ScopeObjectKind::Parameter, - used: false, doc: None, }, ) @@ -59,6 +74,7 @@ impl<'ctx> Resolver<'ctx> { if let (Some(index_signature), Some(index_signature_node)) = (scope_ty.index_signature, &schema_stmt.index_signature) { + // Insert the schema index signature key name into the scope. if let Some(key_name) = index_signature.key_name { let (start, end) = index_signature_node.get_span_pos(); self.insert_object( @@ -69,11 +85,21 @@ impl<'ctx> Resolver<'ctx> { end, ty: index_signature.key_ty.clone(), kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ) } + // Check index signature default value type. + if let Some(value) = &index_signature_node.node.value { + let expected_ty = index_signature.val_ty; + let value_ty = self.expr(value); + self.must_assignable_to( + value_ty, + expected_ty, + index_signature_node.get_span_pos(), + None, + ); + } } let schema_attr_names = schema_stmt.get_left_identifier_list(); for (line, column, name) in schema_attr_names { @@ -90,7 +116,6 @@ impl<'ctx> Resolver<'ctx> { end: Position::dummy_pos(), ty: self.any_ty(), kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); @@ -108,18 +133,21 @@ impl<'ctx> Resolver<'ctx> { } pub(crate) fn resolve_rule_stmt(&mut self, rule_stmt: &'ctx ast::RuleStmt) -> ResolvedResult { - self.resolve_unique_key(&rule_stmt.name.node, &rule_stmt.name.get_pos()); - let ty = self.lookup_type_from_scope(&rule_stmt.name.node, rule_stmt.name.get_pos()); + self.resolve_unique_key(&rule_stmt.name.node, &rule_stmt.name.get_span_pos()); + let ty = self.lookup_type_from_scope(&rule_stmt.name.node, rule_stmt.name.get_span_pos()); + self.node_ty_map + .insert(self.get_node_key(rule_stmt.name.id.clone()), ty.clone()); let scope_ty = if ty.is_schema() { ty.into_schema_type() } else { self.handler.add_error( ErrorKind::TypeError, &[Message { - pos: rule_stmt.get_pos(), + range: rule_stmt.get_span_pos(), style: Style::LineAndColumn, message: format!("expected rule type, got {}", ty.ty_str()), note: None, + suggested_replacement: None, }], ); return ty; @@ -141,7 +169,6 @@ impl<'ctx> Resolver<'ctx> { end: end.clone(), ty: param.ty.clone(), kind: ScopeObjectKind::Parameter, - used: false, doc: None, }, ) @@ -165,7 +192,7 @@ impl<'ctx> Resolver<'ctx> { for decorator in decorators { let name = if let ast::Expr::Identifier(identifier) = &decorator.node.func.node { if identifier.names.len() == 1 { - Some(identifier.names[0].clone()) + Some(identifier.names[0].node.clone()) } else { None } @@ -177,15 +204,21 @@ impl<'ctx> Resolver<'ctx> { Some(ty) => match &ty.kind { TypeKind::Function(func_ty) => { self.do_arguments_type_check( - &decorator.node.func.node, + &decorator.node.func, + &decorator.node.args, + &decorator.node.keywords, + &func_ty, + ); + let (arguments, keywords) = self.arguments_to_string( &decorator.node.args, &decorator.node.keywords, - &func_ty.params, ); decorator_objs.push(Decorator { target: target.clone(), name, key: key.to_string(), + arguments, + keywords, }) } _ => bug!("invalid builtin decorator function type"), @@ -193,18 +226,47 @@ impl<'ctx> Resolver<'ctx> { None => { self.handler.add_compile_error( &format!("UnKnown decorator {}", name), - decorator.get_pos(), + decorator.get_span_pos(), ); } }, None => { self.handler.add_type_error( "decorator name must be a single identifier", - decorator.get_pos(), + decorator.get_span_pos(), ); } } } decorator_objs } + + fn arguments_to_string( + &mut self, + args: &'ctx [ast::NodeRef], + kwargs: &'ctx [ast::NodeRef], + ) -> (Vec, HashMap) { + if self.options.resolve_val { + ( + args.iter() + .map(|a| print_ast_node(ASTNode::Expr(a))) + .collect(), + kwargs + .iter() + .map(|a| { + ( + a.node.arg.node.get_name(), + a.node + .value + .as_ref() + .map(|v| print_ast_node(ASTNode::Expr(v))) + .unwrap_or_default(), + ) + }) + .collect(), + ) + } else { + (vec![], HashMap::new()) + } + } } diff --git a/kclvm/sema/src/resolver/scope.rs b/kclvm/sema/src/resolver/scope.rs index 045bd082f..73056d374 100644 --- a/kclvm/sema/src/resolver/scope.rs +++ b/kclvm/sema/src/resolver/scope.rs @@ -1,19 +1,30 @@ use anyhow::bail; use compiler_base_session::Session; -use indexmap::IndexMap; +use indexmap::{IndexMap, IndexSet}; +use kclvm_ast::ast::NodeRef; +use kclvm_ast::ast::Stmt; +use kclvm_ast::ast::Stmt::Import; use kclvm_ast::{ast, MAIN_PKG}; +use kclvm_error::diagnostic::Range; use kclvm_error::{Handler, Level}; +use std::collections::HashMap; +use std::collections::HashSet; +use std::collections::VecDeque; use std::sync::Arc; +use std::sync::Mutex; use std::{ cell::RefCell, rc::{Rc, Weak}, }; use crate::resolver::Resolver; -use crate::ty::Type; +use crate::ty::TypeRef; use crate::{builtin::BUILTIN_FUNCTIONS, ty::TypeInferMethods}; +use kclvm_ast::ast::AstIndex; use kclvm_ast::pos::ContainsPos; +use kclvm_ast::pos::GetPos; use kclvm_error::Position; +use serde::Serialize; /// The object stored in the scope. #[derive(PartialEq, Clone, Debug)] @@ -25,11 +36,9 @@ pub struct ScopeObject { /// The scope object end position. pub end: Position, /// The type of the scope object. - pub ty: Rc, + pub ty: TypeRef, /// The scope object kind. pub kind: ScopeObjectKind, - /// Record whether has been used, for check unused imported module and var definition - pub used: bool, /// The doc of the scope object, will be None unless the scope object represents a schema or schema attribute. pub doc: Option, } @@ -48,6 +57,19 @@ impl ContainsPos for ScopeObject { } } +impl GetPos for ScopeObject { + fn get_span_pos(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + fn get_pos(&self) -> Position { + self.start.clone() + } + + fn get_end_pos(&self) -> Position { + self.end.clone() + } +} + #[derive(PartialEq, Clone, Debug)] pub enum ScopeObjectKind { Variable, @@ -55,7 +77,16 @@ pub enum ScopeObjectKind { Definition, Parameter, TypeAlias, - Module, + FunctionCall, + Module(Module), +} + +/// A scope object of module type represents an import stmt on an AST and +/// is used to record information on the AST +#[derive(PartialEq, Clone, Debug)] +pub struct Module { + /// Record stmts which import this module and whether has been used, for check unused imported module and var definition + pub import_stmts: Vec<(NodeRef, bool)>, } /// A Scope maintains a set of objects and links to its containing @@ -96,8 +127,35 @@ impl Scope { } } + /// Get all usable scope objects in current and parent scope. + pub fn all_usable_objects(&self) -> IndexMap>> { + let mut res = match &self.parent { + Some(parent) => match parent.upgrade() { + Some(parent) => parent.borrow().all_usable_objects(), + None => IndexMap::new(), + }, + None => IndexMap::new(), + }; + + for (name, obj) in &self.elems { + match &obj.borrow().kind { + ScopeObjectKind::Module(module) => { + for stmt in &module.import_stmts { + if let Import(import_stmt) = &stmt.0.node { + res.insert(import_stmt.name.clone(), obj.clone()); + } + } + } + _ => { + res.insert(name.clone(), obj.clone()); + } + } + } + res + } + /// Set a type by name to existed object, return true if found. - pub fn set_ty(&mut self, name: &str, ty: Rc) -> bool { + pub fn set_ty(&mut self, name: &str, ty: TypeRef) -> bool { match self.elems.get_mut(name) { Some(obj) => { let mut obj = obj.borrow_mut(); @@ -113,17 +171,7 @@ impl ContainsPos for Scope { /// Check if current scope contains a position fn contains_pos(&self, pos: &Position) -> bool { match &self.kind { - ScopeKind::Package(files) => { - if files.contains(&pos.filename) { - self.children.iter().any(|s| s.borrow().contains_pos(pos)) - || self - .elems - .iter() - .any(|(_, child)| child.borrow().contains_pos(pos)) - } else { - false - } - } + ScopeKind::Package(files) => files.contains(&pos.filename), _ => self.start.less_equal(pos) && pos.less_equal(&self.end), } } @@ -132,7 +180,7 @@ impl ContainsPos for Scope { #[derive(Clone, Debug)] pub enum ScopeKind { /// Package scope. - Package(Vec), + Package(IndexSet), /// Builtin scope. Builtin, /// Schema name string. @@ -232,15 +280,19 @@ impl Scope { /// Program scope is scope contains a multiple scopes related to the /// package path. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct ProgramScope { pub scope_map: IndexMap>>, pub import_names: IndexMap>, + pub node_ty_map: NodeTyMap, pub handler: Handler, } unsafe impl Send for ProgramScope {} +unsafe impl Send for Scope {} +unsafe impl Sync for Scope {} + impl ProgramScope { /// Get all package paths. #[inline] @@ -255,11 +307,18 @@ impl ProgramScope { } /// Return diagnostic pretty string but do not abort if the session exists any diagnostic. - pub fn emit_diagnostics_to_string(&self, sess: Arc) -> Result<(), String> { + pub fn emit_diagnostics_to_string( + &self, + sess: Arc, + include_warning: bool, + ) -> Result<(), String> { let emit_error = || -> anyhow::Result<()> { // Add resolve errors into the session for diag in &self.handler.diagnostics { - if matches!(diag.level, Level::Error) { + if matches!(diag.level, Level::Error) || matches!(diag.level, Level::Suggestions) { + sess.add_err(diag.clone())?; + } + if include_warning && matches!(diag.level, Level::Warning) { sess.add_err(diag.clone())?; } } @@ -277,10 +336,21 @@ impl ProgramScope { }; emit_error().map_err(|e| e.to_string()) } + + /// Returns the inner most scope on the position. + pub fn inner_most_scope(&self, pos: &Position) -> Option { + for (_, scope) in &self.scope_map { + match scope.borrow().inner_most(&pos) { + Some(scope) => return Some(scope), + None => continue, + } + } + None + } } /// Construct a builtin scope -pub(crate) fn builtin_scope() -> Scope { +pub fn builtin_scope() -> Scope { let mut elems = IndexMap::default(); for (name, builtin_func) in BUILTIN_FUNCTIONS.iter() { elems.insert( @@ -289,9 +359,8 @@ pub(crate) fn builtin_scope() -> Scope { name: name.to_string(), start: Position::dummy_pos(), end: Position::dummy_pos(), - ty: Rc::new(builtin_func.clone()), + ty: Arc::new(builtin_func.clone()), kind: ScopeObjectKind::Definition, - used: false, doc: None, })), ); @@ -342,7 +411,7 @@ impl<'ctx> Resolver<'ctx> { /// Find scope object type by name. #[inline] - pub fn find_type_in_scope(&mut self, name: &str) -> Option> { + pub fn find_type_in_scope(&mut self, name: &str) -> Option { self.scope .borrow() .lookup(name) @@ -351,13 +420,30 @@ impl<'ctx> Resolver<'ctx> { /// Lookup type from the scope by name, if not found, emit a compile error and /// return the any type. - pub fn lookup_type_from_scope(&mut self, name: &str, pos: Position) -> Rc { + pub fn lookup_type_from_scope(&mut self, name: &str, range: Range) -> TypeRef { match self.find_type_in_scope(name) { Some(ty) => ty, None => { - self.handler.add_compile_error( - &format!("name '{}' is not defined", name.replace('@', "")), - pos, + let mut suggestion = String::new(); + let names = self + .scope + .borrow() + .all_usable_objects() + .keys() + .cloned() + .collect::>(); + let suggs = suggestions::provide_suggestions(name, &names); + if suggs.len() > 0 { + suggestion = format!(", did you mean '{:?}'?", suggs); + } + self.handler.add_compile_error_with_suggestions( + &format!( + "name '{}' is not defined{}", + name.replace('@', ""), + suggestion + ), + range, + Some(suggs.clone()), ); self.any_ty() } @@ -365,17 +451,20 @@ impl<'ctx> Resolver<'ctx> { } /// Set type to the scope exited object, if not found, emit a compile error. - pub fn set_type_to_scope(&mut self, name: &str, ty: Rc, pos: Position) { + pub fn set_type_to_scope(&mut self, name: &str, ty: TypeRef, node: &ast::Node) { let mut scope = self.scope.borrow_mut(); match scope.elems.get_mut(name) { Some(obj) => { let mut obj = obj.borrow_mut(); - obj.ty = self.ctx.ty_ctx.infer_to_variable_type(ty); + let infer_ty = self.ctx.ty_ctx.infer_to_variable_type(ty); + self.node_ty_map + .insert(self.get_node_key(node.id.clone()), infer_ty.clone()); + obj.ty = infer_ty; } None => { self.handler.add_compile_error( &format!("name '{}' is not defined", name.replace('@', "")), - pos, + node.get_span_pos(), ); } } @@ -395,4 +484,222 @@ impl<'ctx> Resolver<'ctx> { pub fn contains_object(&mut self, name: &str) -> bool { self.scope.borrow().elems.contains_key(name) } + + pub fn get_node_key(&self, id: AstIndex) -> NodeKey { + NodeKey { + pkgpath: self.ctx.pkgpath.clone(), + id, + } + } +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize)] +pub struct NodeKey { + pub pkgpath: String, + pub id: AstIndex, +} + +pub type NodeTyMap = IndexMap; +pub type KCLScopeCache = Arc>; + +/// For CachedScope, we assume that all changed files must be located in kclvm_ast::MAIN_PKG , +/// if this is not the case, please clear the cache directly +#[derive(Debug, Clone, Default)] +pub struct CachedScope { + pub program_root: String, + pub scope_map: IndexMap>>, + pub node_ty_map: NodeTyMap, + dependency_graph: DependencyGraph, +} + +unsafe impl Send for CachedScope {} +unsafe impl Sync for CachedScope {} + +#[derive(Debug, Clone, Default)] +struct DependencyGraph { + /// map filename to pkgpath + pub module_map: HashMap>, + /// map pkgpath to node + pub node_map: HashMap, +} + +impl DependencyGraph { + pub fn clear(&mut self) { + self.module_map.clear(); + self.node_map.clear(); + } + + pub fn update(&mut self, program: &ast::Program) -> Result, String> { + let mut new_modules = HashMap::new(); + for (pkgpath, modules) in program.pkgs.iter() { + if pkgpath == kclvm_ast::MAIN_PKG { + continue; + } + if !self.node_map.contains_key(pkgpath) { + self.node_map.insert( + pkgpath.to_string(), + DependencyNode { + pkgpath: pkgpath.to_string(), + parents: HashSet::new(), + children: HashSet::new(), + }, + ); + } + for module in modules { + if !self.module_map.contains_key(&module.filename) { + new_modules.insert(module.filename.to_string(), module); + self.module_map + .insert(module.filename.to_string(), HashSet::new()); + } + self.module_map + .get_mut(&module.filename) + .unwrap() + .insert(pkgpath.to_string()); + } + } + + for new_module in new_modules.values() { + self.add_new_module(new_module); + } + let mut invalidated_set = HashSet::new(); + if let Some(main_modules) = program.pkgs.get(kclvm_ast::MAIN_PKG) { + for module in main_modules { + let result = self.invalidate_module(module)?; + for pkg in result { + invalidated_set.insert(pkg); + } + self.remove_dependency_from_pkg(&module.filename); + self.add_new_module(module); + } + } + Ok(invalidated_set) + } + + fn add_new_module(&mut self, new_module: &ast::Module) { + let module_file = new_module.filename.clone(); + if let Some(pkgpaths) = self.module_map.get(&module_file) { + for stmt in &new_module.body { + if let ast::Stmt::Import(import_stmt) = &stmt.node { + let parent_pkg = &import_stmt.path.node; + if let Some(parent_node) = self.node_map.get_mut(parent_pkg) { + parent_node.children.insert(new_module.filename.clone()); + } + for pkgpath in pkgpaths { + let cur_node = self.node_map.get_mut(pkgpath).unwrap(); + cur_node.parents.insert(parent_pkg.clone()); + } + } + } + } + } + + fn invalidate_module( + &mut self, + changed_module: &ast::Module, + ) -> Result, String> { + let module_file = changed_module.filename.clone(); + let mut invalidated_set = HashSet::new(); + if let Some(pkgpaths) = self.module_map.get(&module_file).cloned() { + let mut pkg_queue = VecDeque::new(); + for pkgpath in pkgpaths.iter() { + invalidated_set.insert(pkgpath.clone()); + pkg_queue.push_back(self.node_map.get(pkgpath)); + } + + let mut old_size = 0; + while old_size < invalidated_set.len() { + old_size = invalidated_set.len(); + let cur_node = loop { + match pkg_queue.pop_front() { + Some(cur_node) => match cur_node { + None => continue, + Some(cur_node) => { + if invalidated_set.contains(&cur_node.pkgpath) { + continue; + } + invalidated_set.insert(cur_node.pkgpath.clone()); + break Some(cur_node); + } + }, + None => break None, + } + }; + if let Some(cur_node) = cur_node { + for child in cur_node.children.iter() { + if let Some(child_pkgs) = self.module_map.get(child) { + for child_pkg in child_pkgs { + if invalidated_set.contains(child_pkg) { + continue; + } + pkg_queue.push_back(self.node_map.get(child_pkg)); + } + } + } + } + } + }; + Ok(invalidated_set) + } + + fn remove_dependency_from_pkg(&mut self, filename: &str) { + if let Some(pkgpaths) = self.module_map.get(filename).cloned() { + for pkgpath in pkgpaths { + if let Some(node) = self.node_map.get(&pkgpath).cloned() { + for parent in node.parents { + if let Some(parent_node) = self.node_map.get_mut(&parent) { + parent_node.children.remove(filename); + } + } + } + } + } + } +} +#[derive(Debug, Clone, Default)] +struct DependencyNode { + pkgpath: String, + //the pkgpath which is imported by this pkg + parents: HashSet, + //the files which import this pkg + children: HashSet, +} + +impl CachedScope { + pub fn new(scope: &ProgramScope, program: &ast::Program) -> Self { + let mut cached_scope = Self { + program_root: program.root.to_string(), + scope_map: scope.scope_map.clone(), + node_ty_map: scope.node_ty_map.clone(), + dependency_graph: DependencyGraph::default(), + }; + let invalidated_pkgs = cached_scope.dependency_graph.update(program); + cached_scope.invalidte_cache(invalidated_pkgs.as_ref()); + cached_scope + } + + pub fn clear(&mut self) { + self.scope_map.clear(); + self.node_ty_map.clear(); + self.dependency_graph.clear(); + } + + pub fn invalidte_cache(&mut self, invalidated_pkgs: Result<&HashSet, &String>) { + match invalidated_pkgs { + Ok(invalidated_pkgs) => { + for invalidated_pkg in invalidated_pkgs.iter() { + self.scope_map.remove(invalidated_pkg); + } + } + Err(_) => self.clear(), + } + } + + pub fn update(&mut self, program: &ast::Program) { + if self.program_root != program.root { + self.clear(); + self.program_root = program.root.clone(); + } + let invalidated_pkgs = self.dependency_graph.update(program); + self.invalidte_cache(invalidated_pkgs.as_ref()); + } } diff --git a/kclvm/sema/src/resolver/test_data/annotation_check_assignment.k b/kclvm/sema/src/resolver/test_data/annotation_check_assignment.k new file mode 100644 index 000000000..cc26f36b0 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/annotation_check_assignment.k @@ -0,0 +1,6 @@ +params = option("params") or {} +# Use `k = v` to override existing annotations +annotations: {str:str} = {k = v for k, v in params.annotations or {}} +items = [item | { + metadata.annotations: annotations +} for item in option("items")] \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/assign_in_lambda.k b/kclvm/sema/src/resolver/test_data/assign_in_lambda.k new file mode 100644 index 000000000..cd8ca643d --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/assign_in_lambda.k @@ -0,0 +1,6 @@ +lambda { + containers = [] + if True: + containers = [] + images: [str] = [c.image for c in containers] +} diff --git a/kclvm/sema/src/resolver/test_data/attr_ty_check.k b/kclvm/sema/src/resolver/test_data/attr_ty_check.k new file mode 100644 index 000000000..2c86d4710 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/attr_ty_check.k @@ -0,0 +1,9 @@ +schema Data: + id?: int + +schema Config: + datas: [Data] + +config = Config { + datas: [{id = "1"}] +} diff --git a/kclvm/sema/src/resolver/test_data/doc.k b/kclvm/sema/src/resolver/test_data/doc.k index 397bf963c..5ac8e6154 100644 --- a/kclvm/sema/src/resolver/test_data/doc.k +++ b/kclvm/sema/src/resolver/test_data/doc.k @@ -19,7 +19,7 @@ schema Server: See also: kusion_models/core/v1/metadata.k. Examples - ---------------------- + -------- myCustomApp = AppConfiguration { name = "componentName" } diff --git a/kclvm/sema/src/resolver/test_data/doc.txt b/kclvm/sema/src/resolver/test_data/doc.txt index f749c9412..6cf94821d 100644 --- a/kclvm/sema/src/resolver/test_data/doc.txt +++ b/kclvm/sema/src/resolver/test_data/doc.txt @@ -12,11 +12,11 @@ A Server-level attribute. The name of the long-running service. See also: kusion_models/core/v1/metadata.k. - labels : {str:str}, optional + labels: {str:str}, optional A Server-level attribute. The labels of the long-running service. See also: kusion_models/core/v1/metadata.k. - + Examples ---------------------- myCustomApp = AppConfiguration { diff --git a/kclvm/sema/src/resolver/test_data/function_with_default_values.k b/kclvm/sema/src/resolver/test_data/function_with_default_values.k new file mode 100644 index 000000000..8d28c586b --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/function_with_default_values.k @@ -0,0 +1,4 @@ +is_alpha = lambda s: str, locale: str = 'en-US', options: {str:} = {} -> bool { + False +} +a = is_alpha("c") diff --git a/kclvm/sema/src/resolver/test_data/kcl.mod b/kclvm/sema/src/resolver/test_data/kcl.mod index e69de29bb..c51d42cae 100644 --- a/kclvm/sema/src/resolver/test_data/kcl.mod +++ b/kclvm/sema/src/resolver/test_data/kcl.mod @@ -0,0 +1,2 @@ +[package] + diff --git a/kclvm/sema/src/resolver/test_data/lint.k b/kclvm/sema/src/resolver/test_data/lint.k index 692e82e37..e44eb6ea8 100644 --- a/kclvm/sema/src/resolver/test_data/lint.k +++ b/kclvm/sema/src/resolver/test_data/lint.k @@ -1,5 +1,6 @@ import import_test.a # UnusedImport import import_test.a # ReImport +import regex schema Person: name: str @@ -8,3 +9,18 @@ schema Person: b1 = b._b import import_test.b # ImportPosition + +requires = option("params").requires or [] +# Define the validation function +validate_required_labels = lambda item, requires { + if requires: + requires_map = {r.key: r.allowedRegex or "" for r in requires} + labels = item.metadata.labels or {} + if labels: + assert all k, v in labels { + regex.match(v, requires_map[k]) if requires_map[k] + }, "must provide labels with the regex ${requires_map}" + item +} +# Validate All resource +items = [validate_required_labels(i, requires) for i in option("items")] diff --git a/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/main.k b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/main.k new file mode 100644 index 000000000..156a89f90 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/main.k @@ -0,0 +1,5 @@ +schema Name: + name?: str + +schema Person: + name: Name = Name {name = "Alice"} \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/sub_pkg/main.k b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/sub_pkg/main.k new file mode 100644 index 000000000..156a89f90 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg/sub_pkg/main.k @@ -0,0 +1,5 @@ +schema Name: + name?: str + +schema Person: + name: Name = Name {name = "Alice"} \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/pkg_asname/pkg_asname.k b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg_asname.k new file mode 100644 index 000000000..c32c27c3f --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/pkg_asname/pkg_asname.k @@ -0,0 +1,5 @@ +import .pkg as p1 +import .pkg.sub_pkg as p2 + +p = pkg.Person{} +pp = subpkg.Person{} diff --git a/kclvm/sema/src/resolver/test_data/pkg_not_found_suggestion.k b/kclvm/sema/src/resolver/test_data/pkg_not_found_suggestion.k new file mode 100644 index 000000000..0655110e0 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/pkg_not_found_suggestion.k @@ -0,0 +1,3 @@ +import k9s + +a = k9s.a \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/schema_params_miss.k b/kclvm/sema/src/resolver/test_data/schema_params_miss.k new file mode 100644 index 000000000..4c8c7d387 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/schema_params_miss.k @@ -0,0 +1,6 @@ +schema D[name: str]: # '' + n: str = name + +d = D() { # expected 1 positional argument, found 0 + n = "" +} \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/system_package.k b/kclvm/sema/src/resolver/test_data/system_package.k new file mode 100644 index 000000000..2873bc47e --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/system_package.k @@ -0,0 +1,4 @@ +import base64 + +base64_encode = base64.encode +base64_decode = base64.decode diff --git a/kclvm/sema/src/resolver/test_data/test_builtin/glob.k b/kclvm/sema/src/resolver/test_data/test_builtin/glob.k new file mode 100644 index 000000000..ca68b1a5c --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/test_builtin/glob.k @@ -0,0 +1,2 @@ +import file +b = file.glob() \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/test_builtin/read.k b/kclvm/sema/src/resolver/test_data/test_builtin/read.k new file mode 100644 index 000000000..b8fae7ab5 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/test_builtin/read.k @@ -0,0 +1,2 @@ +import file +a = file.read() \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_data/ty_in_lambda.k b/kclvm/sema/src/resolver/test_data/ty_in_lambda.k new file mode 100644 index 000000000..4b9a1929c --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/ty_in_lambda.k @@ -0,0 +1,9 @@ +_b = True +a = lambda item: {str:}, c: {str:} -> {str:str} { + result = {"aaa": "bbb"} + if _b : + result = {} + result +} + +result = {"ccc": "ddd"} diff --git a/kclvm/sema/src/resolver/test_data/undef_lambda_param.k b/kclvm/sema/src/resolver/test_data/undef_lambda_param.k new file mode 100644 index 000000000..dd2cd7f86 --- /dev/null +++ b/kclvm/sema/src/resolver/test_data/undef_lambda_param.k @@ -0,0 +1,3 @@ +lambda x: Undef { # 'Undef' is undefined + x +} \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_0.k b/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_0.k new file mode 100644 index 000000000..48b3e40aa --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_0.k @@ -0,0 +1,9 @@ +schema Name: + name: [A] + +schema A: + aa: int + +n = Name { + name = [{a = 1}] +} diff --git a/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_1.k b/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_1.k new file mode 100644 index 000000000..0cca8aa4b --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/cannot_find_member_1.k @@ -0,0 +1,9 @@ +schema Name: + name: {str: A} + +schema A: + aa: int + +n = Name { + name = {a = {a = 1}} +} diff --git a/kclvm/sema/src/resolver/test_fail_data/lambda_ty_error.k b/kclvm/sema/src/resolver/test_fail_data/lambda_ty_error.k new file mode 100644 index 000000000..e07633419 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/lambda_ty_error.k @@ -0,0 +1,6 @@ +_func = lambda x: int, y: int -> int { + x - y +} # Ok +_func = lambda x: int, y: int -> str { + str(x + y) +} # Error: expect function (int, int) -> str, got function (int, int) -> int \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/main.k b/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/main.k new file mode 100644 index 000000000..46fc19516 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/main.k @@ -0,0 +1,3 @@ +import sub as s1 + +main = s.sub \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/sub/main.k b/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/sub/main.k new file mode 100644 index 000000000..fd778d797 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/not_found_suggest/sub/main.k @@ -0,0 +1 @@ +sub = "sub" \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/redefine_import/main.k b/kclvm/sema/src/resolver/test_fail_data/redefine_import/main.k new file mode 100644 index 000000000..2534d9819 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/redefine_import/main.k @@ -0,0 +1,5 @@ +import sub as s + +import sub.sub as s + +main = s.sub_sub \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/main.k b/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/main.k new file mode 100644 index 000000000..fd778d797 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/main.k @@ -0,0 +1 @@ +sub = "sub" \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/sub/main.k b/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/sub/main.k new file mode 100644 index 000000000..7f92e0de0 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/redefine_import/sub/sub/main.k @@ -0,0 +1 @@ +sub_sub = "sub_sub" \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_args.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_args.k index 0cd09bd4f..2160a0b5e 100644 --- a/kclvm/sema/src/resolver/test_fail_data/unmatched_args.k +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_args.k @@ -4,4 +4,9 @@ schema Foo[a : int]: f = lambda x {} foo = Foo(1,2,3) -f(1,2) \ No newline at end of file +f(1,2) + +schema Foo2[a : int, b: int]: + bar? : int + +foo2 = Foo2(1,2,3) \ No newline at end of file diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_index_sign_default_value.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_index_sign_default_value.k new file mode 100644 index 000000000..98e93a0f5 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_index_sign_default_value.k @@ -0,0 +1,5 @@ +schema WithComponent: + name: str + +schema WithComponents: + [name: str]: WithComponent = 1 diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_0.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_0.k new file mode 100644 index 000000000..1750f4f3f --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_0.k @@ -0,0 +1,11 @@ +schema Name: + name: str + +schema Config: + n: {str:Name} + +Config { + n = { + n.n = "n" + } +} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_1.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_1.k new file mode 100644 index 000000000..66f6324ba --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_1.k @@ -0,0 +1,11 @@ +schema Name: + name: str + +schema Config: + n: [Name] + +Config { + n = [{ + n = "n" + }] +} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_2.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_2.k new file mode 100644 index 000000000..77ff72246 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_2.k @@ -0,0 +1,11 @@ +schema Name: + name: str + +schema Config: + n: {str:[Name]} + +Config { + n = {n = [{ + n = "n" + }]} +} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_3.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_3.k new file mode 100644 index 000000000..8b7f9eff4 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_nest_schema_attr_3.k @@ -0,0 +1,14 @@ +schema Name1: + name1: str + +schema Name2: + name2: str + +schema Config: + n: Name1 | Name2 + +Config { + n = { + n = "n" + } +} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_0.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_0.k new file mode 100644 index 000000000..f311d3092 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_0.k @@ -0,0 +1,6 @@ +schema Name: + name: str + +n: {str:Name} = { + n.n = "n" +} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_1.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_1.k new file mode 100644 index 000000000..bc80e9a91 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_1.k @@ -0,0 +1,6 @@ +schema Name: + name: str + +n: [Name] = [{ + n = "n" +}] diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_2.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_2.k new file mode 100644 index 000000000..6522cdd80 --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_2.k @@ -0,0 +1,6 @@ +schema Name: + name: str + +n: {str:[Name]} = {n = [{ + n = "n" +}]} diff --git a/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_3.k b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_3.k new file mode 100644 index 000000000..819b2751e --- /dev/null +++ b/kclvm/sema/src/resolver/test_fail_data/unmatched_schema_attr_3.k @@ -0,0 +1,9 @@ +schema Name1: + name1: str + +schema Name2: + name2: str + +n: Name1 | Name2 = { + n = "n" +} diff --git a/kclvm/sema/src/resolver/tests.rs b/kclvm/sema/src/resolver/tests.rs index ea21a9907..54ccd920b 100644 --- a/kclvm/sema/src/resolver/tests.rs +++ b/kclvm/sema/src/resolver/tests.rs @@ -3,16 +3,41 @@ use super::Resolver; use crate::builtin::BUILTIN_FUNCTION_NAMES; use crate::pre_process::pre_process_program; use crate::resolver::resolve_program; +use crate::resolver::resolve_program_with_opts; use crate::resolver::scope::*; use crate::ty::{Type, TypeKind}; +use anyhow::Result; use kclvm_ast::ast; use kclvm_ast::pos::ContainsPos; use kclvm_error::*; +use kclvm_parser::load_program; +use kclvm_parser::parse_file_force_errors; +use kclvm_parser::LoadProgramOptions; use kclvm_parser::ParseSession; -use kclvm_parser::{load_program, parse_program}; +use kclvm_utils::path::PathPrefix; +use std::collections::HashMap; use std::path::Path; -use std::rc::Rc; use std::sync::Arc; +use std::sync::Mutex; + +pub fn parse_program(filename: &str) -> Result { + let abspath = std::fs::canonicalize(std::path::PathBuf::from(filename)).unwrap(); + + let mut prog = ast::Program { + root: abspath.parent().unwrap().adjust_canonicalization(), + pkgs: HashMap::new(), + }; + + let mut module = parse_file_force_errors(abspath.to_str().unwrap(), None)?; + module.filename = filename.to_string(); + module.pkg = kclvm_ast::MAIN_PKG.to_string(); + module.name = kclvm_ast::MAIN_PKG.to_string(); + + prog.pkgs + .insert(kclvm_ast::MAIN_PKG.to_string(), vec![module]); + + Ok(prog) +} #[test] fn test_scope() { @@ -23,7 +48,7 @@ fn test_scope() { assert!(obj_ref.ty.is_func()); } for name in BUILTIN_FUNCTION_NAMES { - scope.set_ty(name, Rc::new(Type::ANY)); + scope.set_ty(name, Arc::new(Type::ANY)); } for name in BUILTIN_FUNCTION_NAMES { let obj = scope.lookup(name).unwrap(); @@ -44,6 +69,37 @@ fn test_resolve_program() { assert!(main_scope.lookup("print").is_none()); } +#[test] +fn test_resolve_program_with_cache() { + let mut program = parse_program("./src/resolver/test_data/assign.k").unwrap(); + + let scope = resolve_program_with_opts( + &mut program, + Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + None, + ); + let cached_scope = Arc::new(Mutex::new(CachedScope::new(&scope, &program))); + let scope = resolve_program_with_opts( + &mut program, + Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + Some(cached_scope), + ); + assert_eq!(scope.pkgpaths(), vec!["__main__".to_string()]); + let main_scope = scope.main_scope().unwrap(); + let main_scope = main_scope.borrow_mut(); + assert!(main_scope.lookup("a").is_some()); + assert!(main_scope.lookup("b").is_some()); + assert!(main_scope.lookup("print").is_none()); +} + #[test] fn test_pkg_init_in_schema_resolve() { let sess = Arc::new(ParseSession::default()); @@ -51,8 +107,10 @@ fn test_pkg_init_in_schema_resolve() { sess.clone(), &["./src/resolver/test_data/pkg_init_in_schema.k"], None, + None, ) - .unwrap(); + .unwrap() + .program; let scope = resolve_program(&mut program); assert_eq!( scope.pkgpaths(), @@ -63,7 +121,7 @@ fn test_pkg_init_in_schema_resolve() { if let ast::Stmt::SchemaAttr(attr) = &schema.body[0].node { let value = attr.value.as_ref().unwrap(); if let ast::Expr::Schema(schema_expr) = &value.node { - assert_eq!(schema_expr.name.node.names, vec!["Name".to_string()]); + assert_eq!(schema_expr.name.node.get_names(), vec!["Name".to_string()]); } else { panic!("test failed, expect schema expr, got {:?}", value) } @@ -86,6 +144,8 @@ fn test_resolve_program_fail() { let work_dir = "./src/resolver/test_fail_data/"; let cases = &[ "attr.k", + "cannot_find_member_0.k", + "cannot_find_member_1.k", "cannot_find_module.k", "comp_clause_error_0.k", "comp_clause_error_1.k", @@ -97,7 +157,16 @@ fn test_resolve_program_fail() { "mutable_error_1.k", "unique_key_error_0.k", "unique_key_error_1.k", + "unmatched_index_sign_default_value.k", "unmatched_args.k", + "unmatched_nest_schema_attr_0.k", + "unmatched_nest_schema_attr_1.k", + "unmatched_nest_schema_attr_2.k", + "unmatched_nest_schema_attr_3.k", + "unmatched_schema_attr_0.k", + "unmatched_schema_attr_1.k", + "unmatched_schema_attr_2.k", + "unmatched_schema_attr_3.k", ]; for case in cases { let path = Path::new(work_dir).join(case); @@ -107,6 +176,32 @@ fn test_resolve_program_fail() { } } +#[test] +fn test_resolve_program_redefine() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_fail_data/redefine_import/main.k"], + None, + None, + ) + .unwrap() + .program; + + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 2); + let diag = &scope.handler.diagnostics[0]; + assert_eq!( + diag.code, + Some(DiagnosticId::Error(ErrorKind::CompileError)) + ); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "the name 's' is defined multiple times, 's' must be defined only once" + ); +} + #[test] fn test_resolve_program_mismatch_type_fail() { let mut program = parse_program("./src/resolver/test_fail_data/config_expr.k").unwrap(); @@ -128,8 +223,10 @@ fn test_resolve_program_cycle_reference_fail() { sess.clone(), &["./src/resolver/test_fail_data/cycle_reference/file1.k"], None, + None, ) - .unwrap(); + .unwrap() + .program; let scope = resolve_program(&mut program); let err_messages = [ "There is a circular import reference between module file1 and file2", @@ -153,8 +250,10 @@ fn test_record_used_module() { sess.clone(), &["./src/resolver/test_data/record_used_module.k"], None, + None, ) - .unwrap(); + .unwrap() + .program; let scope = resolve_program(&mut program); let main_scope = scope .scope_map @@ -164,11 +263,13 @@ fn test_record_used_module() { .clone(); for (_, obj) in main_scope.elems { let obj = obj.borrow_mut().clone(); - if obj.kind == ScopeObjectKind::Module { - if obj.name == "math" { - assert!(!obj.used); - } else { - assert!(obj.used); + if let ScopeObjectKind::Module(m) = obj.kind { + for (_, used) in m.import_stmts { + if obj.name == "math" { + assert!(!used); + } else { + assert!(used); + } } } } @@ -186,7 +287,7 @@ fn test_resolve_program_illegal_attr_fail() { Some(DiagnosticId::Error(ErrorKind::IllegalAttributeError)) ); assert_eq!(diag.messages.len(), 1); - assert_eq!(diag.messages[0].pos.line, 4); + assert_eq!(diag.messages[0].range.0.line, 4); assert_eq!(diag.messages[0].message, expect_err_msg,); let diag = &scope.handler.diagnostics[1]; assert_eq!( @@ -195,14 +296,14 @@ fn test_resolve_program_illegal_attr_fail() { ); assert_eq!(diag.messages.len(), 1); assert_eq!(diag.messages[0].message, expect_err_msg,); - assert_eq!(diag.messages[0].pos.line, 5); + assert_eq!(diag.messages[0].range.0.line, 5); } #[test] fn test_resolve_program_unmatched_args_fail() { let mut program = parse_program("./src/resolver/test_fail_data/unmatched_args.k").unwrap(); let scope = resolve_program(&mut program); - assert_eq!(scope.handler.diagnostics.len(), 2); + assert_eq!(scope.handler.diagnostics.len(), 3); let expect_err_msg = "\"Foo\" takes 1 positional argument but 3 were given"; let diag = &scope.handler.diagnostics[0]; assert_eq!( @@ -210,7 +311,7 @@ fn test_resolve_program_unmatched_args_fail() { Some(DiagnosticId::Error(ErrorKind::CompileError)) ); assert_eq!(diag.messages.len(), 1); - assert_eq!(diag.messages[0].pos.line, 6); + assert_eq!(diag.messages[0].range.0.line, 6); assert_eq!(diag.messages[0].message, expect_err_msg); let expect_err_msg = "\"f\" takes 1 positional argument but 2 were given"; @@ -220,7 +321,17 @@ fn test_resolve_program_unmatched_args_fail() { Some(DiagnosticId::Error(ErrorKind::CompileError)) ); assert_eq!(diag.messages.len(), 1); - assert_eq!(diag.messages[0].pos.line, 7); + assert_eq!(diag.messages[0].range.0.line, 7); + assert_eq!(diag.messages[0].message, expect_err_msg); + + let expect_err_msg = "\"Foo2\" takes 2 positional arguments but 3 were given"; + let diag = &scope.handler.diagnostics[2]; + assert_eq!( + diag.code, + Some(DiagnosticId::Error(ErrorKind::CompileError)) + ); + assert_eq!(diag.messages.len(), 1); + assert_eq!(diag.messages[0].range.0.line, 12); assert_eq!(diag.messages[0].message, expect_err_msg); } @@ -238,7 +349,7 @@ fn test_resolve_program_module_optional_select_fail() { Some(DiagnosticId::Error(ErrorKind::CompileError)) ); assert_eq!(diag.messages.len(), 1); - assert_eq!(diag.messages[0].pos.line, 3); + assert_eq!(diag.messages[0].range.0.line, 3); assert_eq!(diag.messages[0].message, expect_err_msg); let expect_err_msg = "Module 'math' imported but unused"; @@ -248,24 +359,24 @@ fn test_resolve_program_module_optional_select_fail() { Some(DiagnosticId::Warning(WarningKind::UnusedImportWarning)) ); assert_eq!(diag.messages.len(), 1); - assert_eq!(diag.messages[0].pos.line, 1); + assert_eq!(diag.messages[0].range.0.line, 1); assert_eq!(diag.messages[0].message, expect_err_msg); } #[test] fn test_lint() { let sess = Arc::new(ParseSession::default()); - let mut program = - load_program(sess.clone(), &["./src/resolver/test_data/lint.k"], None).unwrap(); - pre_process_program(&mut program); - let mut resolver = Resolver::new( - &program, - Options { - raise_err: true, - config_auto_fix: false, - lint_check: true, - }, - ); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/lint.k"], + None, + None, + ) + .unwrap() + .program; + let opts = Options::default(); + pre_process_program(&mut program, &opts); + let mut resolver = Resolver::new(&program, opts); resolver.resolve_import(); resolver.check_and_lint(kclvm_ast::MAIN_PKG); @@ -278,40 +389,64 @@ fn test_lint() { handler.add_warning( WarningKind::ImportPositionWarning, &[Message { - pos: Position { - filename: filename.clone(), - line: 10, - column: None, - }, + range: ( + Position { + filename: filename.clone(), + line: 11, + column: Some(0), + }, + Position { + filename: filename.clone(), + line: 11, + column: Some(20), + }, + ), style: Style::Line, message: format!("Importstmt should be placed at the top of the module"), note: Some("Consider moving tihs statement to the top of the file".to_string()), + suggested_replacement: None, }], ); handler.add_warning( WarningKind::ReimportWarning, &[Message { - pos: Position { - filename: filename.clone(), - line: 2, - column: None, - }, + range: ( + Position { + filename: filename.clone(), + line: 2, + column: Some(0), + }, + Position { + filename: filename.clone(), + line: 2, + column: Some(20), + }, + ), style: Style::Line, message: format!("Module 'a' is reimported multiple times"), note: Some("Consider removing this statement".to_string()), + suggested_replacement: None, }], ); handler.add_warning( WarningKind::UnusedImportWarning, &[Message { - pos: Position { - filename, - line: 1, - column: None, - }, + range: ( + Position { + filename: filename.clone(), + line: 1, + column: Some(0), + }, + Position { + filename: filename.clone(), + line: 1, + column: Some(20), + }, + ), style: Style::Line, message: format!("Module 'import_test.a' imported but unused"), note: Some("Consider removing this statement".to_string()), + suggested_replacement: None, }], ); for (d1, d2) in resolver @@ -381,8 +516,10 @@ fn test_pkg_scope() { sess.clone(), &["./src/resolver/test_data/pkg_scope.k"], None, + None, ) - .unwrap(); + .unwrap() + .program; let scope = resolve_program(&mut program); assert_eq!(scope.scope_map.len(), 2); @@ -408,13 +545,6 @@ fn test_pkg_scope() { assert!(main_scope.contains_pos(&pos)); - let pos = Position { - filename: filename.clone(), - line: 10, - column: Some(0), - }; - assert!(!main_scope.contains_pos(&pos)); - let filename = Path::new(&root.clone()) .join("pkg") .join("pkg.k") @@ -428,12 +558,329 @@ fn test_pkg_scope() { }; assert!(pkg_scope.contains_pos(&pos)); +} - let pos = Position { - filename: filename.clone(), - line: 10, - column: Some(0), - }; +#[test] +fn test_system_package() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/system_package.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + let main_scope = scope + .scope_map + .get(kclvm_runtime::MAIN_PKG_PATH) + .unwrap() + .borrow_mut() + .clone(); + + assert!(main_scope.lookup("base64").unwrap().borrow().ty.is_module()); + assert!(main_scope + .lookup("base64_encode") + .unwrap() + .borrow() + .ty + .is_func()); + assert!(main_scope + .lookup("base64_decode") + .unwrap() + .borrow() + .ty + .is_func()); +} + +#[test] +fn test_resolve_program_import_suggest() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_fail_data/not_found_suggest/main.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 2); + let diag = &scope.handler.diagnostics[0]; + assert_eq!( + diag.code, + Some(DiagnosticId::Error(ErrorKind::CompileError)) + ); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "name 's' is not defined, did you mean '[\"s1\"]'?" + ); +} + +#[test] +fn test_resolve_assignment_in_lambda() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/assign_in_lambda.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + let main_scope = scope.scope_map.get("__main__").unwrap().clone(); + assert_eq!(main_scope.borrow().children.len(), 1); + let lambda_scope = main_scope.borrow().children[0].clone(); + assert_eq!(lambda_scope.borrow().elems.len(), 2); + let images_scope_obj = lambda_scope.borrow().elems.get("images").unwrap().clone(); + assert_eq!(images_scope_obj.borrow().ty.ty_str(), "[str]"); +} + +#[test] +fn test_resolve_function_with_default_values() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/function_with_default_values.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert!(!scope.handler.has_errors()); + let main_scope = scope.main_scope().unwrap(); + let func = main_scope.borrow().lookup("is_alpha").unwrap(); + assert!(func.borrow().ty.is_func()); + let func_ty = func.borrow().ty.into_func_type(); + assert_eq!(func_ty.params.len(), 3); + assert_eq!(func_ty.params[0].has_default, false); + assert_eq!(func_ty.params[1].has_default, true); + assert_eq!(func_ty.params[2].has_default, true); +} + +#[test] +fn test_assignment_type_annotation_check_in_lambda() { + let sess = Arc::new(ParseSession::default()); + let opts = LoadProgramOptions::default(); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/annotation_check_assignment.k"], + Some(opts), + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 0); +} + +#[test] +fn test_resolve_lambda_assignment_diagnostic() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_fail_data/lambda_ty_error.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 1); + let diag = &scope.handler.diagnostics[0]; + assert_eq!(diag.code, Some(DiagnosticId::Error(ErrorKind::TypeError))); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "expected (int, int) -> int, got (int, int) -> str" + ); +} + +#[test] +fn test_ty_check_in_dict_assign_to_schema() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/attr_ty_check.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 2); + let diag = &scope.handler.diagnostics[0]; + assert_eq!(diag.code, Some(DiagnosticId::Error(ErrorKind::TypeError))); + assert_eq!(diag.messages.len(), 2); + assert_eq!(diag.messages[0].message, "expected int, got str(1)"); + assert_eq!( + diag.messages[1].message, + "variable is defined here, its type is int, but got str(1)" + ); +} - assert!(!pkg_scope.contains_pos(&pos)); +#[test] +fn test_pkg_not_found_suggestion() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/pkg_not_found_suggestion.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 4); + let diag = &scope.handler.diagnostics[1]; + assert_eq!(diag.code, Some(DiagnosticId::Suggestions)); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "try 'kcl mod add k9s' to download the package not found" + ); + let diag = &scope.handler.diagnostics[2]; + assert_eq!(diag.code, Some(DiagnosticId::Suggestions)); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "find more package on 'https://artifacthub.io'" + ); +} + +#[test] +fn undef_lambda_param() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/undef_lambda_param.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 1); + + let root = &program.root.clone(); + let filename = Path::new(&root.clone()) + .join("undef_lambda_param.k") + .display() + .to_string(); + + let range = scope.handler.diagnostics[0].messages[0].range.clone(); + + assert_eq!( + range, + ( + Position { + filename: filename.clone(), + line: 1, + column: Some(10), + }, + Position { + filename: filename.clone(), + line: 1, + column: Some(15), + } + ) + ); +} + +#[test] +fn test_schema_params_count() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/schema_params_miss.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + assert_eq!(scope.handler.diagnostics.len(), 1); + let diag = &scope.handler.diagnostics[0]; + assert_eq!( + diag.code, + Some(DiagnosticId::Error(ErrorKind::CompileError)) + ); + assert_eq!(diag.messages.len(), 1); + assert_eq!( + diag.messages[0].message, + "expected 1 positional argument, found 0" + ); +} + +#[test] +fn test_set_ty_in_lambda() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/ty_in_lambda.k"], + None, + None, + ) + .unwrap() + .program; + assert_eq!( + resolve_program(&mut program) + .main_scope() + .unwrap() + .borrow() + .lookup("result") + .unwrap() + .borrow() + .ty + .clone() + .ty_str(), + "{str:str}" + ); +} + +#[test] +fn test_pkg_asname() { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program( + sess.clone(), + &["./src/resolver/test_data/pkg_asname/pkg_asname.k"], + None, + None, + ) + .unwrap() + .program; + let scope = resolve_program(&mut program); + let diags = scope.handler.diagnostics; + assert_eq!(diags.len(), 6); + assert_eq!(diags[0].messages[0].message, "name 'pkg' is not defined"); + assert_eq!(diags[2].messages[0].message, "name 'subpkg' is not defined"); +} + +#[test] +fn test_builtin_file_invalid() { + let test_cases = [ + ( + "./src/resolver/test_data/test_builtin/read.k", + "expected 1 positional argument, found 0", + ), + ( + "./src/resolver/test_data/test_builtin/glob.k", + "expected 1 positional argument, found 0", + ), + ]; + + for (file, expected_message) in &test_cases { + let sess = Arc::new(ParseSession::default()); + let mut program = load_program(sess.clone(), &[file], None, None) + .unwrap() + .program; + let scope = resolve_program(&mut program); + let diags = scope.handler.diagnostics; + assert_eq!(diags.len(), 1); + assert_eq!(diags[0].messages[0].message, *expected_message); + } } diff --git a/kclvm/sema/src/resolver/ty.rs b/kclvm/sema/src/resolver/ty.rs index 261aa9699..8e23f9b1e 100644 --- a/kclvm/sema/src/resolver/ty.rs +++ b/kclvm/sema/src/resolver/ty.rs @@ -1,11 +1,14 @@ -use std::rc::Rc; +use std::sync::Arc; use crate::resolver::Resolver; use crate::ty::parser::parse_type_str; -use crate::ty::{assignable_to, SchemaType, Type, TypeKind}; +use crate::ty::{ + assignable_to, is_upper_bound, Attr, DictType, Parameter, SchemaType, Type, TypeKind, TypeRef, +}; use indexmap::IndexMap; use kclvm_ast::ast; use kclvm_ast::pos::GetPos; +use kclvm_error::diagnostic::Range; use kclvm_error::*; use super::node::ResolvedResult; @@ -27,81 +30,94 @@ pub fn ty_str_replace_pkgpath(ty_str: &str, pkgpath: &str) -> String { impl<'ctx> Resolver<'ctx> { #[inline] - pub fn any_ty(&self) -> Rc { + pub fn any_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.any.clone() } #[inline] - pub fn int_ty(&self) -> Rc { + pub fn int_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.int.clone() } #[inline] - pub fn float_ty(&self) -> Rc { + pub fn float_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.float.clone() } #[inline] - pub fn bool_ty(&self) -> Rc { + pub fn bool_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.bool.clone() } #[inline] - pub fn str_ty(&self) -> Rc { + pub fn str_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.str.clone() } #[inline] - pub fn none_ty(&self) -> Rc { + pub fn none_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.none.clone() } #[inline] - pub fn void_ty(&self) -> Rc { + pub fn void_ty(&self) -> TypeRef { self.ctx.ty_ctx.builtin_types.void.clone() } /// Parse the type string with the scope, if parse_ty returns a Named type(schema type or type alias), /// found it from the scope. - pub fn parse_ty_with_scope(&mut self, ty: &ast::Type, pos: Position) -> ResolvedResult { - let ty: Rc = Rc::new(ty.clone().into()); + pub fn parse_ty_with_scope( + &mut self, + ty_node: Option<&ast::Node>, + range: Range, + ) -> ResolvedResult { + let ty: TypeRef = if let Some(ty) = ty_node { + Arc::new(ty.node.clone().into()) + } else { + Arc::new(Type::ANY) + }; // If a named type, find it from scope to get the specific type - let ret_ty = self.upgrade_named_ty_with_scope(ty.clone(), &pos); + let ret_ty = self.upgrade_named_ty_with_scope(ty.clone(), &range, ty_node); self.add_type_alias( &ty.into_type_annotation_str(), &ret_ty.into_type_annotation_str(), ); + if let Some(ty) = ty_node { + self.node_ty_map + .insert(self.get_node_key(ty.id.clone()), ret_ty.clone()); + }; ret_ty } - pub fn parse_ty_str_with_scope(&mut self, ty_str: &str, pos: Position) -> ResolvedResult { - let ty: Rc = parse_type_str(ty_str); + pub fn parse_ty_str_with_scope(&mut self, ty_str: &str, range: Range) -> ResolvedResult { + let ty: TypeRef = parse_type_str(ty_str); // If a named type, find it from scope to get the specific type - let ret_ty = self.upgrade_named_ty_with_scope(ty, &pos); + let ret_ty = self.upgrade_named_ty_with_scope(ty, &range, None); self.add_type_alias(ty_str, &ret_ty.into_type_annotation_str()); ret_ty } /// The given expression must be the expected type. #[inline] - pub fn must_be_type(&mut self, expr: &'ctx ast::NodeRef, expected_ty: Rc) { + pub fn must_be_type(&mut self, expr: &'ctx ast::NodeRef, expected_ty: TypeRef) { let ty = self.expr(expr); - self.must_assignable_to(ty, expected_ty, expr.get_pos(), None); + self.must_assignable_to(ty, expected_ty, expr.get_span_pos(), None); } /// Must assignable to the expected type. #[inline] pub fn must_assignable_to( &mut self, - ty: Rc, - expected_ty: Rc, - pos: Position, - expected_pos: Option, + ty: TypeRef, + expected_ty: TypeRef, + range: Range, + expected_pos: Option, ) { - if !self.check_type(ty.clone(), expected_ty.clone(), &pos) { + if !self.check_type(ty.clone(), expected_ty.clone(), &range) { let mut msgs = vec![Message { - pos, + range, style: Style::LineAndColumn, message: format!("expected {}, got {}", expected_ty.ty_str(), ty.ty_str(),), note: None, + suggested_replacement: None, }]; if let Some(expected_pos) = expected_pos { msgs.push(Message { - pos: expected_pos, + range: expected_pos, style: Style::LineAndColumn, message: format!( "variable is defined here, its type is {}, but got {}", @@ -109,32 +125,104 @@ impl<'ctx> Resolver<'ctx> { ty.ty_str(), ), note: None, + suggested_replacement: None, }); } self.handler.add_error(ErrorKind::TypeError, &msgs); } } + /// Check the type assignment statement between type annotation and target. + pub fn check_assignment_type_annotation( + &mut self, + assign_stmt: &kclvm_ast::ast::AssignStmt, + value_ty: TypeRef, + ) { + if assign_stmt.ty.is_none() { + return; + } + for target in &assign_stmt.targets { + if target.node.names.is_empty() { + continue; + } + let name = &target.node.names[0].node; + // If the assignment statement has type annotation, check the type of value and the type annotation of target + + if let Some(ty_annotation) = &assign_stmt.ty { + let annotation_ty = + self.parse_ty_with_scope(Some(&ty_annotation), ty_annotation.get_span_pos()); + // If the target defined in the scope, check the type of value and the type annotation of target + let target_ty = if let Some(obj) = self.scope.borrow().elems.get(name) { + let obj = obj.borrow(); + if obj.ty.is_any() { + annotation_ty + } else { + if !is_upper_bound(annotation_ty.clone(), obj.ty.clone()) { + self.handler.add_error( + ErrorKind::TypeError, + &[ + Message { + range: target.get_span_pos(), + style: Style::LineAndColumn, + message: format!( + "can not change the type of '{}' to {}", + name, + annotation_ty.ty_str() + ), + note: None, + suggested_replacement: None, + }, + Message { + range: obj.get_span_pos(), + style: Style::LineAndColumn, + message: format!("expected {}", obj.ty.ty_str()), + note: None, + suggested_replacement: None, + }, + ], + ); + } + obj.ty.clone() + } + } else { + annotation_ty + }; + + self.set_type_to_scope(name, target_ty.clone(), &target.node.names[0]); + + // Check the type of value and the type annotation of target + self.must_assignable_to(value_ty.clone(), target_ty, target.get_span_pos(), None) + } + } + } + /// The check type main function, returns a boolean result. #[inline] - pub fn check_type(&mut self, ty: Rc, expected_ty: Rc, pos: &Position) -> bool { + pub fn check_type(&mut self, ty: TypeRef, expected_ty: TypeRef, range: &Range) -> bool { match (&ty.kind, &expected_ty.kind) { (TypeKind::List(item_ty), TypeKind::List(expected_item_ty)) => { - self.check_type(item_ty.clone(), expected_item_ty.clone(), pos) + self.check_type(item_ty.clone(), expected_item_ty.clone(), range) } - (TypeKind::Dict(key_ty, val_ty), TypeKind::Dict(expected_key_ty, expected_val_ty)) => { - self.check_type(key_ty.clone(), expected_key_ty.clone(), pos) - && self.check_type(val_ty.clone(), expected_val_ty.clone(), pos) + ( + TypeKind::Dict(DictType { key_ty, val_ty, .. }), + TypeKind::Dict(DictType { + key_ty: expected_key_ty, + val_ty: expected_val_ty, + .. + }), + ) => { + self.check_type(key_ty.clone(), expected_key_ty.clone(), range) + && self.check_type(val_ty.clone(), expected_val_ty.clone(), range) } - (TypeKind::Dict(key_ty, val_ty), TypeKind::Schema(schema_ty)) => { - self.dict_assignable_to_schema(key_ty.clone(), val_ty.clone(), schema_ty, pos) + (TypeKind::Dict(DictType { key_ty, val_ty, .. }), TypeKind::Schema(schema_ty)) => { + self.dict_assignable_to_schema(key_ty.clone(), val_ty.clone(), schema_ty, range) } (TypeKind::Union(types), _) => types .iter() - .all(|ty| self.check_type(ty.clone(), expected_ty.clone(), pos)), + .all(|ty| self.check_type(ty.clone(), expected_ty.clone(), range)), (_, TypeKind::Union(types)) => types .iter() - .any(|expected_ty| self.check_type(ty.clone(), expected_ty.clone(), pos)), + .any(|expected_ty| self.check_type(ty.clone(), expected_ty.clone(), range)), _ => assignable_to(ty, expected_ty), } } @@ -143,46 +231,110 @@ impl<'ctx> Resolver<'ctx> { /// Do relaxed schema check key and value type check. pub fn dict_assignable_to_schema( &mut self, - key_ty: Rc, - val_ty: Rc, + key_ty: TypeRef, + val_ty: TypeRef, schema_ty: &SchemaType, - pos: &Position, + range: &Range, ) -> bool { if let Some(index_signature) = &schema_ty.index_signature { - if !assignable_to(val_ty.clone(), index_signature.val_ty.clone()) { + if !self.check_type(val_ty.clone(), index_signature.val_ty.clone(), range) { self.handler.add_type_error( &format!( "expected schema index signature value type {}, got {}", index_signature.val_ty.ty_str(), val_ty.ty_str() ), - pos.clone(), + range.clone(), ); } if index_signature.any_other { - return assignable_to(key_ty, index_signature.key_ty.clone()) - && assignable_to(val_ty, index_signature.val_ty.clone()); + return self.check_type(key_ty, index_signature.key_ty.clone(), range) + && self.check_type(val_ty, index_signature.val_ty.clone(), range); } true } else { + // When assigning a dict type to an instance of a schema type, + // check whether the type of key value pair in dict matches the attribute type in the schema. + if let TypeKind::StrLit(key_name) = &key_ty.kind { + if let Some(attr_obj) = schema_ty.attrs.get(key_name) { + self.must_assignable_to( + val_ty.clone(), + attr_obj.ty.clone(), + range.clone(), + Some(attr_obj.range.clone()), + ); + return true; + } + } true } } - fn upgrade_named_ty_with_scope(&mut self, ty: Rc, pos: &Position) -> ResolvedResult { + fn upgrade_named_ty_with_scope( + &mut self, + ty: TypeRef, + range: &Range, + ty_node: Option<&ast::Node>, + ) -> ResolvedResult { match &ty.kind { TypeKind::List(item_ty) => { - Type::list_ref(self.upgrade_named_ty_with_scope(item_ty.clone(), pos)) + let mut inner_node = None; + if let Some(ty_node) = ty_node { + if let ast::Type::List(list_type) = &ty_node.node { + inner_node = list_type.inner_type.as_ref().map(|ty| ty.as_ref()) + } + }; + Type::list_ref(self.upgrade_named_ty_with_scope(item_ty.clone(), range, inner_node)) + } + TypeKind::Dict(DictType { + key_ty, + val_ty, + attrs, + }) => { + let mut key_node = None; + let mut value_node = None; + if let Some(ty_node) = ty_node { + if let ast::Type::Dict(dict_type) = &ty_node.node { + key_node = dict_type.key_type.as_ref().map(|ty| ty.as_ref()); + value_node = dict_type.value_type.as_ref().map(|ty| ty.as_ref()); + } + }; + Type::dict_ref_with_attrs( + self.upgrade_named_ty_with_scope(key_ty.clone(), range, key_node), + self.upgrade_named_ty_with_scope(val_ty.clone(), range, value_node), + attrs + .into_iter() + .map(|(key, attr)| { + ( + key.to_string(), + Attr { + ty: self.upgrade_named_ty_with_scope( + val_ty.clone(), + range, + None, + ), + range: attr.range.clone(), + }, + ) + }) + .collect(), + ) } - TypeKind::Dict(key_ty, val_ty) => Type::dict_ref( - self.upgrade_named_ty_with_scope(key_ty.clone(), pos), - self.upgrade_named_ty_with_scope(val_ty.clone(), pos), - ), TypeKind::Union(types) => Type::union_ref( &types .iter() - .map(|ty| self.upgrade_named_ty_with_scope(ty.clone(), pos)) - .collect::>>(), + .enumerate() + .map(|(index, ty)| { + let mut elem_node = None; + if let Some(ty_node) = ty_node { + if let ast::Type::Union(union_type) = &ty_node.node { + elem_node = + union_type.type_elements.get(index).map(|ty| ty.as_ref()) + } + }; + self.upgrade_named_ty_with_scope(ty.clone(), range, elem_node) + }) + .collect::>(), ), TypeKind::Named(ty_str) => { let ty_str = ty_str_replace_pkgpath(ty_str, &self.ctx.pkgpath); @@ -194,7 +346,7 @@ impl<'ctx> Resolver<'ctx> { }; if names.is_empty() { self.handler - .add_compile_error("missing type annotation", pos.clone()); + .add_compile_error("missing type annotation", range.clone()); return self.any_ty(); } let mut pkgpath = "".to_string(); @@ -207,11 +359,65 @@ impl<'ctx> Resolver<'ctx> { } } self.ctx.l_value = false; - self.resolve_var( + let tys = self.resolve_var( &names.iter().map(|n| n.to_string()).collect::>(), &pkgpath, - pos.clone(), - ) + range.clone(), + ); + + if let Some(ty_node) = ty_node { + if let ast::Type::Named(identifier) = &ty_node.node { + for (index, name) in identifier.names.iter().enumerate() { + self.node_ty_map + .insert(self.get_node_key(name.id.clone()), tys[index].clone()); + } + let ident_ty = tys.last().unwrap().clone(); + self.node_ty_map + .insert(self.get_node_key(ty_node.id.clone()), ident_ty.clone()); + } + }; + tys.last().unwrap().clone() + } + TypeKind::Function(fn_ty) => { + // Replace the type 'Named' to the real type in function params and return type + let mut params_ty = vec![]; + let mut ret_ty = Type::any_ref(); + if let Some(ty_node) = ty_node { + if let ast::Type::Function(fn_ast_type) = &ty_node.node { + if let Some(params_ast_ty) = fn_ast_type.params_ty.as_ref() { + for (ast_ty, ty) in params_ast_ty.iter().zip(fn_ty.params.iter()) { + params_ty.push(Parameter { + name: ty.name.clone(), + ty: self.upgrade_named_ty_with_scope( + ty.ty.clone(), + range, + Some(ast_ty.as_ref()), + ), + has_default: ty.has_default, + }); + } + } + + ret_ty = if let Some(ret_ast_ty) = fn_ast_type.ret_ty.as_ref() { + self.upgrade_named_ty_with_scope( + fn_ty.return_ty.clone(), + range, + Some(ret_ast_ty.as_ref()), + ) + } else { + Type::any_ref() + }; + } + }; + + Arc::new(Type::function( + fn_ty.self_ty.clone(), + ret_ty, + params_ty.as_slice(), + &fn_ty.doc, + fn_ty.is_variadic, + fn_ty.kw_only_index, + )) } _ => ty.clone(), } diff --git a/kclvm/sema/src/resolver/ty_alias.rs b/kclvm/sema/src/resolver/ty_alias.rs index d1a4887e5..7139107f1 100644 --- a/kclvm/sema/src/resolver/ty_alias.rs +++ b/kclvm/sema/src/resolver/ty_alias.rs @@ -1,4 +1,5 @@ use indexmap::IndexMap; +use kclvm_ast::ast::Node; use kclvm_ast::walker::MutSelfMutWalker; use kclvm_ast::{ast, walk_if_mut, walk_list_mut}; @@ -24,15 +25,15 @@ impl<'ctx> MutSelfMutWalker<'ctx> for TypeAliasTransformer { let value = &mut schema_index_signature.node.value; if let Some(type_alias) = self .type_alias_mapping - .get(&schema_index_signature.node.key_type.node) + .get(&schema_index_signature.node.key_ty.node.to_string()) { - schema_index_signature.node.key_type.node = type_alias.clone(); + schema_index_signature.node.key_ty.node = type_alias.clone().into(); } if let Some(type_alias) = self .type_alias_mapping - .get(&schema_index_signature.node.value_type.node) + .get(&schema_index_signature.node.value_ty.node.to_string()) { - schema_index_signature.node.value_type.node = type_alias.clone(); + schema_index_signature.node.value_ty.node = type_alias.clone().into(); } walk_if_mut!(self, walk_expr, value); } @@ -43,15 +44,18 @@ impl<'ctx> MutSelfMutWalker<'ctx> for TypeAliasTransformer { } fn walk_schema_attr(&mut self, schema_attr: &'ctx mut ast::SchemaAttr) { // walk_list_mut!(self, walk_call_expr, schema_attr.decorators); - if let Some(type_alias) = self.type_alias_mapping.get(&schema_attr.type_str.node) { - schema_attr.type_str.node = type_alias.clone(); + if let Some(type_alias) = self + .type_alias_mapping + .get(&schema_attr.ty.node.to_string()) + { + schema_attr.ty.node = type_alias.clone().into(); } walk_if_mut!(self, walk_expr, schema_attr.value); } fn walk_assign_stmt(&mut self, assign_stmt: &'ctx mut ast::AssignStmt) { - if let Some(ty_str) = &mut assign_stmt.type_annotation { - if let Some(type_alias) = self.type_alias_mapping.get(&ty_str.node) { - ty_str.node = type_alias.clone(); + if let Some(ty) = &mut assign_stmt.ty { + if let Some(type_alias) = self.type_alias_mapping.get(&ty.node.to_string()) { + ty.node = type_alias.clone().into(); } } self.walk_expr(&mut assign_stmt.value.node); @@ -63,17 +67,20 @@ impl<'ctx> MutSelfMutWalker<'ctx> for TypeAliasTransformer { fn walk_lambda_expr(&mut self, lambda_expr: &'ctx mut ast::LambdaExpr) { walk_if_mut!(self, walk_arguments, lambda_expr.args); walk_list_mut!(self, walk_stmt, lambda_expr.body); - if let Some(ty_str) = &mut lambda_expr.return_type_str { - if let Some(type_alias) = self.type_alias_mapping.get(ty_str) { - *ty_str = type_alias.clone(); + if let Some(ty) = &mut lambda_expr.return_ty { + if let Some(type_alias) = self.type_alias_mapping.get(&ty.node.to_string()) { + ty.node = type_alias.clone().into(); } } } fn walk_arguments(&mut self, arguments: &'ctx mut ast::Arguments) { walk_list_mut!(self, walk_identifier, arguments.args); - for type_annotation in (&mut arguments.type_annotation_list.iter_mut()).flatten() { - if let Some(type_alias) = self.type_alias_mapping.get(&type_annotation.node) { - type_annotation.node = type_alias.clone(); + for type_annotation in (&mut arguments.ty_list.iter_mut()).flatten() { + if let Some(type_alias) = self + .type_alias_mapping + .get(&type_annotation.node.to_string()) + { + type_annotation.node = type_alias.clone().into(); } } for default in arguments.defaults.iter_mut() { @@ -98,11 +105,24 @@ impl<'ctx> MutSelfMutWalker<'ctx> for TypeAliasTransformer { // ``` if self.pkgpath != &pkgpath[1..] { identifier.pkgpath = pkgpath; - identifier.names = vec![splits[1].to_string(), splits[0].to_string()]; + let mut first_node = identifier.names[0].clone(); + first_node.node = splits[1].to_string(); + let mut second_node = identifier.names[0].clone(); + second_node.node = splits[0].to_string(); + identifier.names = vec![first_node, second_node]; } } else { let names = type_alias.split('.').collect::>(); - identifier.names = names.iter().map(|n| n.to_string()).collect(); + let new_names: Vec> = names + .iter() + .zip(&identifier.names) + .map(|(name, pos_name)| { + let mut new_name = pos_name.clone(); + new_name.node = name.to_string(); + new_name.clone() + }) + .collect(); + identifier.names = new_names; } } } @@ -121,7 +141,7 @@ fn fix_type_alias_identifier<'ctx>( } /// Process type alias. -pub fn process_program_type_alias( +pub fn type_alias_pass( program: &mut ast::Program, type_alias_mapping: IndexMap>, ) { diff --git a/kclvm/sema/src/resolver/ty_erasure.rs b/kclvm/sema/src/resolver/ty_erasure.rs new file mode 100644 index 000000000..0d0f269ef --- /dev/null +++ b/kclvm/sema/src/resolver/ty_erasure.rs @@ -0,0 +1,59 @@ +use kclvm_ast::ast; +use kclvm_ast::walker::MutSelfMutWalker; + +#[derive(Default)] +struct TypeErasureTransformer; +const FUNCTION: &str = "function"; + +impl<'ctx> MutSelfMutWalker<'ctx> for TypeErasureTransformer { + fn walk_schema_stmt(&mut self, schema_stmt: &'ctx mut ast::SchemaStmt) { + if let Some(schema_index_signature) = schema_stmt.index_signature.as_deref_mut() { + if let kclvm_ast::ast::Type::Function(_) = + &mut schema_index_signature.node.value_ty.node + { + schema_index_signature.node.value_ty.node = FUNCTION.to_string().into(); + } + } + for item in schema_stmt.body.iter_mut() { + if let kclvm_ast::ast::Stmt::SchemaAttr(attr) = &mut item.node { + self.walk_schema_attr(attr); + } + } + } + + fn walk_schema_attr(&mut self, schema_attr: &'ctx mut ast::SchemaAttr) { + if let kclvm_ast::ast::Type::Function(_) = schema_attr.ty.as_ref().node { + schema_attr.ty.node = FUNCTION.to_string().into(); + } + } + fn walk_assign_stmt(&mut self, assign_stmt: &'ctx mut ast::AssignStmt) { + if let Some(ty) = &mut assign_stmt.ty { + if let kclvm_ast::ast::Type::Function(_) = ty.as_ref().node { + if let Some(ty_anno) = &mut assign_stmt.ty { + ty_anno.node = FUNCTION.to_string().into(); + } + } + } + } + fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx mut ast::TypeAliasStmt) { + if let kclvm_ast::ast::Type::Function(_) = type_alias_stmt.ty.as_ref().node { + type_alias_stmt.type_value.node = FUNCTION.to_string(); + } + } + fn walk_arguments(&mut self, arguments: &'ctx mut ast::Arguments) { + for ty in (&mut arguments.ty_list.iter_mut()).flatten() { + if let kclvm_ast::ast::Type::Function(_) = ty.as_ref().node { + ty.node = FUNCTION.to_string().into(); + } + } + } +} + +/// Run a pass on AST and change the function type to the `Named("function")` type +pub fn type_func_erasure_pass<'ctx>(program: &'ctx mut ast::Program) { + for (_, modules) in program.pkgs.iter_mut() { + for module in modules.iter_mut() { + TypeErasureTransformer::default().walk_module(module); + } + } +} diff --git a/kclvm/sema/src/resolver/var.rs b/kclvm/sema/src/resolver/var.rs index 5f1aeb579..a45f29d93 100644 --- a/kclvm/sema/src/resolver/var.rs +++ b/kclvm/sema/src/resolver/var.rs @@ -1,6 +1,7 @@ use crate::resolver::Resolver; -use crate::ty::TypeKind; use indexmap::IndexMap; +use kclvm_ast::pos::GetPos; +use kclvm_error::diagnostic::Range; use kclvm_error::*; use super::node::ResolvedResult; @@ -12,12 +13,12 @@ impl<'ctx> Resolver<'ctx> { &mut self, names: &[String], pkgpath: &str, - pos: Position, - ) -> ResolvedResult { + range: Range, + ) -> Vec { if !pkgpath.is_empty() && self.ctx.l_value { self.handler.add_compile_error( "only schema and dict object can be updated attribute", - pos.clone(), + range.clone(), ); } if names.len() == 1 { @@ -25,18 +26,42 @@ impl<'ctx> Resolver<'ctx> { let scope_schema_ty = self.ctx.schema.clone(); if let Some(schema_ty) = &scope_schema_ty { let mut schema_ty = schema_ty.borrow_mut(); + // Find attribute type in the schema. let ty = schema_ty.get_type_of_attr(name); - // Load from schema if in schema + // Load from schema if the variable in schema if !self.ctx.l_value { + // Find the type from from local and global scope. let scope_ty = self.find_type_in_scope(name); if self.ctx.local_vars.contains(name) { - return scope_ty.map_or(self.any_ty(), |ty| ty); - } else if let Some(ref ty) = ty { + return vec![scope_ty.map_or(self.any_ty(), |ty| ty)]; + } + // If it is a schema attribute, return the attribute type. + if let Some(ref ty) = ty { if !ty.is_any() { - return ty.clone(); + return vec![ty.clone()]; } } - scope_ty.map_or(self.any_ty(), |ty| ty) + // Find from mixin schemas of a non-mixin schema + if ty.is_none() && !schema_ty.is_mixin { + for mixin in &schema_ty.mixins { + if let Some(ty) = mixin.get_type_of_attr(name) { + return vec![ty.clone()]; + } + } + } + // If the variable is not found in a schema but not a schema mixin or rule, + // raise an error and return an any type. + // At present, retaining certain dynamic characteristics for mixins and rules + // requires further consideration of their semantics. + if ty.is_none() + && scope_ty.is_none() + && !schema_ty.is_mixin + && !schema_ty.is_rule + { + vec![self.lookup_type_from_scope(name, range)] + } else { + vec![scope_ty.map_or(self.any_ty(), |ty| ty)] + } } // Store else { @@ -45,26 +70,24 @@ impl<'ctx> Resolver<'ctx> { name, ScopeObject { name: name.to_string(), - start: pos.clone(), - end: pos.clone(), + start: range.0.clone(), + end: range.1.clone(), ty: self.any_ty(), kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); if ty.is_none() { schema_ty.set_type_of_attr(name, self.any_ty()) } - return self.any_ty(); + return vec![self.any_ty()]; } - // FIXME: self.check_config_attr(name, &pos, &schema_ty); - ty.map_or(self.lookup_type_from_scope(name, pos.clone()), |ty| ty) + vec![ty.map_or(self.lookup_type_from_scope(name, range.clone()), |ty| ty)] } } else { // Load from schema if in schema if !self.ctx.l_value { - self.lookup_type_from_scope(name, pos) + vec![self.lookup_type_from_scope(name, range)] } // Store else { @@ -73,17 +96,16 @@ impl<'ctx> Resolver<'ctx> { name, ScopeObject { name: name.to_string(), - start: pos.clone(), - end: pos.clone(), + start: range.0.clone(), + end: range.1.clone(), ty: self.any_ty(), kind: ScopeObjectKind::Variable, - used: false, doc: None, }, ); - return self.any_ty(); + return vec![self.any_ty()]; } - self.lookup_type_from_scope(name, pos) + vec![self.lookup_type_from_scope(name, range)] } } } else if !names.is_empty() { @@ -91,53 +113,62 @@ impl<'ctx> Resolver<'ctx> { // It should be recursively search whole scope to lookup scope object, not the current scope.element. if !pkgpath.is_empty() { if let Some(obj) = self.scope.borrow().lookup(pkgpath) { - obj.borrow_mut().used = true; + if let ScopeObjectKind::Module(m) = &mut obj.borrow_mut().kind { + for (stmt, used) in m.import_stmts.iter_mut() { + if stmt.get_pos().filename == range.0.filename { + *used = true; + } + } + } } } // Load type - let mut ty = self.resolve_var( + let mut tys = self.resolve_var( &[if !pkgpath.is_empty() { pkgpath.to_string() } else { names[0].clone() }], pkgpath, - pos.clone(), + range.clone(), ); + let mut ty = tys[0].clone(); + for name in &names[1..] { // Store and config attr check if self.ctx.l_value { - if let TypeKind::Schema(schema_ty) = &ty.kind { - self.check_config_attr(name, &pos, schema_ty); - } + self.must_check_config_attr(name, &range, &ty); } - ty = self.load_attr(ty, name, pos.clone()) + ty = self.load_attr(ty, name, range.clone()); + tys.push(ty.clone()); } - ty + tys } else { self.handler - .add_compile_error("missing variable", pos.clone()); - self.any_ty() + .add_compile_error("missing variable", range.clone()); + vec![self.any_ty()] } } /// Resolve an unique key in the current package. - pub(crate) fn resolve_unique_key(&mut self, name: &str, pos: &Position) { + pub(crate) fn resolve_unique_key(&mut self, name: &str, range: &Range) { if !self.contains_global_name(name) && self.scope_level == 0 { - self.insert_global_name(name, pos); + self.insert_global_name(name, range); } else { let mut msgs = vec![Message { - pos: pos.clone(), + range: range.clone(), style: Style::LineAndColumn, message: format!("Unique key error name '{}'", name), note: None, + suggested_replacement: None, }]; if let Some(pos) = self.get_global_name_pos(name) { msgs.push(Message { - pos: pos.clone(), + range: pos.clone(), style: Style::LineAndColumn, message: format!("The variable '{}' is declared here", name), note: None, + suggested_replacement: None, }); } self.handler.add_error(ErrorKind::UniqueKeyError, &msgs); @@ -145,14 +176,14 @@ impl<'ctx> Resolver<'ctx> { } /// Insert global name in the current package. - pub(crate) fn insert_global_name(&mut self, name: &str, pos: &Position) { + pub(crate) fn insert_global_name(&mut self, name: &str, range: &Range) { match self.ctx.global_names.get_mut(&self.ctx.pkgpath) { Some(mapping) => { - mapping.insert(name.to_string(), pos.clone()); + mapping.insert(name.to_string(), range.clone()); } None => { let mut mapping = IndexMap::default(); - mapping.insert(name.to_string(), pos.clone()); + mapping.insert(name.to_string(), range.clone()); self.ctx .global_names .insert(self.ctx.pkgpath.clone(), mapping); @@ -169,7 +200,7 @@ impl<'ctx> Resolver<'ctx> { } /// Get global name position in the current package. - pub(crate) fn get_global_name_pos(&mut self, name: &str) -> Option<&Position> { + pub(crate) fn get_global_name_pos(&mut self, name: &str) -> Option<&Range> { match self.ctx.global_names.get_mut(&self.ctx.pkgpath) { Some(mapping) => mapping.get(name), None => None, diff --git a/kclvm/sema/src/ty/constants.rs b/kclvm/sema/src/ty/constants.rs index 01ead742e..b433c28ec 100644 --- a/kclvm/sema/src/ty/constants.rs +++ b/kclvm/sema/src/ty/constants.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::sync::Arc; use super::{Type, TypeFlags, TypeKind}; @@ -57,24 +57,24 @@ pub const TYPES_MAPPING: Lazy> = Lazy::new(|| { mapping.insert(STR_TYPE_STR.to_string(), Type::STR); mapping.insert(BOOL_TYPE_STR.to_string(), Type::BOOL); mapping.insert(ANY_TYPE_STR.to_string(), Type::ANY); - mapping.insert("[]".to_string(), Type::list(Rc::new(Type::ANY))); - mapping.insert("[any]".to_string(), Type::list(Rc::new(Type::ANY))); - mapping.insert("[str]".to_string(), Type::list(Rc::new(Type::STR))); + mapping.insert("[]".to_string(), Type::list(Arc::new(Type::ANY))); + mapping.insert("[any]".to_string(), Type::list(Arc::new(Type::ANY))); + mapping.insert("[str]".to_string(), Type::list(Arc::new(Type::STR))); mapping.insert( "{:}".to_string(), - Type::dict(Rc::new(Type::ANY), Rc::new(Type::ANY)), + Type::dict(Arc::new(Type::ANY), Arc::new(Type::ANY)), ); mapping.insert( "{str:}".to_string(), - Type::dict(Rc::new(Type::STR), Rc::new(Type::ANY)), + Type::dict(Arc::new(Type::STR), Arc::new(Type::ANY)), ); mapping.insert( "{str:any}".to_string(), - Type::dict(Rc::new(Type::STR), Rc::new(Type::ANY)), + Type::dict(Arc::new(Type::STR), Arc::new(Type::ANY)), ); mapping.insert( "{str:str}".to_string(), - Type::dict(Rc::new(Type::STR), Rc::new(Type::STR)), + Type::dict(Arc::new(Type::STR), Arc::new(Type::STR)), ); mapping }); diff --git a/kclvm/sema/src/ty/constructor.rs b/kclvm/sema/src/ty/constructor.rs index caa773690..58ae224f5 100644 --- a/kclvm/sema/src/ty/constructor.rs +++ b/kclvm/sema/src/ty/constructor.rs @@ -1,23 +1,48 @@ use super::*; impl Type { + /// Construct an int type reference. + #[inline] + pub fn int_ref() -> TypeRef { + Arc::new(Type::INT) + } + /// Construct a float type reference. + #[inline] + pub fn float_ref() -> TypeRef { + Arc::new(Type::FLOAT) + } + /// Construct a bool type reference. + #[inline] + pub fn bool_ref() -> TypeRef { + Arc::new(Type::BOOL) + } + /// Construct a str type reference. + #[inline] + pub fn str_ref() -> TypeRef { + Arc::new(Type::STR) + } + /// Construct a any type reference. + #[inline] + pub fn any_ref() -> TypeRef { + Arc::new(Type::ANY) + } /// Construct a union type #[inline] - pub fn union(types: &[Rc]) -> Type { + pub fn union(types: &[TypeRef]) -> Type { Type { kind: TypeKind::Union(types.to_owned()), flags: TypeFlags::UNION, is_type_alias: false, } } - /// Construct a union type ref + /// Construct an union type reference. #[inline] - pub fn union_ref(types: &[Rc]) -> Rc { - Rc::new(Self::union(types)) + pub fn union_ref(types: &[TypeRef]) -> TypeRef { + Arc::new(Self::union(types)) } /// Construct a list type #[inline] - pub fn list(item_ty: Rc) -> Type { + pub fn list(item_ty: TypeRef) -> Type { Type { kind: TypeKind::List(item_ty), flags: TypeFlags::LIST, @@ -26,22 +51,52 @@ impl Type { } /// Construct a list type ref #[inline] - pub fn list_ref(item_ty: Rc) -> Rc { - Rc::new(Self::list(item_ty)) + pub fn list_ref(item_ty: TypeRef) -> TypeRef { + Arc::new(Self::list(item_ty)) } /// Construct a dict type #[inline] - pub fn dict(key_ty: Rc, val_ty: Rc) -> Type { + pub fn dict(key_ty: TypeRef, val_ty: TypeRef) -> Type { Type { - kind: TypeKind::Dict(key_ty, val_ty), + kind: TypeKind::Dict(DictType { + key_ty, + val_ty, + attrs: IndexMap::new(), + }), flags: TypeFlags::DICT, is_type_alias: false, } } /// Construct a dict type ref #[inline] - pub fn dict_ref(key_ty: Rc, val_ty: Rc) -> Rc { - Rc::new(Self::dict(key_ty, val_ty)) + pub fn dict_ref(key_ty: TypeRef, val_ty: TypeRef) -> TypeRef { + Arc::new(Self::dict(key_ty, val_ty)) + } + /// Construct a dict type with attrs + #[inline] + pub fn dict_with_attrs( + key_ty: TypeRef, + val_ty: TypeRef, + attrs: IndexMap, + ) -> Type { + Type { + kind: TypeKind::Dict(DictType { + key_ty, + val_ty, + attrs, + }), + flags: TypeFlags::DICT, + is_type_alias: false, + } + } + /// Construct a dict type reference with attrs + #[inline] + pub fn dict_ref_with_attrs( + key_ty: TypeRef, + val_ty: TypeRef, + attrs: IndexMap, + ) -> TypeRef { + Arc::new(Self::dict_with_attrs(key_ty, val_ty, attrs)) } /// Construct a bool literal type. #[inline] @@ -118,8 +173,8 @@ impl Type { /// Construct a function type. #[inline] pub fn function( - self_ty: Option>, - return_ty: Rc, + self_ty: Option, + return_ty: TypeRef, params: &[Parameter], doc: &str, is_variadic: bool, @@ -159,20 +214,18 @@ impl Type { } } /// Construct a iterable type - pub fn iterable() -> Rc { - Rc::new(Type::union(&[ - Rc::new(Type::STR), - Rc::new(Type::dict(Rc::new(Type::ANY), Rc::new(Type::ANY))), - Rc::new(Type::list(Rc::new(Type::ANY))), + #[inline] + pub fn iterable() -> TypeRef { + Arc::new(Type::union(&[ + Arc::new(Type::STR), + Arc::new(Type::dict(Arc::new(Type::ANY), Arc::new(Type::ANY))), + Arc::new(Type::list(Arc::new(Type::ANY))), ])) } /// Construct a number type - pub fn number() -> Rc { - Rc::new(Type::union(&[ - Rc::new(Type::INT), - Rc::new(Type::FLOAT), - Rc::new(Type::STR), - ])) + #[inline] + pub fn number() -> TypeRef { + Type::union_ref(&[Type::int_ref(), Type::float_ref(), Type::bool_ref()]) } /// Whether is a any type. #[inline] @@ -310,7 +363,7 @@ impl Type { | TypeKind::Str | TypeKind::StrLit(_) | TypeKind::List(_) - | TypeKind::Dict(_, _) + | TypeKind::Dict(DictType { .. }) | TypeKind::Union(_) | TypeKind::Schema(_) | TypeKind::NumberMultiplier(_) diff --git a/kclvm/sema/src/ty/context.rs b/kclvm/sema/src/ty/context.rs index 7d2a1a95d..66ad71c01 100644 --- a/kclvm/sema/src/ty/context.rs +++ b/kclvm/sema/src/ty/context.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use std::rc::Rc; +use std::sync::Arc; -use super::{sup, Type, TypeFlags, TypeKind}; +use super::{sup, DictType, Type, TypeFlags, TypeKind, TypeRef}; use petgraph::algo::is_cyclic_directed; use petgraph::graph::{DiGraph, NodeIndex}; @@ -16,13 +16,13 @@ pub struct TypeContext { #[derive(Debug)] pub struct BuiltinTypes { - pub any: Rc, - pub bool: Rc, - pub int: Rc, - pub float: Rc, - pub str: Rc, - pub void: Rc, - pub none: Rc, + pub any: TypeRef, + pub bool: TypeRef, + pub int: TypeRef, + pub float: TypeRef, + pub str: TypeRef, + pub void: TypeRef, + pub none: TypeRef, } impl Default for TypeContext { @@ -37,13 +37,13 @@ impl TypeContext { TypeContext { dep_graph: DiGraph::new(), builtin_types: BuiltinTypes { - any: Rc::new(Type::ANY), - bool: Rc::new(Type::BOOL), - int: Rc::new(Type::INT), - float: Rc::new(Type::FLOAT), - str: Rc::new(Type::STR), - void: Rc::new(Type::VOID), - none: Rc::new(Type::NONE), + any: Arc::new(Type::ANY), + bool: Arc::new(Type::BOOL), + int: Arc::new(Type::INT), + float: Arc::new(Type::FLOAT), + str: Arc::new(Type::STR), + void: Arc::new(Type::VOID), + none: Arc::new(Type::NONE), }, node_index_map: HashMap::new(), } @@ -77,7 +77,7 @@ impl TypeContext { /// Convert the literal union type to its variable type /// e.g., 1|2 -> int, 's'|'ss' -> str. - pub fn literal_union_type_to_variable_type(&self, ty: Rc) -> Rc { + pub fn literal_union_type_to_variable_type(&self, ty: TypeRef) -> TypeRef { if ty.is_union() { self.infer_to_variable_type(ty) } else { @@ -87,7 +87,7 @@ impl TypeContext { /// Judge a type kind in the type kind list or the union /// type kinds are all in the type kind. - pub fn is_kind_type_or_kind_union_type(&self, ty: Rc, flags: &[TypeFlags]) -> bool { + pub fn is_kind_type_or_kind_union_type(&self, ty: TypeRef, flags: &[TypeFlags]) -> bool { match &ty.kind { TypeKind::Union(types) => types .iter() @@ -97,7 +97,7 @@ impl TypeContext { } #[inline] - pub fn is_number_type_or_number_union_type(&self, ty: Rc) -> bool { + pub fn is_number_type_or_number_union_type(&self, ty: TypeRef) -> bool { self.is_kind_type_or_kind_union_type( ty, &[TypeFlags::INT, TypeFlags::FLOAT, TypeFlags::BOOL], @@ -105,17 +105,17 @@ impl TypeContext { } #[inline] - pub fn is_config_type_or_config_union_type(&self, ty: Rc) -> bool { + pub fn is_config_type_or_config_union_type(&self, ty: TypeRef) -> bool { self.is_kind_type_or_kind_union_type(ty, &[TypeFlags::DICT, TypeFlags::SCHEMA]) } #[inline] - pub fn is_str_type_or_str_union_type(&self, ty: Rc) -> bool { + pub fn is_str_type_or_str_union_type(&self, ty: TypeRef) -> bool { self.is_kind_type_or_kind_union_type(ty, &[TypeFlags::STR]) } #[inline] - pub fn is_primitive_type_or_primitive_union_type(&self, ty: Rc) -> bool { + pub fn is_primitive_type_or_primitive_union_type(&self, ty: TypeRef) -> bool { self.is_kind_type_or_kind_union_type( ty, &[ @@ -128,7 +128,7 @@ impl TypeContext { } #[inline] - pub fn is_mul_val_type_or_mul_val_union_type(&self, ty: Rc) -> bool { + pub fn is_mul_val_type_or_mul_val_union_type(&self, ty: TypeRef) -> bool { self.is_kind_type_or_kind_union_type( ty, &[ @@ -143,19 +143,19 @@ impl TypeContext { /// Convert type to the real type annotation #[inline] - pub fn into_type_annotation_str(&self, ty: Rc) -> String { + pub fn into_type_annotation_str(&self, ty: TypeRef) -> String { ty.into_type_annotation_str() } } pub trait TypeInferMethods { /// Infer the value type to the variable type" - fn infer_to_variable_type(&self, ty: Rc) -> Rc; + fn infer_to_variable_type(&self, ty: TypeRef) -> TypeRef; } impl TypeInferMethods for TypeContext { /// Infer the value type to the variable type" - fn infer_to_variable_type(&self, ty: Rc) -> Rc { + fn infer_to_variable_type(&self, ty: TypeRef) -> TypeRef { match &ty.kind { // None/Undefined type to any type e.g., None -> any TypeKind::None => self.builtin_types.any.clone(), @@ -166,15 +166,20 @@ impl TypeInferMethods for TypeContext { TypeKind::StrLit(_) => self.builtin_types.str.clone(), TypeKind::List(item_ty) => Type::list_ref(self.infer_to_variable_type(item_ty.clone())), // Dict type e.g., {str:1|2} -> {str:int} - TypeKind::Dict(key_ty, val_ty) => Type::dict_ref( + TypeKind::Dict(DictType { + key_ty, + val_ty, + attrs, + }) => Type::dict_ref_with_attrs( self.infer_to_variable_type(key_ty.clone()), self.infer_to_variable_type(val_ty.clone()), + attrs.clone(), ), // Union type e.g., 1|2|"s" -> int|str TypeKind::Union(types) => sup(&types .iter() .map(|ty| self.infer_to_variable_type(ty.clone())) - .collect::>>()), + .collect::>()), _ => ty.clone(), } } diff --git a/kclvm/sema/src/ty/into.rs b/kclvm/sema/src/ty/into.rs index bfb090a11..f73fb9327 100644 --- a/kclvm/sema/src/ty/into.rs +++ b/kclvm/sema/src/ty/into.rs @@ -3,7 +3,7 @@ use super::*; impl Type { /// Downcast ty into the list type. #[inline] - pub fn list_item_ty(&self) -> Rc { + pub fn list_item_ty(&self) -> TypeRef { match &self.kind { TypeKind::List(item_ty) => item_ty.clone(), _ => bug!("invalid list type {}", self.ty_str()), @@ -11,33 +11,35 @@ impl Type { } /// Downcast ty into the dict entry type. #[inline] - pub fn dict_entry_ty(&self) -> (Rc, Rc) { + pub fn dict_entry_ty(&self) -> (TypeRef, TypeRef) { match &self.kind { - TypeKind::Dict(key_ty, val_ty) => (key_ty.clone(), val_ty.clone()), + TypeKind::Dict(DictType { key_ty, val_ty, .. }) => (key_ty.clone(), val_ty.clone()), _ => bug!("invalid dict type {}", self.ty_str()), } } /// Downcast ty into the config key type. #[inline] - pub fn config_key_ty(&self) -> Rc { + pub fn config_key_ty(&self) -> TypeRef { match &self.kind { - TypeKind::Dict(key_ty, _) => key_ty.clone(), + TypeKind::Dict(DictType { key_ty, .. }) => key_ty.clone(), TypeKind::Schema(schema_ty) => schema_ty.key_ty(), _ => bug!("invalid config type {}", self.ty_str()), } } /// Downcast ty into the config value type. #[inline] - pub fn config_val_ty(&self) -> Rc { + pub fn config_val_ty(&self) -> TypeRef { match &self.kind { - TypeKind::Dict(_, val_ty) => val_ty.clone(), + TypeKind::Dict(DictType { + key_ty: _, val_ty, .. + }) => val_ty.clone(), TypeKind::Schema(schema_ty) => schema_ty.val_ty(), _ => bug!("invalid config type {}", self.ty_str()), } } /// Get types from the union type. #[inline] - pub fn union_types(&self) -> Vec> { + pub fn union_types(&self) -> Vec { match &self.kind { TypeKind::Union(types) => types.clone(), _ => bug!("invalid {} into union type", self.ty_str()), @@ -51,6 +53,14 @@ impl Type { _ => bug!("invalid type {} into schema type", self.ty_str()), } } + /// Into function type. + #[inline] + pub fn into_func_type(&self) -> FunctionType { + match &self.kind { + TypeKind::Function(func_ty) => func_ty.clone(), + _ => bug!("invalid type {} into function type", self.ty_str()), + } + } /// Into number multiplier type. #[inline] pub fn into_number_multiplier(&self) -> NumberMultiplierType { @@ -79,7 +89,7 @@ impl Type { } TypeKind::StrLit(v) => format!("\"{}\"", v.replace('"', "\\\"")), TypeKind::List(item_ty) => format!("[{}]", item_ty.into_type_annotation_str()), - TypeKind::Dict(key_ty, val_ty) => { + TypeKind::Dict(DictType { key_ty, val_ty, .. }) => { format!( "{{{}:{}}}", key_ty.into_type_annotation_str(), @@ -90,7 +100,7 @@ impl Type { .iter() .map(|ty| ty.into_type_annotation_str()) .collect::>() - .join("|"), + .join(" | "), TypeKind::Schema(schema_ty) => schema_ty.ty_str_with_pkgpath(), TypeKind::NumberMultiplier(number_multiplier) => { if number_multiplier.is_literal { @@ -104,6 +114,7 @@ impl Type { NUMBER_MULTIPLIER_PKG_TYPE_STR.to_string() } } + TypeKind::Function(fn_ty) => fn_ty.ty_str(), _ => self.ty_str(), } } @@ -124,28 +135,31 @@ impl From for Type { list_ty .inner_type .as_ref() - .map_or(Rc::new(Type::ANY), |ty| Rc::new(ty.node.clone().into())), + .map_or(Arc::new(Type::ANY), |ty| Arc::new(ty.node.clone().into())), ), ast::Type::Dict(dict_ty) => Type::dict( dict_ty .key_type .as_ref() - .map_or(Rc::new(Type::ANY), |ty| Rc::new(ty.node.clone().into())), + .map_or(Arc::new(Type::ANY), |ty| Arc::new(ty.node.clone().into())), dict_ty .value_type .as_ref() - .map_or(Rc::new(Type::ANY), |ty| Rc::new(ty.node.clone().into())), + .map_or(Arc::new(Type::ANY), |ty| Arc::new(ty.node.clone().into())), ), ast::Type::Union(union_ty) => Type::union( &union_ty .type_elements .iter() - .map(|ty| Rc::new(ty.node.clone().into())) - .collect::>>(), + .map(|ty| Arc::new(ty.node.clone().into())) + .collect::>(), ), ast::Type::Literal(literal_ty) => match literal_ty { ast::LiteralType::Bool(v) => Type::bool_lit(v), - ast::LiteralType::Int(v, suffix_option) => match suffix_option { + ast::LiteralType::Int(ast::IntLiteralType { + value: v, + suffix: suffix_option, + }) => match suffix_option { Some(suffix) => Type::number_multiplier( kclvm_runtime::cal_num(v, &suffix.value()), v, @@ -156,6 +170,29 @@ impl From for Type { ast::LiteralType::Float(v) => Type::float_lit(v), ast::LiteralType::Str(v) => Type::str_lit(&v), }, + // Ast::function => Sema::function, + ast::Type::Function(func_ty) => Type::function( + None, + func_ty + .ret_ty + .as_ref() + .map_or(Arc::new(Type::ANY), |ty| Arc::new(ty.node.clone().into())), + func_ty + .params_ty + .map_or(vec![], |tys| { + tys.iter() + .map(|ty| Parameter { + name: "".to_string(), + ty: Arc::new(ty.node.clone().into()), + has_default: false, + }) + .collect::>() + }) + .as_slice(), + "", + false, + None, + ), } } } diff --git a/kclvm/sema/src/ty/mod.rs b/kclvm/sema/src/ty/mod.rs index bf77f043c..64b109f0a 100644 --- a/kclvm/sema/src/ty/mod.rs +++ b/kclvm/sema/src/ty/mod.rs @@ -6,21 +6,29 @@ pub mod parser; mod unify; mod walker; -use std::rc::Rc; +use std::collections::HashMap; +use std::sync::Arc; pub use constants::*; pub use context::{TypeContext, TypeInferMethods}; +use indexmap::IndexMap; use kclvm_ast::ast; use kclvm_ast::MAIN_PKG; +use kclvm_error::diagnostic::Range; use kclvm_error::Position; pub use unify::*; pub use walker::walk_type; -use indexmap::IndexMap; +use super::resolver::doc::Example; #[cfg(test)] mod tests; +/// TypeRef represents a reference to a type that exists to avoid copying types everywhere affecting +/// performance. For example, for two instances that are both integer types, there is actually no +/// difference between them. +pub type TypeRef = Arc; + #[derive(Debug, Clone, PartialEq)] pub struct Type { // The type kind. @@ -32,6 +40,8 @@ pub struct Type { flags: TypeFlags, } +unsafe impl Send for Type {} + impl Type { /// Whether the type contains the flag. #[inline] @@ -44,7 +54,17 @@ impl Type { TypeKind::None => NONE_TYPE_STR.to_string(), TypeKind::Any => ANY_TYPE_STR.to_string(), TypeKind::Bool => BOOL_TYPE_STR.to_string(), - TypeKind::BoolLit(v) => format!("{}({})", BOOL_TYPE_STR, v), + TypeKind::BoolLit(v) => { + format!( + "{}({})", + BOOL_TYPE_STR, + if *v { + NAME_CONSTANT_TRUE + } else { + NAME_CONSTANT_FALSE + } + ) + } TypeKind::Int => INT_TYPE_STR.to_string(), TypeKind::IntLit(v) => format!("{}({})", INT_TYPE_STR, v), TypeKind::Float => FLOAT_TYPE_STR.to_string(), @@ -52,24 +72,35 @@ impl Type { TypeKind::Str => STR_TYPE_STR.to_string(), TypeKind::StrLit(v) => format!("{}({})", STR_TYPE_STR, v), TypeKind::List(item_ty) => format!("[{}]", item_ty.ty_str()), - TypeKind::Dict(key_ty, val_ty) => { + TypeKind::Dict(DictType { key_ty, val_ty, .. }) => { format!("{{{}:{}}}", key_ty.ty_str(), val_ty.ty_str()) } TypeKind::Union(types) => types .iter() .map(|ty| ty.ty_str()) .collect::>() - .join("|"), + .join(" | "), TypeKind::Schema(schema_ty) => schema_ty.name.to_string(), TypeKind::NumberMultiplier(number_multiplier) => number_multiplier.ty_str(), - TypeKind::Function(_) => FUNCTION_TYPE_STR.to_string(), + TypeKind::Function(func_ty) => func_ty.ty_str(), TypeKind::Void => VOID_TYPE_STR.to_string(), TypeKind::Module(module_ty) => format!("{} '{}'", MODULE_TYPE_STR, module_ty.pkgpath), TypeKind::Named(name) => name.to_string(), } } + + pub fn ty_doc(&self) -> Option { + match &self.kind { + TypeKind::Schema(schema) => Some(schema.doc.clone()), + TypeKind::Function(func) => Some(func.doc.clone()), + _ => None, + } + } } +unsafe impl Send for TypeKind {} +unsafe impl Sync for TypeKind {} + #[derive(Debug, Clone, PartialEq)] pub enum TypeKind { /// A primitive None name constant. @@ -93,11 +124,11 @@ pub enum TypeKind { /// A primitive string literal type. StrLit(String), /// The pointer of an array slice. Written as `[T]`. - List(Rc), + List(TypeRef), /// A map type. Written as `{kT, vT}`. - Dict(Rc, Rc), + Dict(DictType), /// A union type. Written as ty1 | ty2 | ... | tyn - Union(Vec>), + Union(Vec), /// A schema type. Schema(SchemaType), /// A number multiplier type. @@ -135,6 +166,19 @@ bitflags::bitflags! { } } +#[derive(Debug, Clone, PartialEq)] +pub struct DictType { + pub key_ty: TypeRef, + pub val_ty: TypeRef, + pub attrs: IndexMap, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Attr { + pub ty: TypeRef, + pub range: Range, +} + /// The schema type. #[derive(Debug, Clone, PartialEq)] pub struct SchemaType { @@ -146,6 +190,8 @@ pub struct SchemaType { pub filename: String, /// The schema definition document string. pub doc: String, + /// The code snippets of the schema usage examples + pub examples: HashMap, /// Indicates whether the schema is a type of a instance or /// a type (value). Besides, it is necessary to distinguish /// between a type instance and a type value, such as the following code: @@ -199,16 +245,18 @@ impl SchemaType { !self.is_instance && SCHEMA_MEMBER_FUNCTIONS.contains(&name) } - pub fn set_type_of_attr(&mut self, attr: &str, ty: Rc) { + pub fn set_type_of_attr(&mut self, attr: &str, ty: TypeRef) { match self.attrs.get_mut(attr) { Some(attr) => attr.ty = ty, None => { let schema_attr = SchemaAttr { is_optional: true, has_default: false, + default: None, ty, - pos: Position::dummy_pos(), + range: (Position::dummy_pos(), Position::dummy_pos()), doc: None, + decorators: vec![], }; self.attrs.insert(attr.to_string(), schema_attr); } @@ -216,7 +264,7 @@ impl SchemaType { } #[inline] - pub fn get_type_of_attr(&self, attr: &str) -> Option> { + pub fn get_type_of_attr(&self, attr: &str) -> Option { self.get_obj_of_attr(attr).map(|attr| attr.ty.clone()) } @@ -233,33 +281,62 @@ impl SchemaType { } } - pub fn key_ty(&self) -> Rc { - Rc::new(Type::STR) + pub fn key_ty(&self) -> TypeRef { + Arc::new(Type::STR) } - pub fn val_ty(&self) -> Rc { + pub fn val_ty(&self) -> TypeRef { if let Some(index_signature) = &self.index_signature { index_signature.val_ty.clone() } else { - Rc::new(Type::ANY) + Arc::new(Type::ANY) } } + + pub fn schema_ty_signature_str(&self) -> String { + let base: String = if let Some(base) = &self.base { + format!("({})", base.name) + } else { + "".to_string() + }; + let params: String = if self.func.params.is_empty() { + "".to_string() + } else { + format!( + "[{}]", + self.func + .params + .iter() + .map(|p| format!("{}: {}", p.name.clone(), p.ty.ty_str())) + .collect::>() + .join(", ") + ) + }; + format!("{}\n\nschema {}{}{}", self.pkgpath, self.name, params, base) + } } #[derive(Debug, Clone, PartialEq)] pub struct SchemaAttr { pub is_optional: bool, pub has_default: bool, - pub ty: Rc, - pub pos: Position, + /// `default` denotes the schema attribute optional value string. For example, + /// for the schema attribute definition `name?: str = "Alice"`, the value of + /// `default` is [Some("Alice")]. + /// For the schema attribute definition `name?: str`, the value of `default` + /// is [None]. + pub default: Option, + pub ty: TypeRef, + pub range: Range, pub doc: Option, + pub decorators: Vec, } #[derive(Debug, Clone, PartialEq)] pub struct SchemaIndexSignature { pub key_name: Option, - pub key_ty: Rc, - pub val_ty: Rc, + pub key_ty: TypeRef, + pub val_ty: TypeRef, pub any_other: bool, } @@ -294,11 +371,16 @@ pub enum ModuleKind { #[derive(Debug, Clone, PartialEq)] pub struct Decorator { + /// The decorator target e.g., the schema statement or schema attribute. pub target: DecoratorTarget, /// The decorator name. pub name: String, - /// The schema or attribute name of decorator dimension + /// The schema or attribute name of decorator dimension. pub key: String, + /// The decorator argument list values. + pub arguments: Vec, + /// The decorator keyword mapping values. + pub keywords: HashMap, } #[derive(Debug, Clone, PartialEq)] @@ -334,16 +416,57 @@ impl NumberMultiplierType { pub struct FunctionType { pub doc: String, pub params: Vec, - pub self_ty: Option>, - pub return_ty: Rc, + pub self_ty: Option, + pub return_ty: TypeRef, pub is_variadic: bool, pub kw_only_index: Option, } +impl FunctionType { + pub fn ty_str(&self) -> String { + format!( + "({}) -> {}", + self.params + .iter() + .map(|param| param.ty.ty_str()) + .collect::>() + .join(", "), + self.return_ty.ty_str() + ) + } + + pub fn func_signature_str(&self, name: &String) -> String { + format!( + "function {}({}) -> {}", + name, + self.params + .iter() + .map(|param| format!("{}: {}", param.name, param.ty.ty_str())) + .collect::>() + .join(", "), + self.return_ty.ty_str() + ) + } +} + +impl FunctionType { + #[inline] + pub fn variadic_func() -> Self { + Self { + doc: "".to_string(), + params: vec![], + self_ty: None, + return_ty: Type::any_ref(), + is_variadic: true, + kw_only_index: None, + } + } +} + /// The function parameter. #[derive(Debug, Clone, PartialEq)] pub struct Parameter { pub name: String, - pub ty: Rc, + pub ty: TypeRef, pub has_default: bool, } diff --git a/kclvm/sema/src/ty/parser.rs b/kclvm/sema/src/ty/parser.rs index ab68174a2..285a4720a 100644 --- a/kclvm/sema/src/ty/parser.rs +++ b/kclvm/sema/src/ty/parser.rs @@ -3,13 +3,13 @@ use crate::eval::str_literal_eval; use super::*; /// Parse type string -pub fn parse_type_str(ty_str: &str) -> Rc { +pub fn parse_type_str(ty_str: &str) -> TypeRef { if ty_str.is_empty() { - return Rc::new(Type::ANY); + return Arc::new(Type::ANY); } let ty_str = ty_str_strip(ty_str); match TYPES_MAPPING.get(ty_str) { - Some(ty) => Rc::new(ty.clone()), + Some(ty) => Arc::new(ty.clone()), None => { if is_union_type_str(ty_str) { parse_union_type_str(ty_str) @@ -19,12 +19,12 @@ pub fn parse_type_str(ty_str: &str) -> Rc { parse_number_multiplier_literal_type_str(ty_str) } else if is_dict_type_str(ty_str) { let (key_ty_str, val_ty_str) = separate_kv(&dereference_type(ty_str)); - Rc::new(Type::dict( + Arc::new(Type::dict( parse_type_str(&key_ty_str), parse_type_str(&val_ty_str), )) } else if is_list_type_str(ty_str) { - Rc::new(Type::list(parse_type_str(&dereference_type(ty_str)))) + Arc::new(Type::list(parse_type_str(&dereference_type(ty_str)))) } else { parse_named_type_str(ty_str) } @@ -157,31 +157,31 @@ pub fn split_type_union(ty_str: &str) -> Vec<&str> { } /// Parse union type string. -pub fn parse_union_type_str(ty_str: &str) -> Rc { +pub fn parse_union_type_str(ty_str: &str) -> TypeRef { let types = split_type_union(ty_str) .iter() .map(|ty_str| parse_type_str(ty_str)) - .collect::>>(); + .collect::>(); sup(&types) } /// Parse literal type string. -pub fn parse_lit_type_str(ty_str: &str) -> Rc { +pub fn parse_lit_type_str(ty_str: &str) -> TypeRef { // Bool literal type. if ty_str == NAME_CONSTANT_TRUE { - return Rc::new(Type::bool_lit(true)); + return Arc::new(Type::bool_lit(true)); } else if ty_str == NAME_CONSTANT_FALSE { - return Rc::new(Type::bool_lit(false)); + return Arc::new(Type::bool_lit(false)); } match ty_str.parse::() { // Float literal type. - Ok(v) => Rc::new(Type::int_lit(v)), + Ok(v) => Arc::new(Type::int_lit(v)), Err(_) => match ty_str.parse::() { // Int literal type. - Ok(v) => Rc::new(Type::float_lit(v)), + Ok(v) => Arc::new(Type::float_lit(v)), // Maybe string literal type Err(_) => match str_literal_eval(ty_str, false, false) { - Some(v) => Rc::new(Type::str_lit(&v)), + Some(v) => Arc::new(Type::str_lit(&v)), None => bug!("invalid literal type string {}", ty_str), }, }, @@ -189,7 +189,7 @@ pub fn parse_lit_type_str(ty_str: &str) -> Rc { } /// Parse number multiplier literal type. -pub fn parse_number_multiplier_literal_type_str(ty_str: &str) -> Rc { +pub fn parse_number_multiplier_literal_type_str(ty_str: &str) -> TypeRef { let suffix_index = if &ty_str[ty_str.len() - 1..] == kclvm_runtime::IEC_SUFFIX { ty_str.len() - 2 } else { @@ -202,7 +202,7 @@ pub fn parse_number_multiplier_literal_type_str(ty_str: &str) -> Rc { }, &ty_str[suffix_index..], ); - Rc::new(Type::number_multiplier( + Arc::new(Type::number_multiplier( kclvm_runtime::cal_num(value, suffix), value, suffix, @@ -211,8 +211,8 @@ pub fn parse_number_multiplier_literal_type_str(ty_str: &str) -> Rc { /// Please note Named type to find it in the scope (e.g. schema type, type alias). #[inline] -pub fn parse_named_type_str(ty_str: &str) -> Rc { - Rc::new(Type::named(ty_str)) +pub fn parse_named_type_str(ty_str: &str) -> TypeRef { + Arc::new(Type::named(ty_str)) } /// separate_kv function separates key_type and value_type in the dictionary type strings, diff --git a/kclvm/sema/src/ty/tests.rs b/kclvm/sema/src/ty/tests.rs index c23ebc5f9..e634ae027 100644 --- a/kclvm/sema/src/ty/tests.rs +++ b/kclvm/sema/src/ty/tests.rs @@ -3,62 +3,62 @@ use super::*; #[test] fn test_sup() { let cases = vec![ - (vec![], Rc::new(Type::ANY)), - (vec![Rc::new(Type::ANY)], Rc::new(Type::ANY)), - (vec![Rc::new(Type::STR)], Rc::new(Type::STR)), + (vec![], Arc::new(Type::ANY)), + (vec![Arc::new(Type::ANY)], Arc::new(Type::ANY)), + (vec![Arc::new(Type::STR)], Arc::new(Type::STR)), ( - vec![Rc::new(Type::STR), Rc::new(Type::INT)], - Type::union_ref(&[Rc::new(Type::STR), Rc::new(Type::INT)]), + vec![Arc::new(Type::STR), Arc::new(Type::INT)], + Type::union_ref(&[Arc::new(Type::STR), Arc::new(Type::INT)]), ), ( - vec![Rc::new(Type::BOOL), Rc::new(Type::bool_lit(true))], - Rc::new(Type::BOOL), + vec![Arc::new(Type::BOOL), Arc::new(Type::bool_lit(true))], + Arc::new(Type::BOOL), ), ( vec![ - Rc::new(Type::str_lit("Blue")), - Rc::new(Type::str_lit("Yellow")), - Rc::new(Type::str_lit("Red")), + Arc::new(Type::str_lit("Blue")), + Arc::new(Type::str_lit("Yellow")), + Arc::new(Type::str_lit("Red")), ], Type::union_ref(&[ - Rc::new(Type::str_lit("Blue")), - Rc::new(Type::str_lit("Yellow")), - Rc::new(Type::str_lit("Red")), + Arc::new(Type::str_lit("Blue")), + Arc::new(Type::str_lit("Yellow")), + Arc::new(Type::str_lit("Red")), ]), ), ( vec![ Type::list_ref(Type::union_ref(&[ - Rc::new(Type::int_lit(1)), - Rc::new(Type::int_lit(2)), + Arc::new(Type::int_lit(1)), + Arc::new(Type::int_lit(2)), ])), Type::list_ref(Type::union_ref(&[ - Rc::new(Type::int_lit(3)), - Rc::new(Type::int_lit(4)), + Arc::new(Type::int_lit(3)), + Arc::new(Type::int_lit(4)), ])), ], Type::union_ref(&[ Type::list_ref(Type::union_ref(&[ - Rc::new(Type::int_lit(1)), - Rc::new(Type::int_lit(2)), + Arc::new(Type::int_lit(1)), + Arc::new(Type::int_lit(2)), ])), Type::list_ref(Type::union_ref(&[ - Rc::new(Type::int_lit(3)), - Rc::new(Type::int_lit(4)), + Arc::new(Type::int_lit(3)), + Arc::new(Type::int_lit(4)), ])), ]), ), ( vec![ Type::union_ref(&[ - Rc::new(Type::STR), - Type::dict_ref(Rc::new(Type::STR), Rc::new(Type::STR)), + Arc::new(Type::STR), + Type::dict_ref(Arc::new(Type::STR), Arc::new(Type::STR)), ]), - Type::dict_ref(Rc::new(Type::ANY), Rc::new(Type::ANY)), + Type::dict_ref(Arc::new(Type::ANY), Arc::new(Type::ANY)), ], Type::union_ref(&[ - Rc::new(Type::STR), - Type::dict_ref(Rc::new(Type::ANY), Rc::new(Type::ANY)), + Arc::new(Type::STR), + Type::dict_ref(Arc::new(Type::ANY), Arc::new(Type::ANY)), ]), ), ]; @@ -70,40 +70,40 @@ fn test_sup() { #[test] fn test_type_walker() { - fn walk_fn(ty: &Type) -> Rc { + fn walk_fn(ty: &Type) -> TypeRef { if ty.is_int() { - Rc::new(Type::STR) + Arc::new(Type::STR) } else { - Rc::new(ty.clone()) + Arc::new(ty.clone()) } } let cases = [ - (Rc::new(Type::ANY), Rc::new(Type::ANY)), - (Rc::new(Type::INT), Rc::new(Type::STR)), - (Rc::new(Type::STR), Rc::new(Type::STR)), + (Arc::new(Type::ANY), Arc::new(Type::ANY)), + (Arc::new(Type::INT), Arc::new(Type::STR)), + (Arc::new(Type::STR), Arc::new(Type::STR)), ( - Type::list_ref(Rc::new(Type::INT)), - Type::list_ref(Rc::new(Type::STR)), + Type::list_ref(Arc::new(Type::INT)), + Type::list_ref(Arc::new(Type::STR)), ), ( - Type::union_ref(&[Rc::new(Type::INT), Rc::new(Type::STR)]), - Type::union_ref(&[Rc::new(Type::STR), Rc::new(Type::STR)]), + Type::union_ref(&[Arc::new(Type::INT), Arc::new(Type::STR)]), + Type::union_ref(&[Arc::new(Type::STR), Arc::new(Type::STR)]), ), ( Type::union_ref(&[ - Rc::new(Type::INT), - Rc::new(Type::STR), - Type::union_ref(&[Rc::new(Type::INT), Rc::new(Type::STR)]), + Arc::new(Type::INT), + Arc::new(Type::STR), + Type::union_ref(&[Arc::new(Type::INT), Arc::new(Type::STR)]), ]), Type::union_ref(&[ - Rc::new(Type::STR), - Rc::new(Type::STR), - Type::union_ref(&[Rc::new(Type::STR), Rc::new(Type::STR)]), + Arc::new(Type::STR), + Arc::new(Type::STR), + Type::union_ref(&[Arc::new(Type::STR), Arc::new(Type::STR)]), ]), ), ( - Type::dict_ref(Rc::new(Type::INT), Rc::new(Type::INT)), - Type::dict_ref(Rc::new(Type::STR), Rc::new(Type::STR)), + Type::dict_ref(Arc::new(Type::INT), Arc::new(Type::INT)), + Type::dict_ref(Arc::new(Type::STR), Arc::new(Type::STR)), ), ]; for (ty, expected) in cases { diff --git a/kclvm/sema/src/ty/unify.rs b/kclvm/sema/src/ty/unify.rs index 331fb0d26..4c09de8e7 100644 --- a/kclvm/sema/src/ty/unify.rs +++ b/kclvm/sema/src/ty/unify.rs @@ -1,12 +1,14 @@ -use std::{collections::HashSet, rc::Rc}; +use std::{collections::HashSet, sync::Arc}; -use super::{SchemaType, Type, TypeKind}; +use indexmap::IndexMap; + +use super::{SchemaType, Type, TypeKind, TypeRef}; /// The type can be assigned to the expected type. /// /// For security and performance considerations, dynamic dispatch of /// types is not supported at this stage. -pub fn subsume(ty_lhs: Rc, ty_rhs: Rc, check_left_any: bool) -> bool { +pub fn subsume(ty_lhs: TypeRef, ty_rhs: TypeRef, check_left_any: bool) -> bool { if (check_left_any && ty_lhs.is_any()) || (ty_rhs.is_any() || ty_lhs.is_none()) { true } else if ty_lhs.is_union() { @@ -64,6 +66,29 @@ pub fn subsume(ty_lhs: Rc, ty_rhs: Rc, check_left_any: bool) -> bool let (ty_rhs_key, ty_rhs_val) = ty_rhs.dict_entry_ty(); subsume(ty_lhs_key, ty_rhs_key, check_left_any) && subsume(ty_lhs_val, ty_rhs_val, check_left_any) + } else if ty_lhs.is_str() && ty_rhs.is_literal() && ty_rhs.is_str() { + return true; + } else if ty_lhs.is_func() && ty_rhs.is_func() { + let ty_lhs_fn_ty = ty_lhs.into_func_type(); + let ty_rhs_fn_ty = ty_rhs.into_func_type(); + let mut is_ok = ty_lhs_fn_ty.params.len() == ty_rhs_fn_ty.params.len(); + for (ty_lhs_param, ty_rhs_param) in + ty_lhs_fn_ty.params.iter().zip(ty_rhs_fn_ty.params.iter()) + { + is_ok = is_ok + && (subsume( + ty_rhs_param.ty.clone(), + ty_lhs_param.ty.clone(), + check_left_any, + )); + } + is_ok = is_ok + && (subsume( + ty_lhs_fn_ty.return_ty.clone(), + ty_rhs_fn_ty.return_ty.clone(), + check_left_any, + )); + is_ok } else { equal(ty_lhs, ty_rhs) } @@ -71,7 +96,7 @@ pub fn subsume(ty_lhs: Rc, ty_rhs: Rc, check_left_any: bool) -> bool /// Are the two types exactly equal. #[inline] -pub fn equal(ty_lhs: Rc, ty_rhs: Rc) -> bool { +pub fn equal(ty_lhs: TypeRef, ty_rhs: TypeRef) -> bool { ty_lhs.kind == ty_rhs.kind } @@ -89,7 +114,7 @@ pub fn is_sub_schema_of(schema_ty_lhs: &SchemaType, schema_ty_rhs: &SchemaType) /// The type can be assigned to the expected type. #[inline] -pub fn assignable_to(ty: Rc, expected_ty: Rc) -> bool { +pub fn assignable_to(ty: TypeRef, expected_ty: TypeRef) -> bool { if !ty.is_assignable_type() { return false; } @@ -98,72 +123,72 @@ pub fn assignable_to(ty: Rc, expected_ty: Rc) -> bool { /// Whether `lhs_ty` is the upper bound of the `rhs_ty` #[inline] -pub fn is_upper_bound(lhs_ty: Rc, rhs_ty: Rc) -> bool { +pub fn is_upper_bound(lhs_ty: TypeRef, rhs_ty: TypeRef) -> bool { subsume(rhs_ty, lhs_ty, false) } /// Whether the type list contains the `any` type. #[inline] -pub fn has_any_type(types: &[Rc]) -> bool { +pub fn has_any_type(types: &[TypeRef]) -> bool { types.iter().any(|ty| ty.is_any()) } /// The sup function returns the minimum supremum of all types in an array of types. #[inline] -pub fn sup(types: &[Rc]) -> Rc { +pub fn sup(types: &[TypeRef]) -> TypeRef { r#typeof(types, true) } /// Typeof types -pub fn r#typeof(types: &[Rc], should_remove_sub_types: bool) -> Rc { +pub fn r#typeof(types: &[TypeRef], should_remove_sub_types: bool) -> TypeRef { // 1. Initialize an ordered set to store the type array - let mut type_set: Vec> = vec![]; + let mut type_set: IndexMap<*const Type, TypeRef> = IndexMap::default(); // 2. Add the type array to the ordered set for sorting by the type id and de-duplication. add_types_to_type_set(&mut type_set, types); // 3. Remove sub types according to partial order relation rules e.g. sub schema types. if should_remove_sub_types { let mut remove_index_set = HashSet::new(); - for (i, source) in type_set.iter().enumerate() { - for (j, target) in type_set.iter().enumerate() { - if i != j && subsume(source.clone(), target.clone(), false) { - remove_index_set.insert(i); + for (i, (source_addr, source)) in type_set.iter().enumerate() { + for j in i + 1..type_set.len() { + let (target_addr, target) = type_set.get_index(j).unwrap(); + if subsume(source.clone(), target.clone(), false) { + remove_index_set.insert(*source_addr); + } else if subsume(target.clone(), source.clone(), false) { + remove_index_set.insert(*target_addr); } } } - let types: Vec<(usize, &Rc)> = type_set - .iter() - .enumerate() - .filter(|(i, _)| !remove_index_set.contains(i)) - .collect(); - type_set = types - .iter() - .map(|(_, ty)| <&Rc>::clone(ty).clone()) - .collect(); + for i in remove_index_set { + type_set.remove(&i); + } } if type_set.is_empty() { - Rc::new(Type::ANY) + Arc::new(Type::ANY) } else if type_set.len() == 1 { type_set[0].clone() } else { - Rc::new(Type::union(&type_set)) + Arc::new(Type::union( + &type_set.values().cloned().collect::>(), + )) } } -fn add_types_to_type_set(type_set: &mut Vec>, types: &[Rc]) { +fn add_types_to_type_set(type_set: &mut IndexMap<*const Type, TypeRef>, types: &[TypeRef]) { for ty in types { add_type_to_type_set(type_set, ty.clone()); } } -fn add_type_to_type_set(type_set: &mut Vec>, ty: Rc) { +fn add_type_to_type_set(type_set: &mut IndexMap<*const Type, TypeRef>, ty: TypeRef) { match &ty.kind { TypeKind::Union(types) => { add_types_to_type_set(type_set, types); } _ => { + let ref_addr = ty.as_ref() as *const Type; // Remove the bottom type. - if !ty.is_void() && !type_set.contains(&ty) { - type_set.push(ty.clone()) + if !ty.is_void() && !type_set.contains_key(&ref_addr) { + type_set.insert(ref_addr, ty.clone()); } } } diff --git a/kclvm/sema/src/ty/walker.rs b/kclvm/sema/src/ty/walker.rs index 3f996ff6c..22deb0609 100644 --- a/kclvm/sema/src/ty/walker.rs +++ b/kclvm/sema/src/ty/walker.rs @@ -1,21 +1,37 @@ -use std::rc::Rc; +use std::sync::Arc; -use super::Type; +use super::{Attr, DictType, Type, TypeRef}; /// Walk one type recursively and deal the type using the `walk_fn` -pub fn walk_type(ty: &Type, walk_fn: impl Fn(&Type) -> Rc + Copy) -> Rc { +pub fn walk_type(ty: &Type, walk_fn: impl Fn(&Type) -> TypeRef + Copy) -> TypeRef { let ty = walk_fn(ty); match &ty.kind { - super::TypeKind::List(item_ty) => Rc::new(Type::list(walk_type(item_ty, walk_fn))), - super::TypeKind::Dict(key_ty, val_ty) => Rc::new(Type::dict( + super::TypeKind::List(item_ty) => Arc::new(Type::list(walk_type(item_ty, walk_fn))), + super::TypeKind::Dict(DictType { + key_ty, + val_ty, + attrs, + }) => Arc::new(Type::dict_with_attrs( walk_type(key_ty, walk_fn), walk_type(val_ty, walk_fn), + attrs + .into_iter() + .map(|(key, attr)| { + ( + key.to_string(), + Attr { + ty: walk_type(&attr.ty, walk_fn), + range: attr.range.clone(), + }, + ) + }) + .collect(), )), - super::TypeKind::Union(types) => Rc::new(Type::union( + super::TypeKind::Union(types) => Arc::new(Type::union( &types .iter() .map(|ty| walk_type(ty, walk_fn)) - .collect::>>(), + .collect::>(), )), _ => ty, } diff --git a/kclvm/span/Cargo.toml b/kclvm/span/Cargo.toml index 93af47aa4..238cb1d91 100644 --- a/kclvm/span/Cargo.toml +++ b/kclvm/span/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-span" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/kclvm/span/src/symbol.rs b/kclvm/span/src/symbol.rs index 8b783f87b..d57abd990 100644 --- a/kclvm/span/src/symbol.rs +++ b/kclvm/span/src/symbol.rs @@ -228,6 +228,15 @@ pub mod sym { } } +pub mod reserved { + + pub use super::reserved_word; + + pub fn is_reserved_word(word: &str) -> bool { + reserved_word::reserved_words.contains(&word) + } +} + /// Special symbols related to KCL keywords. impl Symbol { /// Returns `true` if the symbol is `true` or `false`. diff --git a/kclvm/spec/gpyrpc/gpyrpc.proto b/kclvm/spec/gpyrpc/gpyrpc.proto new file mode 100644 index 000000000..85d427fba --- /dev/null +++ b/kclvm/spec/gpyrpc/gpyrpc.proto @@ -0,0 +1,464 @@ +// Copyright The KCL Authors. All rights reserved. +// +// This file defines the request parameters and return structure of the KCL RPC server. + +syntax = "proto3"; + +package gpyrpc; + +// kcl main.k -E pkg_name=pkg_path +message CmdExternalPkgSpec { + string pkg_name = 1; + string pkg_path = 2; +} + +// kcl main.k -D name=value +message CmdArgSpec { + string name = 1; + string value = 2; +} + +// kcl main.k -O pkgpath:path.to.field=field_value +message CmdOverrideSpec { + string pkgpath = 1; + string field_path = 2; + string field_value = 3; + string action = 4; +} + +// ---------------------------------------------------------------------------- +// Error types +// ---------------------------------------------------------------------------- + +message Error { + string level = 1; + string code = 2; + repeated Message messages = 3; +} + +message Message { + string msg = 1; + Position pos = 2; +} + +// ---------------------------------------------------------------------------- +// service request/response +// ---------------------------------------------------------------------------- + +// gpyrpc.BuiltinService +service BuiltinService { + rpc Ping(Ping_Args) returns(Ping_Result); + rpc ListMethod(ListMethod_Args) returns(ListMethod_Result); +} + +// gpyrpc.KclvmService +service KclvmService { + rpc Ping(Ping_Args) returns(Ping_Result); + + rpc ExecProgram(ExecProgram_Args) returns(ExecProgram_Result); + rpc BuildProgram(BuildProgram_Args) returns(BuildProgram_Result); + rpc ExecArtifact(ExecArtifact_Args) returns(ExecProgram_Result); + + rpc ParseFile(ParseFile_Args) returns(ParseFile_Result); + rpc ParseProgram(ParseProgram_Args) returns(ParseProgram_Result); + rpc LoadPackage(LoadPackage_Args) returns(LoadPackage_Result); + + rpc FormatCode(FormatCode_Args) returns(FormatCode_Result); + rpc FormatPath(FormatPath_Args) returns(FormatPath_Result); + rpc LintPath(LintPath_Args) returns(LintPath_Result); + rpc OverrideFile(OverrideFile_Args) returns (OverrideFile_Result); + + rpc GetSchemaType(GetSchemaType_Args) returns(GetSchemaType_Result); + rpc GetFullSchemaType(GetFullSchemaType_Args) returns(GetSchemaType_Result); + rpc GetSchemaTypeMapping(GetSchemaTypeMapping_Args) returns(GetSchemaTypeMapping_Result); + rpc ValidateCode(ValidateCode_Args) returns(ValidateCode_Result); + + rpc ListDepFiles(ListDepFiles_Args) returns(ListDepFiles_Result); + rpc LoadSettingsFiles(LoadSettingsFiles_Args) returns(LoadSettingsFiles_Result); + + rpc Rename(Rename_Args) returns(Rename_Result); + rpc RenameCode(RenameCode_Args) returns(RenameCode_Result); + + rpc Test(Test_Args) returns (Test_Result); +} + +message Ping_Args { + string value = 1; +} +message Ping_Result { + string value = 1; +} + +message ListMethod_Args { + // empty +} +message ListMethod_Result { + repeated string method_name_list = 1; +} + +message ParseFile_Args { + string path = 1; + string source = 2; + repeated CmdExternalPkgSpec external_pkgs = 3; // External packages path +} + +message ParseFile_Result { + string ast_json = 1; // JSON string value + repeated string deps = 2; // file dependency paths + repeated Error errors = 3; // Parse errors +} + +message ParseProgram_Args { + repeated string paths = 1; + repeated string sources = 2; + repeated CmdExternalPkgSpec external_pkgs = 3; // External packages path +} + +message ParseProgram_Result { + string ast_json = 1; // JSON string value + repeated string paths = 2; // Returns the files in the order they should be compiled + repeated Error errors = 3; // Parse errors +} + +message LoadPackage_Args { + ParseProgram_Args parse_args = 1; + bool resolve_ast = 2; + bool load_builtin = 3; + bool with_ast_index = 4; +} + +message LoadPackage_Result { + string program = 1; // JSON string value + repeated string paths = 2; // Returns the files in the order they should be compiled + repeated Error parse_errors = 3; // Parse errors + repeated Error type_errors = 4; // Type errors + map scopes = 5; // Map key is the ScopeIndex json string. + map symbols = 6; // Map key is the SymbolIndex json string. + map node_symbol_map = 7; // Map key is the AST index UUID string. + map symbol_node_map = 8; // Map key is the SymbolIndex json string. + map fully_qualified_name_map = 9; // Map key is the fully_qualified_name e.g. `pkg.Name` + map pkg_scope_map = 10; // Map key is the package path. +} + +message Symbol { + KclType ty = 1; + string name = 2; + SymbolIndex owner = 3; + SymbolIndex def = 4; + repeated SymbolIndex attrs = 5; + bool is_global = 6; +} + +message Scope { + string kind = 1; + ScopeIndex parent = 2; + SymbolIndex owner = 3; + repeated ScopeIndex children = 4; + repeated SymbolIndex defs = 5; +} + +message SymbolIndex { + uint64 i = 1; + uint64 g = 2; + string kind = 3; +} + +message ScopeIndex { + uint64 i = 1; + uint64 g = 2; + string kind = 3; +} + +message ExecProgram_Args { + string work_dir = 1; + + repeated string k_filename_list = 2; + repeated string k_code_list = 3; + + repeated CmdArgSpec args = 4; + repeated CmdOverrideSpec overrides = 5; + + bool disable_yaml_result = 6; + + bool print_override_ast = 7; + + // -r --strict-range-check + bool strict_range_check = 8; + + // -n --disable-none + bool disable_none = 9; + // -v --verbose + int32 verbose = 10; + + // -d --debug + int32 debug = 11; + + // yaml/json: sort keys + bool sort_keys = 12; + + // -E --external : external packages path + repeated CmdExternalPkgSpec external_pkgs = 13; + + // Whether including schema type in JSON/YAML result + bool include_schema_type_path = 14; + + // Whether only compiling the program + bool compile_only = 15; + + // Show hidden attributes + bool show_hidden = 16; + + // -S --path_selector + repeated string path_selector = 17; +} + +message ExecProgram_Result { + string json_result = 1; + string yaml_result = 2; + string log_message = 3; + string err_message = 4; +} + +message BuildProgram_Args { + ExecProgram_Args exec_args = 1; + string output = 2; +} + +message BuildProgram_Result { + string path = 1; +} + +message ExecArtifact_Args { + string path = 1; + ExecProgram_Args exec_args = 2; +} + +message ResetPlugin_Args { + string plugin_root = 1; +} +message ResetPlugin_Result { + // empty +} + +message FormatCode_Args { + string source = 1; +} + +message FormatCode_Result { + bytes formatted = 1; +} + +message FormatPath_Args { + string path = 1; +} + +message FormatPath_Result { + repeated string changed_paths = 1; +} + +message LintPath_Args { + repeated string paths = 1; +} + +message LintPath_Result { + repeated string results = 1; +} + +message OverrideFile_Args { + string file = 1; + repeated string specs = 2; + repeated string import_paths = 3; +} + +message OverrideFile_Result { + bool result = 1; +} + +message GetFullSchemaType_Args { + ExecProgram_Args exec_args = 1; + string schema_name = 2; +} + +message GetSchemaType_Args { + string file = 1; + string code = 2; + string schema_name = 3; +} +message GetSchemaType_Result { + repeated KclType schema_type_list = 1; +} + +message GetSchemaTypeMapping_Args { + string file = 1; + string code = 2; + string schema_name = 3; +} +message GetSchemaTypeMapping_Result { + map schema_type_mapping = 1; +} + +message ValidateCode_Args { + string datafile = 1; + string data = 2; + string file = 3; + string code = 4; + string schema = 5; + string attribute_name = 6; + string format = 7; +} + +message ValidateCode_Result { + bool success = 1; + string err_message = 2; +} + +message Position { + int64 line = 1; + int64 column = 2; + string filename = 3; +} + +message ListDepFiles_Args { + string work_dir = 1; + bool use_abs_path = 2; + bool include_all = 3; + bool use_fast_parser = 4; +} + +message ListDepFiles_Result { + string pkgroot = 1; + string pkgpath = 2; + repeated string files = 3; +} + +// --------------------------------------------------------------------------------- +// LoadSettingsFiles API +// Input work dir and setting files and return the merged kcl singleton config. +// --------------------------------------------------------------------------------- + +message LoadSettingsFiles_Args { + string work_dir = 1; + repeated string files = 2; +} + +message LoadSettingsFiles_Result { + CliConfig kcl_cli_configs = 1; + repeated KeyValuePair kcl_options = 2; +} + +message CliConfig { + repeated string files = 1; + string output = 2; + repeated string overrides = 3; + repeated string path_selector = 4; + bool strict_range_check = 5; + bool disable_none = 6; + int64 verbose = 7; + bool debug = 8; + bool sort_keys = 9; + bool show_hidden = 10; + bool include_schema_type_path = 11; +} + +message KeyValuePair { + string key = 1; + string value = 2; +} + +// --------------------------------------------------------------------------------- +// Rename API +// find all the occurrences of the target symbol and rename them. This API will rewrite files if they contain symbols to be renamed. +// --------------------------------------------------------------------------------- + +message Rename_Args { + string package_root = 1; // the file path to the package root + string symbol_path = 2; // the path to the target symbol to be renamed. The symbol path should conform to format: `:` When the pkgpath is '__main__', `:` can be omitted. + repeated string file_paths = 3; // the paths to the source code files + string new_name = 4; // the new name of the symbol +} + +message Rename_Result { + repeated string changed_files = 1; // the file paths got changed +} + +// --------------------------------------------------------------------------------- +// RenameCode API +// find all the occurrences of the target symbol and rename them. This API won't rewrite files but return the modified code if any code has been changed. +// --------------------------------------------------------------------------------- + +message RenameCode_Args { + string package_root = 1; // the file path to the package root + string symbol_path = 2; // the path to the target symbol to be renamed. The symbol path should conform to format: `:` When the pkgpath is '__main__', `:` can be omitted. + map source_codes = 3; // the source code. a : map + string new_name = 4; // the new name of the symbol +} + +message RenameCode_Result { + map changed_codes = 1; // the changed code. a : map +} + +// --------------------------------------------------------------------------------- +// Test API +// Test KCL packages with test arguments +// --------------------------------------------------------------------------------- + +message Test_Args { + ExecProgram_Args exec_args = 1; // This field stores the execution program arguments. + repeated string pkg_list = 2; // The package path list to be tested e.g., "./...", "/path/to/package/", "/path/to/package/..." + string run_regexp = 3; // This field stores a regular expression for filtering tests to run. + bool fail_fast = 4; // This field determines whether the test run should stop on the first failure. +} + +message Test_Result { + repeated TestCaseInfo info = 2; +} + +message TestCaseInfo { + string name = 1; // Test case name + string error = 2; + uint64 duration = 3; // Number of whole microseconds in the duration. + string log_message = 4; +} + +// ---------------------------------------------------------------------------- +// KCL Type Structure +// ---------------------------------------------------------------------------- + +message KclType { + string type = 1; // schema, dict, list, str, int, float, bool, any, union, number_multiplier + repeated KclType union_types = 2 ; // union types + string default = 3; // default value + + string schema_name = 4; // schema name + string schema_doc = 5; // schema doc + map properties = 6; // schema properties + repeated string required = 7; // required schema properties, [property_name1, property_name2] + + KclType key = 8; // dict key type + KclType item = 9; // dict/list item type + + int32 line = 10; + + repeated Decorator decorators = 11; // schema decorators + + string filename = 12; // `filename` represents the absolute path of the file name where the attribute is located. + string pkg_path = 13; // `pkg_path` represents the path name of the package where the attribute is located. + string description = 14; // `description` represents the document of the attribute. + map examples = 15; // A map object to hold examples, the key is the example name. +} + +message Decorator { + string name = 1; + repeated string arguments = 2; + map keywords = 3; +} + +message Example { + string summary = 1; // Short description for the example. + string description = 2; // Long description for the example. + string value = 3; // Embedded literal example. +} + +// ---------------------------------------------------------------------------- +// END +// ---------------------------------------------------------------------------- diff --git a/kclvm/src/lib.rs b/kclvm/src/lib.rs index 9e4b71a74..7f92cb3c1 100644 --- a/kclvm/src/lib.rs +++ b/kclvm/src/lib.rs @@ -12,11 +12,11 @@ use std::ffi::CStr; use std::process::ExitCode; use std::sync::Arc; -/// KCLVM CLI run function CAPI. +/// KCL CLI run function CAPI. /// /// args is a ExecProgramArgs JSON string. #[no_mangle] -pub unsafe extern "C" fn kclvm_cli_run(args: *const i8, plugin_agent: *const i8) -> *const i8 { +pub unsafe extern "C" fn kclvm_cli_run(args: *const c_char, plugin_agent: *const i8) -> *const i8 { let prev_hook = std::panic::take_hook(); // disable print panic info @@ -51,16 +51,17 @@ pub unsafe extern "C" fn kclvm_cli_run(args: *const i8, plugin_agent: *const i8) } } -/// KCLVM CLI run function CAPI. -fn kclvm_cli_run_unsafe(args: *const i8, plugin_agent: *const i8) -> Result { - let mut args = ExecProgramArgs::from_str(kclvm_runtime::c2str(args)); +/// KCL CLI run function CAPI. +fn kclvm_cli_run_unsafe(args: *const c_char, plugin_agent: *const i8) -> Result { + let mut args = + ExecProgramArgs::from_str(unsafe { std::ffi::CStr::from_ptr(args) }.to_str().unwrap()); args.plugin_agent = plugin_agent as u64; exec_program(Arc::new(ParseSession::default()), &args) - .map_err(|e| PanicInfo::from(e).to_json_string()) + .map_err(|e| PanicInfo::from(e.to_string()).to_json_string()) .map(|r| r.json_result) } -/// KCLVM CLI main function CAPI. +/// KCL CLI main function CAPI. #[no_mangle] pub unsafe extern "C" fn kclvm_cli_main(argc: c_int, argv: *const *const c_char) -> *mut ExitCode { let prev_hook = std::panic::take_hook(); @@ -83,10 +84,10 @@ pub unsafe extern "C" fn kclvm_cli_main(argc: c_int, argv: *const *const c_char) Ok(()) => Box::into_raw(Box::new(ExitCode::SUCCESS)), Err(err) => { let backtrace = format!("{}", err.backtrace()); - if backtrace.is_empty() { - println!("Error: {}", err); + if backtrace.is_empty() || backtrace.contains("disabled backtrace") { + eprintln!("{err}"); } else { - println!("Error: {}\n\nStack backtrace:\n{}", err, backtrace); + eprintln!("{err}\nStack backtrace:\n{backtrace}"); } Box::into_raw(Box::new(ExitCode::FAILURE)) } @@ -94,7 +95,7 @@ pub unsafe extern "C" fn kclvm_cli_main(argc: c_int, argv: *const *const c_char) Err(err) => { let err_str = kclvm_error::err_to_str(err); if !err_str.is_empty() { - println!("Error: {}", err_str); + eprintln!("{err_str}"); } Box::into_raw(Box::new(ExitCode::FAILURE)) } diff --git a/kclvm/tests/fuzz/Cargo.lock b/kclvm/tests/fuzz/Cargo.lock index eb86202b9..2de130f91 100644 --- a/kclvm/tests/fuzz/Cargo.lock +++ b/kclvm/tests/fuzz/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.7.6" @@ -13,35 +28,109 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "always-assert" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +dependencies = [ + "log", +] + [[package]] name = "annotate-snippets" -version = "0.8.0" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" +dependencies = [ + "unicode-width", + "yansi-term", +] + +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstyle-parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", ] [[package]] name = "anyhow" -version = "1.0.60" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +dependencies = [ + "backtrace", +] [[package]] name = "arbitrary" @@ -58,13 +147,35 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -75,6 +186,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base64" version = "0.13.0" @@ -102,6 +234,21 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -128,14 +275,29 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", - "regex-automata", + "regex-automata 0.1.10", ] +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-if" @@ -158,25 +320,125 @@ dependencies = [ "libc", "num-integer", "num-traits", - "time", + "serde", + "time 0.1.44", "winapi", ] +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown 0.14.3", + "stacker", +] + [[package]] name = "clap" -version = "2.34.0" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ - "ansi_term", - "atty", - "bitflags", + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "compiler_base_error" +version = "0.0.10" +dependencies = [ + "anyhow", + "compiler_base_macros", + "compiler_base_span 0.0.1", + "fluent", + "pretty_assertions", + "rustc_errors", + "rustc_span", + "termcolor", + "unic-langid", + "walkdir", +] + +[[package]] +name = "compiler_base_error" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a26baf92ec0548418efaa8f24124cec069c40107af267a58c017c857b1cd136" +dependencies = [ + "anyhow", + "compiler_base_macros", + "compiler_base_span 0.0.1", + "fluent", + "pretty_assertions", + "rustc_errors", + "rustc_span", + "termcolor", + "unic-langid", + "walkdir", +] + +[[package]] +name = "compiler_base_macros" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e1cdc2aad3a38fae518f80e9bda866b6a01d8676c2c1bbc8b06aea3fcc1bb7" + +[[package]] +name = "compiler_base_session" +version = "0.0.13" +dependencies = [ + "anyhow", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_base_span 0.0.1", +] + +[[package]] +name = "compiler_base_span" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1616c7ca53a60881a4f1f2e3a30665cfb1f026d9d1b4101782028fc371354aa3" +dependencies = [ + "rustc_span", +] + +[[package]] +name = "compiler_base_span" +version = "0.0.2" +dependencies = [ + "rustc_span", +] + +[[package]] +name = "const_fn" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" + [[package]] name = "cpufeatures" version = "0.2.2" @@ -186,6 +448,16 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.1" @@ -213,12 +485,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -231,6 +502,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "dashmap" +version = "5.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.12.3", + "lock_api", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "deranged" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" + [[package]] name = "derive_arbitrary" version = "1.1.0" @@ -239,9 +528,15 @@ checksum = "98e23c06c035dac87bd802d98f368df73a7f2cb05a66ffbd1f377e821fac4af9" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -261,6 +556,44 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "either" version = "1.6.1" @@ -286,84 +619,339 @@ dependencies = [ ] [[package]] -name = "fancy-regex" -version = "0.7.1" +name = "env_logger" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ - "bit-set", + "humantime", + "is-terminal", + "log", "regex", + "termcolor", ] [[package]] -name = "fastrand" -version = "1.7.0" +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" dependencies = [ - "instant", + "serde", ] [[package]] -name = "fixedbitset" -version = "0.4.1" +name = "errno" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] [[package]] -name = "fslock" -version = "0.2.1" +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ + "cc", "libc", - "winapi", ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "fancy-regex" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "9d6b8560a05112eb52f04b00e5d3790c0dd75d9d980eb8a122fb23b92a623ccf" +dependencies = [ + "bit-set", + "regex", +] [[package]] -name = "gcc" -version = "0.3.55" +name = "fastrand" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] -name = "generic-array" -version = "0.14.5" +name = "filetime" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ - "typenum", - "version_check", + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "fixedbitset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" + +[[package]] +name = "fluent" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7" +dependencies = [ + "fluent-bundle", + "unic-langid", +] + +[[package]] +name = "fluent-bundle" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell 0.10.3", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" +dependencies = [ + "thiserror", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fst" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" + +[[package]] +name = "generational-arena" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash 0.8.6", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -374,15 +962,61 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.3", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", - "rustc-rayon", + "hashbrown 0.12.3", + "rustc-rayon 0.5.0", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", ] [[package]] @@ -395,7 +1029,7 @@ dependencies = [ "libc", "llvm-sys", "once_cell", - "parking_lot", + "parking_lot 0.12.0", ] [[package]] @@ -405,7 +1039,27 @@ source = "git+https://github.com/TheDan64/inkwell?branch=master#02fb7045f7a952c8 dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", ] [[package]] @@ -417,6 +1071,42 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "intl-memoizer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "inventory" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53088c87cf71c9d4f3372a2cb9eea1e7b8a0b1bf8b7f7d23fe5b76dbb07e63b" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.2", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.3" @@ -442,55 +1132,211 @@ dependencies = [ ] [[package]] -name = "json_minimal" -version = "0.1.3" +name = "jod-thread" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] -name = "kclvm" -version = "0.1.0" +name = "json-spanned-value" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb343fa4e3b1b22b344937deedac88da995abf139c2232cbeaa436c38380a210" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "jsonrpc-stdio-server" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6878586767497326eb3d011bd6dbb583e9f008b11528f82fd47798ec46bb6c26" +dependencies = [ + "futures", + "jsonrpc-core", + "log", + "tokio", + "tokio-util", +] + +[[package]] +name = "kcl-language-server" +version = "0.7.2" +dependencies = [ + "anyhow", "chrono", + "chumsky", "clap", + "compiler_base_session", + "crossbeam-channel", + "dashmap", + "env_logger", + "im-rc", + "indexmap 1.9.3", + "kclvm-ast", + "kclvm-config", + "kclvm-driver", + "kclvm-error", + "kclvm-parser", + "kclvm-query", + "kclvm-sema", + "kclvm-span", + "kclvm-tools", + "kclvm-utils", + "kclvm-version", + "log", + "lsp-server", + "lsp-types", + "parking_lot 0.12.0", + "proc_macro_crate", + "ra_ap_vfs", + "ra_ap_vfs-notify", + "ropey", + "rustc-hash", + "rustc_lexer", + "salsa", + "serde", + "serde_json", + "threadpool", + "tokio", + "tokio-test", +] + +[[package]] +name = "kclvm" +version = "0.7.2" +dependencies = [ + "anyhow", + "cc", + "chrono", + "compiler_base_session", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", + "kclvm-api", + "kclvm-ast", + "kclvm-cmd", + "kclvm-compiler", + "kclvm-config", + "kclvm-driver", + "kclvm-error", + "kclvm-parser", + "kclvm-query", + "kclvm-runner", + "kclvm-runtime", + "kclvm-sema", + "kclvm-tools", + "kclvm-version", + "libc", + "libloading", + "serde", + "serde_json", + "walkdir", +] + +[[package]] +name = "kclvm-api" +version = "0.7.2" +dependencies = [ + "anyhow", + "futures", + "indexmap 1.9.3", + "jsonrpc-stdio-server", + "kcl-language-server", "kclvm-ast", - "kclvm-compiler", + "kclvm-ast-pretty", "kclvm-config", + "kclvm-driver", "kclvm-error", "kclvm-parser", + "kclvm-query", "kclvm-runner", "kclvm-runtime", "kclvm-sema", "kclvm-tools", - "kclvm-version", - "libc", - "libloading", + "once_cell", + "prost", + "prost-build", + "prost-types", + "prost-wkt", + "prost-wkt-build", + "prost-wkt-types", + "protoc-bin-vendored", "serde", "serde_json", - "threadpool", - "walkdir", + "serde_yaml", + "tempfile", + "tokio", ] [[package]] name = "kclvm-ast" -version = "0.1.0" +version = "0.7.2" dependencies = [ + "compiler_base_span 0.0.2", + "kclvm-error", "kclvm-span", - "rustc_span", "serde", "serde_json", + "uuid", +] + +[[package]] +name = "kclvm-ast-pretty" +version = "0.7.2" +dependencies = [ + "compiler_base_macros", + "compiler_base_session", + "fancy-regex", + "indexmap 1.9.3", + "kclvm-ast", + "kclvm-error", + "pretty_assertions", +] + +[[package]] +name = "kclvm-cmd" +version = "0.7.2" +dependencies = [ + "anyhow", + "clap", + "compiler_base_session", + "kclvm-api", + "kclvm-config", + "kclvm-driver", + "kclvm-error", + "kclvm-parser", + "kclvm-runner", + "kclvm-runtime", + "kclvm-tools", + "kclvm-version", ] [[package]] name = "kclvm-compiler" -version = "0.1.0" +version = "0.7.2" dependencies = [ - "ahash", + "ahash 0.7.6", "bit-set", - "bitflags", + "bitflags 1.3.2", "fancy-regex", - "indexmap", + "indexmap 1.9.3", "inkwell", "kclvm-ast", "kclvm-error", @@ -498,46 +1344,71 @@ dependencies = [ "kclvm-sema", "once_cell", "phf", - "time", + "time 0.2.27", "unicode_names2", ] [[package]] name = "kclvm-config" -version = "0.1.0" +version = "0.7.2" dependencies = [ - "ahash", + "ahash 0.7.6", + "anyhow", "chrono", + "dirs", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", + "kclvm-ast", + "kclvm-utils", "kclvm-version", "pathdiff", + "pcre2", "ron", "rust-crypto", "serde", + "serde_json", "serde_yaml", "toml", ] +[[package]] +name = "kclvm-driver" +version = "0.7.2" +dependencies = [ + "anyhow", + "glob", + "kclvm-ast", + "kclvm-config", + "kclvm-parser", + "kclvm-runtime", + "kclvm-utils", + "serde", + "serde_json", + "walkdir", +] + [[package]] name = "kclvm-error" -version = "0.1.0" +version = "0.7.2" dependencies = [ "annotate-snippets", + "anyhow", "atty", - "indexmap", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_base_macros", + "compiler_base_session", + "compiler_base_span 0.0.2", + "indexmap 1.9.3", "kclvm-runtime", "kclvm-span", - "rustc_span", - "termcolor", "termize", "tracing", ] [[package]] name = "kclvm-lexer" -version = "0.1.0" +version = "0.7.2" dependencies = [ "kclvm-error", "rustc_lexer", @@ -546,21 +1417,28 @@ dependencies = [ [[package]] name = "kclvm-macros" -version = "0.1.0" +version = "0.7.2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", "synstructure", ] [[package]] name = "kclvm-parser" -version = "0.1.0" +version = "0.7.2" dependencies = [ + "anyhow", "bstr", + "compiler_base_error 0.0.10", + "compiler_base_error 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_base_macros", + "compiler_base_session", + "compiler_base_span 0.0.2", "either", "enquote", + "indexmap 1.9.3", "kclvm-ast", "kclvm-config", "kclvm-error", @@ -568,36 +1446,58 @@ dependencies = [ "kclvm-runtime", "kclvm-sema", "kclvm-span", + "kclvm-utils", "num-bigint", - "rustc_data_structures", + "regex", "rustc_lexer", - "rustc_span", "serde", "serde_json", "tracing", "unicode_names2", ] +[[package]] +name = "kclvm-query" +version = "0.7.2" +dependencies = [ + "anyhow", + "compiler_base_macros", + "compiler_base_session", + "indexmap 1.9.3", + "kclvm-ast", + "kclvm-ast-pretty", + "kclvm-error", + "kclvm-parser", + "kclvm-sema", + "maplit", +] + [[package]] name = "kclvm-runner" -version = "0.1.0" +version = "0.7.2" dependencies = [ + "anyhow", + "cc", "chrono", - "clap", + "compiler_base_macros", + "compiler_base_session", "fslock", "glob", - "indexmap", + "indexmap 1.9.3", "kclvm-ast", "kclvm-compiler", "kclvm-config", + "kclvm-driver", "kclvm-error", "kclvm-parser", + "kclvm-query", "kclvm-runtime", "kclvm-sema", - "kclvm-tools", + "kclvm-utils", "kclvm-version", "libc", "libloading", + "once_cell", "serde", "serde_json", "tempfile", @@ -607,16 +1507,15 @@ dependencies = [ [[package]] name = "kclvm-runtime" -version = "0.1.0" +version = "0.7.2" dependencies = [ - "ahash", + "ahash 0.7.6", "base64", "bstr", "chrono", "fancy-regex", - "indexmap", + "indexmap 1.9.3", "itertools", - "json_minimal", "kclvm_runtime_internal_macros", "libc", "md5", @@ -635,58 +1534,114 @@ dependencies = [ [[package]] name = "kclvm-sema" -version = "0.1.0" +version = "0.7.2" dependencies = [ - "ahash", + "ahash 0.7.6", + "anyhow", "bit-set", - "bitflags", + "bitflags 1.3.2", + "compiler_base_error 0.0.10", + "compiler_base_macros", + "compiler_base_session", + "compiler_base_span 0.0.2", "fancy-regex", - "indexmap", + "generational-arena", + "indexmap 1.9.3", "kclvm-ast", + "kclvm-ast-pretty", "kclvm-error", "kclvm-runtime", "kclvm-span", + "kclvm-utils", + "lazy_static", "once_cell", + "pcre2", "petgraph", "phf", + "regex", + "serde_json", + "suggestions", "unicode_names2", ] [[package]] name = "kclvm-span" -version = "0.1.0" +version = "0.7.2" dependencies = [ + "compiler_base_span 0.0.2", "kclvm-macros", - "rustc_span", + "parking_lot 0.11.2", "scoped-tls", ] [[package]] name = "kclvm-tools" -version = "0.1.0" +version = "0.7.2" dependencies = [ "anyhow", + "compiler_base_session", + "compiler_base_span 0.0.1", "fancy-regex", - "indexmap", + "indexmap 1.9.3", + "json-spanned-value", "kclvm-ast", + "kclvm-ast-pretty", "kclvm-config", + "kclvm-driver", "kclvm-error", "kclvm-parser", + "kclvm-query", + "kclvm-runner", + "kclvm-runtime", "kclvm-sema", + "kclvm-utils", + "located_yaml", + "once_cell", + "regex", + "rustc_lexer", + "serde_json", + "serde_yaml", "walkdir", ] +[[package]] +name = "kclvm-utils" +version = "0.7.2" + [[package]] name = "kclvm-version" -version = "0.1.0" +version = "0.7.2" +dependencies = [ + "vergen", +] [[package]] name = "kclvm_runtime_internal_macros" -version = "0.1.0" +version = "0.5.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", +] + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", ] [[package]] @@ -697,9 +1652,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libfuzzer-sys" @@ -724,9 +1679,18 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +dependencies = [ + "serde", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "llvm-sys" @@ -738,7 +1702,18 @@ dependencies = [ "lazy_static", "libc", "regex", - "semver", + "semver 0.11.0", +] + +[[package]] +name = "located_yaml" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bc68ee6f87a1be7fdba1dcfd854528371aa84a8390279b5d7a99d5da82add76" +dependencies = [ + "linked-hash-map", + "serde", + "yaml-rust", ] [[package]] @@ -753,13 +1728,41 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "lsp-server" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "f70570c1c29cf6654029b8fe201a5507c153f0d85be6f234d471d756bc36775a" dependencies = [ - "cfg-if 1.0.0", + "crossbeam-channel", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "lsp-types" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "matches" version = "0.1.9" @@ -805,6 +1808,60 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "miow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123" +dependencies = [ + "windows-sys 0.42.0", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "notify" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -841,15 +1898,39 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.12.0" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "oorandom" +version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" @@ -857,34 +1938,94 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ - "lock_api", - "parking_lot_core", + "lock_api", + "parking_lot_core 0.9.3", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall 0.2.13", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.13", + "smallvec", + "windows-sys 0.36.1", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "pcre2" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486aca7e74edb8cab09a48d461177f450a5cca3b55e61d139f7552190e2bbcf5" +dependencies = [ + "libc", + "log", + "pcre2-sys", + "thread_local", ] [[package]] -name = "parking_lot_core" -version = "0.9.3" +name = "pcre2-sys" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "ae234f441970dbd52d4e29bee70f3b56ca83040081cb2b55b7df772b16e0b06e" dependencies = [ - "cfg-if 1.0.0", + "cc", "libc", - "redox_syscall", - "smallvec", - "windows-sys", + "pkg-config", ] [[package]] -name = "pathdiff" -version = "0.2.1" +name = "percent-encoding" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" @@ -902,7 +2043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -937,7 +2078,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.95", ] [[package]] @@ -955,12 +2096,44 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.95", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -969,13 +2142,167 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] +[[package]] +name = "proc_macro_crate" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 1.0.95", + "tempfile", + "which", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.95", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "prost-wkt" +version = "0.4.1" +dependencies = [ + "chrono", + "inventory", + "prost", + "serde", + "serde_derive", + "serde_json", + "typetag", +] + +[[package]] +name = "prost-wkt-build" +version = "0.4.1" +dependencies = [ + "heck 0.4.1", + "prost", + "prost-build", + "prost-types", + "quote", +] + +[[package]] +name = "prost-wkt-types" +version = "0.4.1" +dependencies = [ + "chrono", + "prost", + "prost-build", + "prost-types", + "prost-wkt", + "prost-wkt-build", + "protoc-bin-vendored", + "regex", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "protoc-bin-vendored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005ca8623e5633e298ad1f917d8be0a44bcf406bf3cde3b80e63003e49a3f27d" +dependencies = [ + "protoc-bin-vendored-linux-aarch_64", + "protoc-bin-vendored-linux-ppcle_64", + "protoc-bin-vendored-linux-x86_32", + "protoc-bin-vendored-linux-x86_64", + "protoc-bin-vendored-macos-x86_64", + "protoc-bin-vendored-win32", +] + +[[package]] +name = "protoc-bin-vendored-linux-aarch_64" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb9fc9cce84c8694b6ea01cc6296617b288b703719b725b8c9c65f7c5874435" + +[[package]] +name = "protoc-bin-vendored-linux-ppcle_64" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d2a07dcf7173a04d49974930ccbfb7fd4d74df30ecfc8762cf2f895a094516" + +[[package]] +name = "protoc-bin-vendored-linux-x86_32" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54fef0b04fcacba64d1d80eed74a20356d96847da8497a59b0a0a436c9165b0" + +[[package]] +name = "protoc-bin-vendored-linux-x86_64" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8782f2ce7d43a9a5c74ea4936f001e9e8442205c244f7a3d4286bd4c37bc924" + +[[package]] +name = "protoc-bin-vendored-macos-x86_64" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5de656c7ee83f08e0ae5b81792ccfdc1d04e7876b1d9a38e6876a9e09e02537" + +[[package]] +name = "protoc-bin-vendored-win32" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9653c3ed92974e34c5a6e0a510864dab979760481714c172e0a34e437cb98804" + [[package]] name = "psm" version = "0.1.18" @@ -987,13 +2314,59 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] +[[package]] +name = "ra_ap_paths" +version = "0.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d780b450680460bd7ea3e2483dcf15a3ac0ce0ec028696caa342c577d65e5506" + +[[package]] +name = "ra_ap_stdx" +version = "0.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d776542bf771f4fdf40c21ced864bf213924d8a60d580c970715818471ebd74c" +dependencies = [ + "always-assert", + "libc", + "miow", + "winapi", +] + +[[package]] +name = "ra_ap_vfs" +version = "0.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cd60adecd0947e1dd41a3077713381aa0cdcba6dc8777300d7d5b83b9fbe84" +dependencies = [ + "fst", + "indexmap 1.9.3", + "ra_ap_paths", + "ra_ap_stdx", + "rustc-hash", +] + +[[package]] +name = "ra_ap_vfs-notify" +version = "0.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a680f2dbd796844ebeaa2a4d01ae209f412ddc2981f6512ab8bc9b471156e6cd" +dependencies = [ + "crossbeam-channel", + "jod-thread", + "notify", + "ra_ap_paths", + "ra_ap_vfs", + "tracing", + "walkdir", +] + [[package]] name = "rand" version = "0.3.23" @@ -1062,6 +2435,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.3", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -1077,17 +2459,47 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.13", + "thiserror", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", + "regex-automata 0.3.6", "regex-syntax", ] @@ -1098,19 +2510,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] -name = "regex-syntax" -version = "0.6.26" +name = "regex-automata" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "ron" @@ -1119,10 +2533,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678" dependencies = [ "base64", - "bitflags", + "bitflags 1.3.2", "serde", ] +[[package]] +name = "ropey" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5" +dependencies = [ + "smallvec", + "str_indices", +] + [[package]] name = "rust-crypto" version = "0.2.36" @@ -1133,9 +2557,15 @@ dependencies = [ "libc", "rand 0.3.23", "rustc-serialize", - "time", + "time 0.1.44", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1150,7 +2580,17 @@ checksum = "9974ab223660e61c1b4e7b43b827379df286736ca988308ce7e16f59f2d89246" dependencies = [ "crossbeam-deque", "either", - "rustc-rayon-core", + "rustc-rayon-core 0.3.2", +] + +[[package]] +name = "rustc-rayon" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81aadc8837ca6ecebe0fe1353f15df83b3b3cc2cf7a8afd571bc22aa121710" +dependencies = [ + "either", + "rustc-rayon-core 0.5.0", ] [[package]] @@ -1165,6 +2605,18 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rustc-rayon-core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67668daaf00e359c126f6dcb40d652d89b458a008c8afa727a42a2d20fca0b7f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1173,20 +2625,22 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc_data_structures" -version = "0.0.0" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c44a5f9188372885b2cafd1e0297755679e3fc451a6eccabba5ffd9b261d4c1e" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "cfg-if 0.1.10", "ena", - "indexmap", + "indexmap 1.9.3", "jobserver", "libc", "memmap2", - "parking_lot", + "parking_lot 0.12.0", "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon 0.3.2", + "rustc-rayon-core 0.3.2", "stable_deref_trait", "stacker", "tempfile", @@ -1194,6 +2648,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc_errors" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36ca70968783a8242b8dca63f0ee9bfbba57174760deb5c9972d52d8562d5a0" +dependencies = [ + "termcolor", + "winapi", +] + [[package]] name = "rustc_lexer" version = "0.1.0" @@ -1205,7 +2669,9 @@ dependencies = [ [[package]] name = "rustc_span" -version = "0.0.0" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee78969130992735ace193e2c463da2bddd275e90e648871198312a7aed7baf" dependencies = [ "cfg-if 0.1.10", "md-5", @@ -1218,10 +2684,76 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.10" +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.18", +] + +[[package]] +name = "rustix" +version = "0.38.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + +[[package]] +name = "salsa" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403" +dependencies = [ + "crossbeam-utils", + "indexmap 1.9.3", + "lock_api", + "log", + "oorandom", + "parking_lot 0.11.2", + "rustc-hash", + "salsa-macros", + "smallvec", +] + +[[package]] +name = "salsa-macros" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "cd3904a4ba0a9d0211816177fd34b04c7095443f8cdacd11175064fe541c8fe2" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.95", +] [[package]] name = "same-file" @@ -1244,15 +2776,51 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "self_cell" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.2", +] + +[[package]] +name = "self_cell" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser 0.7.0", +] + [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser", + "semver-parser 0.10.2", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "semver-parser" version = "0.10.2" @@ -1264,45 +2832,57 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.32", ] [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "serde_yaml" -version = "0.8.24" +version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ - "indexmap", + "indexmap 2.0.0", + "itoa", "ryu", "serde", - "yaml-rust", + "unsafe-libyaml", ] [[package]] @@ -1355,18 +2935,56 @@ dependencies = [ "digest 0.10.3", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "siphasher" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1386,11 +3004,84 @@ dependencies = [ "winapi", ] +[[package]] +name = "standback" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +dependencies = [ + "version_check", +] + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version 0.2.3", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn 1.0.95", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn 1.0.95", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + +[[package]] +name = "str_indices" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9557cb6521e8d009c51a8666f09356f4b817ba9ba0981a305bd86aee47bd35c" + [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "suggestions" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "5441c382482e49aaac2c3ea9cbcd24290531246e879ee94af5dfc4b144f11e80" +dependencies = [ + "strsim", +] [[package]] name = "syn" @@ -1403,6 +3094,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -1411,22 +3113,21 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", "unicode-xid", ] [[package]] name = "tempfile" -version = "3.3.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ "cfg-if 1.0.0", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.48.0", ] [[package]] @@ -1460,15 +3161,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.31" @@ -1486,7 +3178,17 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.95", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", ] [[package]] @@ -1505,10 +3207,171 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "time" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +dependencies = [ + "const_fn", + "libc", + "standback", + "stdweb", + "time-macros 0.1.1", + "version_check", "winapi", ] +[[package]] +name = "time" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" +dependencies = [ + "deranged", + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros 0.2.11", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +dependencies = [ + "proc-macro-hack", + "time-macros-impl", +] + +[[package]] +name = "time-macros" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +dependencies = [ + "time-core", +] + +[[package]] +name = "time-macros-impl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "standback", + "syn 1.0.95", +] + +[[package]] +name = "tinystr" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef" +dependencies = [ + "displaydoc", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot 0.12.0", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-test" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" +dependencies = [ + "async-stream", + "bytes", + "futures-core", + "tokio", + "tokio-stream", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.9" @@ -1520,11 +3383,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1532,29 +3394,62 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.32", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "type-map" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" +dependencies = [ + "rustc-hash", ] [[package]] -name = "tracing-core" -version = "0.1.26" +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "typetag" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "aec6850cc671cd0cfb3ab285465e48a3b927d9de155051c35797446b32f9169f" dependencies = [ - "lazy_static", + "erased-serde", + "inventory", + "once_cell", + "serde", + "typetag-impl", ] [[package]] -name = "typenum" -version = "1.15.0" +name = "typetag-impl" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "30c49a6815b4f8379c36f06618bc1b80ca77aaf8a3fd4d8549dca6fdb016000f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] [[package]] name = "ucd-trie" @@ -1594,6 +3489,49 @@ dependencies = [ "unic-ucd-version", ] +[[package]] +name = "unic-langid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f" +dependencies = [ + "unic-langid-impl", + "unic-langid-macros", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff" +dependencies = [ + "tinystr", +] + +[[package]] +name = "unic-langid-macros" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe" +dependencies = [ + "proc-macro-hack", + "tinystr", + "unic-langid-impl", + "unic-langid-macros-impl", +] + +[[package]] +name = "unic-langid-macros-impl" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8" +dependencies = [ + "proc-macro-hack", + "quote", + "syn 1.0.95", + "unic-langid-impl", +] + [[package]] name = "unic-ucd-bidi" version = "0.9.0" @@ -1626,6 +3564,12 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicode-bidi" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" + [[package]] name = "unicode-casing" version = "0.1.0" @@ -1638,6 +3582,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.9" @@ -1657,10 +3616,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d6678d7916394abad0d4b19df4d3802e1fd84abd7d701f39b75ee71b9e8cf1" [[package]] -name = "vec_map" -version = "0.8.2" +name = "unsafe-libyaml" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +dependencies = [ + "getrandom", +] + +[[package]] +name = "vergen" +version = "8.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "bbc5ad0d9d26b2c49a5ab7da76c3e79d3ee37e7821799f8223fcb8f2f391a2e7" +dependencies = [ + "anyhow", + "rustc_version 0.4.0", + "rustversion", + "time 0.3.25", +] [[package]] name = "version_check" @@ -1685,6 +3683,77 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1722,43 +3791,256 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -1767,3 +4049,38 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] diff --git a/kclvm/tests/fuzz/Cargo.toml b/kclvm/tests/fuzz/Cargo.toml index be7618113..75867f156 100644 --- a/kclvm/tests/fuzz/Cargo.toml +++ b/kclvm/tests/fuzz/Cargo.toml @@ -10,7 +10,7 @@ cargo-fuzz = true [dependencies] kclvm-runtime = {path = "../../runtime"} -kclvm-parser = {path="../../parser", version="0.1.0"} +kclvm-parser = {path = "../../parser"} libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } arbitrary = { version = "1", features = ["derive"] } serde_json = "1.0" diff --git a/kclvm/tests/integration/grammar/test_grammar.py b/kclvm/tests/integration/grammar/test_grammar.py index 8f6f496b0..3e2cf928b 100644 --- a/kclvm/tests/integration/grammar/test_grammar.py +++ b/kclvm/tests/integration/grammar/test_grammar.py @@ -110,7 +110,7 @@ def read_settings_file(settings_file_name): def test_grammar(test_dir): print("Testing {}".format(test_dir)) test_settings = read_settings_file(os.path.join(test_dir, SETTINGS_FILE)) - kcl_command = ["kcl", "--target", "native", TEST_FILE] + kcl_command = ["kclvm_cli", "run", TEST_FILE] if test_settings and test_settings["kcl_options"]: kcl_command.extend(test_settings["kcl_options"].split()) process = subprocess.Popen( diff --git a/kclvm/tests/integration/konfig/test_konfig_kcl.py b/kclvm/tests/integration/konfig/test_konfig_kcl.py index 5e79bf027..0461deda6 100644 --- a/kclvm/tests/integration/konfig/test_konfig_kcl.py +++ b/kclvm/tests/integration/konfig/test_konfig_kcl.py @@ -15,6 +15,7 @@ CI_TEST_DIR = "ci-test" STDOUT_GOLDEN = "stdout.golden.yaml" SETTINGS_FILE = "settings.yaml" +SKIP_TESTS = ["kcl-vault-csi"] ROOT_STR = "test/integration/konfig" ROOT = str(Path(__file__).parent.parent.parent.parent.parent.joinpath(ROOT_STR)) @@ -29,7 +30,10 @@ def find_test_dirs(): for root, _, files in os.walk(root_dir): for name in files: if name == TEST_FILE: - result.append(root) + if any([p in SKIP_TESTS for p in Path(root).parts]): + print(f"Skip {root}") + else: + result.append(root) return result diff --git a/kclvm/plugin/kclvm_runtime.py b/kclvm/tests/test_units/runtime/kclvm_runtime.py similarity index 85% rename from kclvm/plugin/kclvm_runtime.py rename to kclvm/tests/test_units/runtime/kclvm_runtime.py index f3d53375f..db00c11bc 100644 --- a/kclvm/plugin/kclvm_runtime.py +++ b/kclvm/tests/test_units/runtime/kclvm_runtime.py @@ -15,12 +15,12 @@ def _find_default_dylib_path() -> str: f"{_executable_root}/bin/libkclvm_cli_cdylib.dylib", f"{_executable_root}/bin/libkclvm_cli_cdylib.so", f"{_executable_root}\\bin\\kclvm_cli_cdylib.dll", - f"{os.path.dirname(__file__)}/../target/release/libkclvm_cli_cdylib.dylib", - f"{os.path.dirname(__file__)}/../target/release/libkclvm_cli_cdylib.so", - f"{os.path.dirname(__file__)}\\..\\target\\release\\kclvm_cli_cdylib.dll", - f"{os.path.dirname(__file__)}/../target/debug/libkclvm_cli_cdylib.dylib", - f"{os.path.dirname(__file__)}/../target/debug/libkclvm_cli_cdylib.so", - f"{os.path.dirname(__file__)}\\..\\target\\debug\\kclvm_cli_cdylib.dll", + f"{os.path.dirname(__file__)}/../../../target/release/libkclvm_cli_cdylib.dylib", + f"{os.path.dirname(__file__)}/../../../target/release/libkclvm_cli_cdylib.so", + f"{os.path.dirname(__file__)}\\..\\..\\..\\target\\release\\kclvm_cli_cdylib.dll", + f"{os.path.dirname(__file__)}/../../../target/debug/libkclvm_cli_cdylib.dylib", + f"{os.path.dirname(__file__)}/../../../target/debug/libkclvm_cli_cdylib.so", + f"{os.path.dirname(__file__)}\\..\\..\\..\\target\\debug\\kclvm_cli_cdylib.dll", ] for s in pathList: diff --git a/kclvm/tests/test_units/runtime/str/Makefile b/kclvm/tests/test_units/runtime/str/Makefile index 08fb119e3..d3b534b28 100644 --- a/kclvm/tests/test_units/runtime/str/Makefile +++ b/kclvm/tests/test_units/runtime/str/Makefile @@ -2,6 +2,6 @@ default: python3 -m black . - kclvm -m pytest + python3 -m pytest clean: diff --git a/kclvm/tools/Cargo.toml b/kclvm/tools/Cargo.toml index 647076325..acdf895e4 100644 --- a/kclvm/tools/Cargo.toml +++ b/kclvm/tools/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-tools" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -23,15 +23,20 @@ kclvm-query = {path = "../query"} kclvm-runner = {path = "../runner"} kclvm-runtime = {path = "../runtime"} kclvm-driver = {path = "../driver"} +kclvm-utils ={ path = "../utils"} serde_json = "1.0.85" -serde_yaml = "0.9.13" +serde_yaml = "0.9.32" once_cell = "1.15.0" regex = "1.3" +json-spanned-value = "0.2.2" +compiler_base_span = "0.0.1" +located_yaml = "0.2.1" [dev-dependencies] pretty_assertions = "1.2.1" criterion = "0.3" +insta = "1.8.0" [[bench]] name = "benchmark" diff --git a/kclvm/tools/benches/benchmark.rs b/kclvm/tools/benches/benchmark.rs index f9e7d64e6..0a8899c6e 100644 --- a/kclvm/tools/benches/benchmark.rs +++ b/kclvm/tools/benches/benchmark.rs @@ -1,6 +1,10 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kclvm_query::override_file; use kclvm_tools::format::{format, FormatOptions}; +use std::{ + fmt, + time::{Duration, Instant}, +}; pub fn criterion_benchmark_override(c: &mut Criterion) { c.bench_function("override", |b| { @@ -29,3 +33,77 @@ criterion_group!( criterion_benchmark_format ); criterion_main!(benches); + +pub struct StopWatch { + time: Instant, +} + +pub struct StopWatchSpan { + pub time: Duration, +} + +impl StopWatch { + pub fn start() -> StopWatch { + let time = Instant::now(); + StopWatch { time } + } + + pub fn elapsed(&mut self) -> StopWatchSpan { + let time = self.time.elapsed(); + + StopWatchSpan { time } + } +} + +impl fmt::Display for StopWatchSpan { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:.2?}", self.time)?; + Ok(()) + } +} + +/// Utility for writing benchmark tests. +/// +/// If you need to benchmark the entire test, you can directly add the macro `#[bench_test]` like this: +/// ``` +/// #[test] +/// #[bench_test] +/// fn benchmark_foo() { +/// actual_work(analysis) +/// } +/// ``` +/// +/// If you need to skip some preparation stages and only test some parts of test, you can use the `bench()` method. +/// A benchmark test looks like this: +/// +/// ``` +/// #[test] +/// fn benchmark_foo() { +/// let data = bench_fixture::some_fixture(); +/// let analysis = some_setup(); +/// +/// { +/// let _b = bench("foo"); +/// actual_work(analysis) +/// }; +/// } +/// ``` +/// +/// +pub fn bench(label: &'static str) -> impl Drop { + struct Bencher { + sw: StopWatch, + label: &'static str, + } + + impl Drop for Bencher { + fn drop(&mut self) { + eprintln!("{}: {}", self.label, self.sw.elapsed()); + } + } + + Bencher { + sw: StopWatch::start(), + label, + } +} diff --git a/kclvm/tools/benches/proc_macro_crate/Cargo.toml b/kclvm/tools/benches/proc_macro_crate/Cargo.toml new file mode 100644 index 000000000..a112f709b --- /dev/null +++ b/kclvm/tools/benches/proc_macro_crate/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "proc_macro_crate" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = "1.0.7" +quote = "1" +syn = { version = "2.0.29", features = ["full","extra-traits"] } diff --git a/kclvm/tools/benches/proc_macro_crate/src/lib.rs b/kclvm/tools/benches/proc_macro_crate/src/lib.rs new file mode 100644 index 000000000..6452dc46b --- /dev/null +++ b/kclvm/tools/benches/proc_macro_crate/src/lib.rs @@ -0,0 +1,32 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{parse_macro_input, ItemFn}; + +#[proc_macro_attribute] +pub fn bench_test(_attr: TokenStream, item: TokenStream) -> TokenStream { + let mut input_fn = parse_macro_input!(item as ItemFn); + + let fn_name = &input_fn.sig.ident; + let fn_body = &input_fn.block; + + let timing_code = quote! { + { + let start_time = std::time::Instant::now(); + let result = #fn_body; + let end_time = std::time::Instant::now(); + let time = (end_time - start_time).as_micros(); + println!("{} took {} μs", stringify!(#fn_name), (end_time - start_time).as_micros()); + // 200 ms + assert!(time < 200000, "Bench mark test failed"); + result + } + }; + + input_fn.block = Box::new(syn::parse2(timing_code).unwrap()); + + let output = quote! { + #input_fn + }; + + output.into() +} diff --git a/kclvm/tools/src/LSP/Cargo.toml b/kclvm/tools/src/LSP/Cargo.toml index ef7e0924e..ba60c79b6 100644 --- a/kclvm/tools/src/LSP/Cargo.toml +++ b/kclvm/tools/src/LSP/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kcl-language-server" -version = "0.1.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -9,7 +9,7 @@ edition = "2021" chrono = "0.4.19" indexmap = "1.0" chumsky = "0.9.0" -env_logger = "0.10.0" +env_logger = "0.11.2" ropey = "1.3.2" tokio = { version = "1.17.0", features = ["full"] } tokio-test = "0.4.2" @@ -18,24 +18,31 @@ dashmap = "5.1.0" log = "0.4.14" im-rc = "15.0.0" rustc_lexer = "0.1.0" +clap = "4.3.0" +maplit = "1.0.2" -kclvm-tools = {path = "../../../tools"} -kclvm-error = {path = "../../../error"} -kclvm-config ={ path = "../../../config"} -kclvm-driver = {path = "../../../driver"} -kclvm-parser = {path = "../../../parser"} -kclvm-sema = {path = "../../../sema"} -kclvm-ast = {path = "../../../ast"} -kclvm-utils = {path = "../../../utils"} -compiler_base_session = {path = "../../../../compiler_base/session"} +kclvm-tools = { path = "../../../tools" } +kclvm-error = { path = "../../../error" } +kclvm-config = { path = "../../../config" } +kclvm-driver = { path = "../../../driver" } +kclvm-parser = { path = "../../../parser" } +kclvm-sema = { path = "../../../sema" } +kclvm-ast = { path = "../../../ast" } +kclvm-utils = { path = "../../../utils" } +kclvm-version = { path = "../../../version" } +compiler_base_session = { path = "../../../../compiler_base/session" } +kclvm-query = { path = "../../../query" } +kclvm-span = { path = "../../../span" } lsp-server = { version = "0.6.0", default-features = false } -anyhow = { version = "1.0", default-features = false, features=["std"] } +anyhow = { version = "1.0", default-features = false, features = ["std"] } crossbeam-channel = { version = "0.5.7", default-features = false } ra_ap_vfs = "0.0.149" +ra_ap_vfs-notify = "0.0.149" lsp-types = { version = "0.93.0", default-features = false } threadpool = { version = "1.8.1", default-features = false } salsa = { version = "0.16.1", default-features = false } serde_json = { version = "1.0", default-features = false } parking_lot = { version = "0.12.0", default-features = false } rustc-hash = { version = "1.1.0", default-features = false } +proc_macro_crate = { path = "../../benches/proc_macro_crate" } diff --git a/kclvm/tools/src/LSP/src/analysis.rs b/kclvm/tools/src/LSP/src/analysis.rs index 2532252fb..67df4039c 100644 --- a/kclvm/tools/src/LSP/src/analysis.rs +++ b/kclvm/tools/src/LSP/src/analysis.rs @@ -1,6 +1,9 @@ use crate::db::AnalysisDatabase; +use parking_lot::RwLock; +use ra_ap_vfs::FileId; +use std::{collections::HashMap, sync::Arc}; #[derive(Default)] pub struct Analysis { - _db: AnalysisDatabase, + pub db: Arc>>, } diff --git a/kclvm/tools/src/LSP/src/capabilities.rs b/kclvm/tools/src/LSP/src/capabilities.rs index e853c8762..6f0f0086c 100644 --- a/kclvm/tools/src/LSP/src/capabilities.rs +++ b/kclvm/tools/src/LSP/src/capabilities.rs @@ -1,16 +1,39 @@ use lsp_types::{ - ClientCapabilities, CompletionOptions, HoverProviderCapability, OneOf, ServerCapabilities, - TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions, + ClientCapabilities, CodeActionKind, CodeActionOptions, CodeActionProviderCapability, + CompletionOptions, HoverProviderCapability, OneOf, SemanticTokensFullOptions, + SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities, TextDocumentSyncCapability, + TextDocumentSyncKind, WorkDoneProgressOptions, }; +use crate::semantic_token::LEGEND_TYPE; + /// Returns the capabilities of this LSP server implementation given the capabilities of the client. -pub fn server_capabilities(_client_caps: &ClientCapabilities) -> ServerCapabilities { +#[allow(dead_code)] +pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities { ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)), + semantic_tokens_provider: Some( + lsp_types::SemanticTokensServerCapabilities::SemanticTokensOptions( + SemanticTokensOptions { + work_done_progress_options: WorkDoneProgressOptions::default(), + legend: SemanticTokensLegend { + token_types: LEGEND_TYPE.into(), + token_modifiers: vec![], + }, + range: Some(false), + full: Some(SemanticTokensFullOptions::Bool(true)), + }, + ), + ), document_symbol_provider: Some(OneOf::Left(true)), completion_provider: Some(CompletionOptions { resolve_provider: None, - trigger_characters: Some(vec![String::from(".")]), + trigger_characters: Some(vec![ + String::from("."), + String::from("="), + String::from(":"), + String::from("\n"), + ]), all_commit_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None, @@ -18,6 +41,27 @@ pub fn server_capabilities(_client_caps: &ClientCapabilities) -> ServerCapabilit }), hover_provider: Some(HoverProviderCapability::Simple(true)), definition_provider: Some(OneOf::Left(true)), + code_action_provider: Some( + client_caps + .text_document + .as_ref() + .and_then(|it| it.code_action.as_ref()) + .and_then(|it| it.code_action_literal_support.as_ref()) + .map_or(CodeActionProviderCapability::Simple(true), |_| { + CodeActionProviderCapability::Options(CodeActionOptions { + // Advertise support for all built-in CodeActionKinds. + // Ideally we would base this off of the client capabilities + // but the client is supposed to fall back gracefully for unknown values. + code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]), + resolve_provider: None, + work_done_progress_options: Default::default(), + }) + }), + ), + document_formatting_provider: Some(OneOf::Left(true)), + document_range_formatting_provider: Some(OneOf::Left(true)), + references_provider: Some(OneOf::Left(true)), + rename_provider: Some(OneOf::Left(true)), ..Default::default() } } diff --git a/kclvm/tools/src/LSP/src/completion.rs b/kclvm/tools/src/LSP/src/completion.rs index e40e592ed..48e9b1928 100644 --- a/kclvm/tools/src/LSP/src/completion.rs +++ b/kclvm/tools/src/LSP/src/completion.rs @@ -1,85 +1,583 @@ //! Complete for KCL -//! Github Issue: https://github.com/kcl-lang/kcl/issues/476 -//! Now supports code completion in treigger mode (triggered when user enters `.`), +//! Now supports code completion in trigger mode (triggered when user enters `.`, `:` and `=`), schema attr and global variables //! and the content of the completion includes: -//! + import path -//! + schema attr -//! + builtin function(str function) -//! + defitions in pkg -//! + system module functions +//! + variable +//! + schema attr name +//! + dot(.) +//! + import path +//! + schema attr +//! + builtin function(str function) +//! + definitions in pkg +//! + system module functions +//! + assign(=, :) +//! + schema attr value +//! + variable value +//! + new line +//! + schema init use std::io; use std::{fs, path::Path}; +use crate::goto_def::find_def_with_gs; use indexmap::IndexSet; -use kclvm_ast::ast::{Expr, ImportStmt, Program, Stmt}; +use kclvm_ast::ast::{ImportStmt, Program, Stmt}; + +use kclvm_ast::MAIN_PKG; use kclvm_config::modfile::KCL_FILE_EXTENSION; +use kclvm_sema::core::global_state::GlobalState; use kclvm_error::Position as KCLPos; -use kclvm_sema::builtin::{ - get_system_module_members, STANDARD_SYSTEM_MODULES, STRING_MEMBER_FUNCTIONS, -}; -use kclvm_sema::resolver::scope::ProgramScope; -use lsp_types::CompletionItem; +use kclvm_sema::builtin::{BUILTIN_FUNCTIONS, STANDARD_SYSTEM_MODULES}; +use kclvm_sema::core::package::ModuleInfo; +use kclvm_sema::resolver::doc::{parse_doc_string, Doc}; +use kclvm_sema::ty::{FunctionType, SchemaType, Type}; +use lsp_types::{CompletionItem, CompletionItemKind, InsertTextFormat}; + +use crate::util::{get_real_path_from_external, is_in_schema_expr}; +use crate::util::{inner_most_expr_in_stmt, is_in_docstring}; -use crate::goto_def::get_identifier_last_name; -use crate::{goto_def::find_objs_in_program_scope, util::inner_most_expr_in_stmt}; +#[derive(Debug, Clone, PartialEq, Hash, Eq)] +pub enum KCLCompletionItemKind { + Function, + Variable, + File, + Dir, + Schema, + SchemaAttr, + Module, + Doc, +} + +impl From for CompletionItemKind { + fn from(val: KCLCompletionItemKind) -> Self { + match val { + KCLCompletionItemKind::Function => CompletionItemKind::FUNCTION, + KCLCompletionItemKind::Variable => CompletionItemKind::VARIABLE, + KCLCompletionItemKind::File => CompletionItemKind::FILE, + KCLCompletionItemKind::Schema => CompletionItemKind::CLASS, + KCLCompletionItemKind::SchemaAttr => CompletionItemKind::FIELD, + KCLCompletionItemKind::Module => CompletionItemKind::MODULE, + KCLCompletionItemKind::Dir => CompletionItemKind::FOLDER, + KCLCompletionItemKind::Doc => CompletionItemKind::SNIPPET, + } + } +} + +/// Abstraction of CompletionItem in KCL +#[derive(Debug, Clone, PartialEq, Hash, Eq, Default)] +pub(crate) struct KCLCompletionItem { + pub label: String, + pub detail: Option, + pub documentation: Option, + pub kind: Option, + pub insert_text: Option, +} /// Computes completions at the given position. pub(crate) fn completion( trigger_character: Option, program: &Program, pos: &KCLPos, - prog_scope: &ProgramScope, + gs: &GlobalState, ) -> Option { - if let Some('.') = trigger_character { - completion_dot(program, pos, prog_scope) - } else { - // todo: Complete identifiers such as attr, variables, types, etc. - None + match trigger_character { + Some(c) => match c { + '.' => completion_dot(program, pos, gs), + '=' | ':' => completion_assign(pos, gs), + '\n' => completion_newline(program, pos, gs), + _ => None, + }, + None => { + let mut completions: IndexSet = IndexSet::new(); + // Complete builtin pkgs if in import stmt + completions.extend(completion_import_builtin_pkg(program, pos)); + if !completions.is_empty() { + return Some(into_completion_items(&completions).into()); + } + + // Complete import pkgs name + if let Some(pkg_info) = gs.get_packages().get_module_info(&pos.filename) { + completions.extend(pkg_info.get_imports().keys().map(|key| KCLCompletionItem { + label: key.clone(), + detail: None, + documentation: None, + kind: Some(KCLCompletionItemKind::Module), + insert_text: None, + })); + } + + if let Some(scope) = gs.look_up_scope(pos) { + // Complete builtin functions in root scope and lambda + match scope.get_kind() { + kclvm_sema::core::scope::ScopeKind::Local => { + if let Some(local_scope) = gs.get_scopes().try_get_local_scope(&scope) { + match local_scope.get_kind() { + kclvm_sema::core::scope::LocalSymbolScopeKind::Lambda => { + completions.extend(BUILTIN_FUNCTIONS.iter().map( + |(name, ty)| KCLCompletionItem { + label: func_ty_complete_label( + name, + &ty.into_func_type(), + ), + detail: Some( + ty.into_func_type().func_signature_str(name), + ), + documentation: ty.ty_doc(), + kind: Some(KCLCompletionItemKind::Function), + insert_text: Some(func_ty_complete_insert_text( + name, + &ty.into_func_type(), + )), + }, + )); + } + _ => {} + } + } + } + kclvm_sema::core::scope::ScopeKind::Root => { + completions.extend(BUILTIN_FUNCTIONS.iter().map(|(name, ty)| { + KCLCompletionItem { + label: func_ty_complete_label(name, &ty.into_func_type()), + detail: Some(ty.into_func_type().func_signature_str(name)), + documentation: ty.ty_doc(), + kind: Some(KCLCompletionItemKind::Function), + insert_text: Some(func_ty_complete_insert_text( + name, + &ty.into_func_type(), + )), + } + })); + } + } + + // Complete all usable symbol obj in inner most scope + if let Some(defs) = gs.get_all_defs_in_scope(scope) { + for symbol_ref in defs { + match gs.get_symbols().get_symbol(symbol_ref) { + Some(def) => { + let sema_info = def.get_sema_info(); + let name = def.get_name(); + match &sema_info.ty { + Some(ty) => match symbol_ref.get_kind() { + kclvm_sema::core::symbol::SymbolKind::Schema => { + let schema_ty = ty.into_schema_type(); + // complete schema type + completions.insert(schema_ty_to_type_complete_item( + &schema_ty, + )); + // complete schema value + completions.insert(schema_ty_to_value_complete_item( + &schema_ty, + )); + } + kclvm_sema::core::symbol::SymbolKind::Package => { + completions.insert(KCLCompletionItem { + label: name, + detail: Some(ty.ty_str()), + documentation: sema_info.doc.clone(), + kind: Some(KCLCompletionItemKind::Module), + insert_text: None, + }); + } + _ => { + let detail = match &ty.kind { + kclvm_sema::ty::TypeKind::Function(func_ty) => { + func_ty.func_signature_str(&name) + } + _ => ty.ty_str(), + }; + completions.insert(KCLCompletionItem { + label: name, + detail: Some(detail), + documentation: sema_info.doc.clone(), + kind: type_to_item_kind(ty), + insert_text: None, + }); + } + }, + None => {} + } + } + None => {} + } + } + } + } + + Some(into_completion_items(&completions).into()) + } } } fn completion_dot( program: &Program, pos: &KCLPos, - prog_scope: &ProgramScope, + gs: &GlobalState, ) -> Option { - // Get the position of trigger_character '.' - let pos = &KCLPos { + let mut items: IndexSet = IndexSet::new(); + + // get pre position of trigger character '.' + let pre_pos = KCLPos { filename: pos.filename.clone(), line: pos.line, column: pos.column.map(|c| c - 1), }; - match program.pos_to_stmt(pos) { - Some(node) => match node.node { - Stmt::Import(stmt) => completion_for_import(&stmt, pos, prog_scope, program), + if let Some(stmt) = program.pos_to_stmt(&pre_pos) { + match stmt.node { + Stmt::Import(stmt) => return completion_import(&stmt, &pos, program), _ => { - let expr = inner_most_expr_in_stmt(&node.node, pos, None).0; - match expr { - Some(node) => { - let items = get_completion_items(&node.node, prog_scope); - Some(into_completion_items(&items).into()) + let (expr, _) = inner_most_expr_in_stmt(&stmt.node, &pos, None); + if let Some(node) = expr { + match node.node { + // if the complete trigger character in string, skip it + kclvm_ast::ast::Expr::StringLit(_) + | kclvm_ast::ast::Expr::JoinedString(_) => { + return Some(into_completion_items(&items).into()) + } + _ => {} } - None => None, } } + } + } + + // look_up_exact_symbol + let mut def = find_def_with_gs(&pre_pos, gs, true); + if def.is_none() { + def = find_def_with_gs(pos, gs, false); + } + + match def { + Some(def_ref) => { + if let Some(def) = gs.get_symbols().get_symbol(def_ref) { + let module_info = gs.get_packages().get_module_info(&pos.filename); + let attrs = def.get_all_attributes(gs.get_symbols(), module_info); + for attr in attrs { + let attr_def = gs.get_symbols().get_symbol(attr); + if let Some(attr_def) = attr_def { + let sema_info = attr_def.get_sema_info(); + let name = attr_def.get_name(); + match &sema_info.ty { + Some(attr_ty) => { + let label: String = match &attr_ty.kind { + kclvm_sema::ty::TypeKind::Function(func_ty) => { + func_ty_complete_label(&name, func_ty) + } + _ => name.clone(), + }; + let insert_text = match &attr_ty.kind { + kclvm_sema::ty::TypeKind::Function(func_ty) => { + Some(func_ty_complete_insert_text(&name, func_ty)) + } + _ => None, + }; + let kind = match &def.get_sema_info().ty { + Some(symbol_ty) => match &symbol_ty.kind { + kclvm_sema::ty::TypeKind::Schema(_) => { + Some(KCLCompletionItemKind::SchemaAttr) + } + _ => type_to_item_kind(attr_ty), + }, + None => type_to_item_kind(attr_ty), + }; + let documentation = match &sema_info.doc { + Some(doc) => { + if doc.is_empty() { + None + } else { + Some(doc.clone()) + } + } + None => None, + }; + items.insert(KCLCompletionItem { + label, + detail: Some(format!("{}: {}", name, attr_ty.ty_str())), + documentation, + kind, + insert_text, + }); + } + None => { + items.insert(KCLCompletionItem { + label: name, + detail: None, + documentation: None, + kind: None, + insert_text: None, + }); + } + } + } + } + } + } + None => {} + } + Some(into_completion_items(&items).into()) +} + +/// Get completion items for trigger '=' or ':' +/// Now, just completion for schema attr value +fn completion_assign(pos: &KCLPos, gs: &GlobalState) -> Option { + let mut items = IndexSet::new(); + if let Some(symbol_ref) = find_def_with_gs(pos, gs, false) { + if let Some(symbol) = gs.get_symbols().get_symbol(symbol_ref) { + if let Some(def) = symbol.get_definition() { + match def.get_kind() { + kclvm_sema::core::symbol::SymbolKind::Attribute => { + let sema_info = symbol.get_sema_info(); + match &sema_info.ty { + Some(ty) => { + items.extend( + ty_complete_label( + ty, + gs.get_packages().get_module_info(&pos.filename), + ) + .iter() + .map(|label| { + KCLCompletionItem { + label: format!(" {}", label), + detail: Some(format!( + "{}: {}", + symbol.get_name(), + ty.ty_str() + )), + kind: Some(KCLCompletionItemKind::Variable), + documentation: sema_info.doc.clone(), + insert_text: None, + } + }), + ); + return Some(into_completion_items(&items).into()); + } + None => {} + } + } + _ => {} + } + } + } + } + None +} + +fn completion_newline( + program: &Program, + pos: &KCLPos, + gs: &GlobalState, +) -> Option { + let mut completions: IndexSet = IndexSet::new(); + + if let Some((doc, schema)) = is_in_docstring(program, pos) { + let doc = parse_doc_string(&doc.node); + if doc.summary.is_empty() && doc.attrs.is_empty() && doc.examples.is_empty() { + // empty docstring, provide total completion + let doc_parsed = Doc::new_from_schema_stmt(&schema); + let label = doc_parsed.to_doc_string(); + // generate docstring from doc + completions.insert(KCLCompletionItem { + label, + detail: Some("generate docstring".to_string()), + documentation: Some(format!("docstring for {}", schema.name.node.clone())), + kind: Some(KCLCompletionItemKind::Doc), + insert_text: None, + }); + } + return Some(into_completion_items(&completions).into()); + } + + // todo: judge based on scope kind instead of `is_in_schema_expr` + if let Some(_) = is_in_schema_expr(program, pos) { + // Complete schema attr when input newline in schema + if let Some(scope) = gs.look_up_scope(pos) { + if let Some(defs) = gs.get_all_defs_in_scope(scope) { + for symbol_ref in defs { + match gs.get_symbols().get_symbol(symbol_ref) { + Some(def) => { + let sema_info = def.get_sema_info(); + let name = def.get_name(); + match symbol_ref.get_kind() { + kclvm_sema::core::symbol::SymbolKind::Attribute => { + completions.insert(KCLCompletionItem { + label: name.clone(), + detail: sema_info + .ty + .as_ref() + .map(|ty| format!("{}: {}", name, ty.ty_str())), + documentation: match &sema_info.doc { + Some(doc) => { + if doc.is_empty() { + None + } else { + Some(doc.clone()) + } + } + None => None, + }, + kind: Some(KCLCompletionItemKind::SchemaAttr), + insert_text: None, + }); + } + _ => {} + } + } + None => {} + } + } + } + } + } + Some(into_completion_items(&completions).into()) +} + +fn completion_import_builtin_pkg(program: &Program, pos: &KCLPos) -> IndexSet { + let mut completions: IndexSet = IndexSet::new(); + // completion position not contained in import stmt + // import + // | | | <- input `m` here for complete `math` + // |<----------->| <- import stmt only contains this range, so we need to check the beginning of line + let line_start_pos = &KCLPos { + filename: pos.filename.clone(), + line: pos.line, + column: Some(0), + }; + + if let Some(node) = program.pos_to_stmt(line_start_pos) { + if let Stmt::Import(_) = node.node { + completions.extend(STANDARD_SYSTEM_MODULES.iter().map(|s| KCLCompletionItem { + label: s.to_string(), + detail: None, + documentation: None, + kind: Some(KCLCompletionItemKind::Module), + insert_text: None, + })) + } + } + completions +} + +/// Complete schema value +/// +/// ```no_check +/// #[cfg(not(test))] +/// p = P +/// ``` +/// complete to +/// ```no_check +/// #[cfg(not(test))] +/// p = Person(param1, param2){} +/// ``` +fn schema_ty_to_value_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem { + let param = schema_ty.func.params.clone(); + let label = format!( + "{}{}{}", + schema_ty.name.clone(), + if param.is_empty() { + "".to_string() + } else { + format!( + "({})", + param + .iter() + .map(|p| p.name.clone()) + .collect::>() + .join(", ") + ) }, - None => None, + "{}" + ); + let detail = { + let mut details = vec![]; + details.push(schema_ty.schema_ty_signature_str()); + details.push("Attributes:".to_string()); + for (name, attr) in &schema_ty.attrs { + details.push(format!( + "{}{}:{}", + name, + if attr.is_optional { "?" } else { "" }, + format!(" {}", attr.ty.ty_str()), + )); + } + details.join("\n") + }; + let insert_text = format!( + "{}{}{}", + schema_ty.name.clone(), + if param.is_empty() { + "".to_string() + } else { + format!( + "({})", + param + .iter() + .enumerate() + .map(|(idx, p)| format!("${{{}:{}}}", idx + 1, p.name.clone())) + .collect::>() + .join(", ") + ) + }, + "{}" + ); + KCLCompletionItem { + label, + detail: Some(detail), + documentation: Some(schema_ty.doc.clone()), + kind: Some(KCLCompletionItemKind::Schema), + insert_text: Some(insert_text), + } +} + +/// Complete schema type +/// +/// ```no_check +/// #[cfg(not(test))] +/// p: P +/// ``` +/// complete to +/// ```no_check +/// #[cfg(not(test))] +/// p: Person +/// ``` +fn schema_ty_to_type_complete_item(schema_ty: &SchemaType) -> KCLCompletionItem { + let detail = { + let mut details = vec![]; + details.push(schema_ty.schema_ty_signature_str()); + details.push("Attributes:".to_string()); + for (name, attr) in &schema_ty.attrs { + details.push(format!( + "{}{}:{}", + name, + if attr.is_optional { "?" } else { "" }, + format!(" {}", attr.ty.ty_str()), + )); + } + details.join("\n") + }; + KCLCompletionItem { + label: schema_ty.name.clone(), + detail: Some(detail), + documentation: Some(schema_ty.doc.clone()), + kind: Some(KCLCompletionItemKind::Schema), + insert_text: None, } } -fn completion_for_import( +fn completion_import( stmt: &ImportStmt, _pos: &KCLPos, - _prog_scope: &ProgramScope, program: &Program, ) -> Option { - let mut items: IndexSet = IndexSet::new(); - let pkgpath = &stmt.path; - let real_path = - Path::new(&program.root).join(pkgpath.replace('.', &std::path::MAIN_SEPARATOR.to_string())); + let mut items: IndexSet = IndexSet::new(); + let pkgpath = &stmt.path.node; + let mut real_path = + Path::new(&program.root).join(pkgpath.replace('.', std::path::MAIN_SEPARATOR_STR)); + if !real_path.exists() { + real_path = + get_real_path_from_external(&stmt.pkg_name, pkgpath, program.root.clone().into()); + } if real_path.is_dir() { if let Ok(entries) = fs::read_dir(real_path) { let mut entries = entries @@ -90,18 +588,29 @@ fn completion_for_import( for path in entries { let filename = path.file_name().unwrap().to_str().unwrap().to_string(); if path.is_dir() { - items.insert(filename); + items.insert(KCLCompletionItem { + label: filename, + detail: None, + documentation: None, + kind: Some(KCLCompletionItemKind::Dir), + insert_text: None, + }); } else if path.is_file() { if let Some(extension) = path.extension() { if extension == KCL_FILE_EXTENSION { - items.insert( - path.with_extension("") + items.insert(KCLCompletionItem { + label: path + .with_extension("") .file_name() .unwrap() .to_str() .unwrap() .to_string(), - ); + detail: None, + documentation: None, + kind: Some(KCLCompletionItemKind::File), + insert_text: None, + }); } } } @@ -111,76 +620,1034 @@ fn completion_for_import( Some(into_completion_items(&items).into()) } -fn get_completion_items(expr: &Expr, prog_scope: &ProgramScope) -> IndexSet { - let mut items = IndexSet::new(); - match expr { - Expr::Identifier(id) => { - let name = get_identifier_last_name(id); - if !id.pkgpath.is_empty() { - // standard system module - if STANDARD_SYSTEM_MODULES.contains(&name.as_str()) { - items.extend( - get_system_module_members(name.as_str()) - .iter() - .map(|s| s.to_string()), - ) - } - // user module - if let Some(scope) = prog_scope.scope_map.get(&id.pkgpath) { - let scope = scope.borrow(); - for (name, obj) in &scope.elems { - if obj.borrow().ty.is_module() { - continue; - } - items.insert(name.clone()); - } - } - return items; - } - - let objs = find_objs_in_program_scope(&name, prog_scope); - for obj in objs { - match &obj.ty.kind { - // builtin (str) functions - kclvm_sema::ty::TypeKind::Str => { - let binding = STRING_MEMBER_FUNCTIONS; - for k in binding.keys() { - items.insert(format!("{}{}", k, "()")); - } - } - // schema attrs - kclvm_sema::ty::TypeKind::Schema(schema) => { - for k in schema.attrs.keys() { - if k != "__settings__" { - items.insert(k.clone()); - } - } - } - _ => {} - } - } +fn ty_complete_label(ty: &Type, module: Option<&ModuleInfo>) -> Vec { + match &ty.kind { + kclvm_sema::ty::TypeKind::Bool => vec!["True".to_string(), "False".to_string()], + kclvm_sema::ty::TypeKind::BoolLit(b) => { + vec![if *b { + "True".to_string() + } else { + "False".to_string() + }] } - Expr::StringLit(_) => { - let binding = STRING_MEMBER_FUNCTIONS; - for k in binding.keys() { - items.insert(format!("{}{}", k, "()")); - } + kclvm_sema::ty::TypeKind::IntLit(i) => vec![i.to_string()], + kclvm_sema::ty::TypeKind::FloatLit(f) => vec![f.to_string()], + kclvm_sema::ty::TypeKind::Str => vec![r#""""#.to_string()], + kclvm_sema::ty::TypeKind::StrLit(s) => vec![format!("{:?}", s)], + kclvm_sema::ty::TypeKind::List(_) => vec!["[]".to_string()], + kclvm_sema::ty::TypeKind::Dict(_) => vec!["{}".to_string()], + kclvm_sema::ty::TypeKind::Union(types) => types + .iter() + .flat_map(|ty| ty_complete_label(ty, module)) + .collect(), + kclvm_sema::ty::TypeKind::Schema(schema) => { + vec![format!( + "{}{}{}", + if schema.pkgpath.is_empty() || schema.pkgpath == MAIN_PKG { + "".to_string() + } else if let Some(m) = module { + format!("{}.", pkg_real_name(&schema.pkgpath, m)) + } else { + format!("{}.", schema.pkgpath.split('.').last().unwrap()) + }, + schema.name, + "{}" + )] } - Expr::Selector(select_expr) => { - let res = get_completion_items(&select_expr.value.node, prog_scope); - items.extend(res); + _ => vec![], + } +} + +/// get pkg_path real name: as_name if not none or pkg last name +fn pkg_real_name(pkg: &String, module: &ModuleInfo) -> String { + let imports = module.get_imports(); + for (name, import_info) in imports { + if &import_info.get_fully_qualified_name() == pkg { + return name; } - _ => {} } - items + pkg.split('.').last().unwrap().to_string() +} + +fn func_ty_complete_label(func_name: &String, _func_type: &FunctionType) -> String { + format!("{}(…)", func_name,) +} + +fn func_ty_complete_insert_text(func_name: &String, func_type: &FunctionType) -> String { + format!( + "{}({})", + func_name, + func_type + .params + .iter() + .enumerate() + .map(|(idx, param)| format!("${{{}:{}}}", idx + 1, param.name.clone())) + .collect::>() + .join(", "), + ) +} +fn type_to_item_kind(ty: &Type) -> Option { + match ty.kind { + kclvm_sema::ty::TypeKind::Bool + | kclvm_sema::ty::TypeKind::BoolLit(_) + | kclvm_sema::ty::TypeKind::Int + | kclvm_sema::ty::TypeKind::IntLit(_) + | kclvm_sema::ty::TypeKind::Float + | kclvm_sema::ty::TypeKind::FloatLit(_) + | kclvm_sema::ty::TypeKind::Str + | kclvm_sema::ty::TypeKind::StrLit(_) + | kclvm_sema::ty::TypeKind::List(_) + | kclvm_sema::ty::TypeKind::Dict(_) + | kclvm_sema::ty::TypeKind::Union(_) + | kclvm_sema::ty::TypeKind::NumberMultiplier(_) + | kclvm_sema::ty::TypeKind::Named(_) => Some(KCLCompletionItemKind::Variable), + kclvm_sema::ty::TypeKind::Schema(_) => Some(KCLCompletionItemKind::Schema), + kclvm_sema::ty::TypeKind::Function(_) => Some(KCLCompletionItemKind::Function), + kclvm_sema::ty::TypeKind::Module(_) => Some(KCLCompletionItemKind::Module), + kclvm_sema::ty::TypeKind::Void + | kclvm_sema::ty::TypeKind::None + | kclvm_sema::ty::TypeKind::Any => None, + } } -pub(crate) fn into_completion_items(items: &IndexSet) -> Vec { +pub(crate) fn into_completion_items(items: &IndexSet) -> Vec { items .iter() .map(|item| CompletionItem { - label: item.clone(), + label: item.label.clone(), + detail: item.detail.clone(), + documentation: item + .documentation + .clone() + .map(lsp_types::Documentation::String), + kind: item.kind.clone().map(|kind| kind.into()), + insert_text: item.insert_text.clone(), + insert_text_format: if item.insert_text.is_some() { + Some(InsertTextFormat::SNIPPET) + } else { + None + }, ..Default::default() }) .collect() } + +#[cfg(test)] +mod tests { + use indexmap::IndexSet; + use kclvm_error::Position as KCLPos; + use kclvm_sema::builtin::{BUILTIN_FUNCTIONS, MATH_FUNCTION_TYPES, STRING_MEMBER_FUNCTIONS}; + use lsp_types::{CompletionItem, CompletionItemKind, CompletionResponse, InsertTextFormat}; + use proc_macro_crate::bench_test; + + use crate::{ + completion::{ + completion, func_ty_complete_insert_text, func_ty_complete_label, + into_completion_items, KCLCompletionItem, KCLCompletionItemKind, + }, + tests::compile_test_file, + }; + + #[test] + #[bench_test] + fn var_completion_test() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/completion.k"); + + // test completion for var + let pos = KCLPos { + filename: file.to_owned(), + line: 26, + column: Some(1), + }; + + let got = completion(None, &program, &pos, &gs).unwrap(); + let mut got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let mut expected_labels: Vec = vec![ + "", // generate from error recovery of "pkg." + "subpkg", "math", "Person", "Person{}", "P", "P{}", "p", "p1", "p2", "p3", "p4", + "aaaa", + ] + .iter() + .map(|s| s.to_string()) + .collect(); + + expected_labels.extend( + BUILTIN_FUNCTIONS + .iter() + .map(|(name, func)| func_ty_complete_label(name, &func.into_func_type())), + ); + got_labels.sort(); + expected_labels.sort(); + + assert_eq!(got_labels, expected_labels); + + // test completion for schema attr + let pos = KCLPos { + filename: file.to_owned(), + line: 24, + column: Some(4), + }; + + let got = completion(None, &program, &pos, &gs).unwrap(); + let mut got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + expected_labels = vec!["", "age", "math", "name", "subpkg"] + .iter() + .map(|s| s.to_string()) + .collect(); + got_labels.sort(); + expected_labels.sort(); + assert_eq!(got_labels, expected_labels); + } + + #[test] + #[bench_test] + fn dot_completion_test() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/completion.k"); + + // test completion for schema attr + let pos = KCLPos { + filename: file.to_owned(), + line: 12, + column: Some(7), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["name", "age"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 14, + column: Some(12), + }; + + // test completion for str builtin function + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match &got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + let got_insert_text: Vec = match &got { + CompletionResponse::Array(arr) => arr + .iter() + .map(|item| item.insert_text.clone().unwrap()) + .collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_insert_text: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_insert_text(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_insert_text, expected_insert_text); + + // test completion for import pkg path + let pos = KCLPos { + filename: file.to_owned(), + line: 1, + column: Some(12), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["file1", "file2", "subpkg"]; + assert_eq!(got_labels, expected_labels); + + // test completion for import pkg' schema + let pos = KCLPos { + filename: file.to_owned(), + line: 16, + column: Some(12), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["Person1"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 19, + column: Some(5), + }; + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec = MATH_FUNCTION_TYPES + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + // test completion for literal str builtin function + let pos = KCLPos { + filename: file.clone(), + line: 21, + column: Some(4), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file, + line: 30, + column: Some(11), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["a"]; + assert_eq!(got_labels, expected_labels); + } + + #[test] + #[bench_test] + fn dot_completion_test_without_dot() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/without_dot/completion.k"); + + // test completion for schema attr + let pos = KCLPos { + filename: file.to_owned(), + line: 12, + column: Some(7), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["name", "age"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 14, + column: Some(12), + }; + + // test completion for str builtin function + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + // test completion for import pkg path + let pos = KCLPos { + filename: file.to_owned(), + line: 1, + column: Some(12), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["file1", "file2", "subpkg"]; + assert_eq!(got_labels, expected_labels); + + // test completion for import pkg' schema + let pos = KCLPos { + filename: file.to_owned(), + line: 16, + column: Some(12), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["Person1"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 19, + column: Some(5), + }; + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match &got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec = MATH_FUNCTION_TYPES + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + let got_insert_text: Vec = match &got { + CompletionResponse::Array(arr) => arr + .iter() + .map(|item| item.insert_text.clone().unwrap()) + .collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_insert_text: Vec = MATH_FUNCTION_TYPES + .iter() + .map(|(name, ty)| func_ty_complete_insert_text(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_insert_text, expected_insert_text); + + // test completion for literal str builtin function + let pos = KCLPos { + filename: file.clone(), + line: 21, + column: Some(4), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match &got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + let got_insert_text: Vec = match &got { + CompletionResponse::Array(arr) => arr + .iter() + .map(|item| item.insert_text.clone().unwrap()) + .collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_insert_text: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_insert_text(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_insert_text, expected_insert_text); + + let pos = KCLPos { + filename: file, + line: 30, + column: Some(11), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec<&str> = vec!["a"]; + assert_eq!(got_labels, expected_labels); + } + + #[test] + #[bench_test] + fn import_builtin_package() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/import/builtin_pkg.k"); + let mut items: IndexSet = IndexSet::new(); + + // test completion for builtin packages + let pos = KCLPos { + filename: file.to_owned(), + line: 1, + column: Some(8), + }; + + let got = completion(None, &program, &pos, &gs).unwrap(); + let _got_labels: Vec = match &got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + items.extend( + [ + "collection", + "net", + "manifests", + "math", + "datetime", + "regex", + "yaml", + "json", + "crypto", + "base64", + "units", + "file", + ] + .iter() + .map(|name| KCLCompletionItem { + label: name.to_string(), + kind: Some(KCLCompletionItemKind::Module), + detail: None, + documentation: None, + insert_text: None, + }) + .collect::>(), + ); + let expect: CompletionResponse = into_completion_items(&items).into(); + assert_eq!(got, expect); + } + + #[test] + #[bench_test] + fn attr_value_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/assign/completion.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 14, + column: Some(6), + }; + + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" True", " False"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 16, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" \"abc\"", " \"def\""]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 18, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" []"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 20, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" 1"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 22, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" True"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 24, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" {}"]; + assert_eq!(got_labels, expected_labels); + + let pos = KCLPos { + filename: file.to_owned(), + line: 26, + column: Some(6), + }; + let got = completion(Some(':'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![" sub.Person1{}"]; + assert_eq!(got_labels, expected_labels); + } + + #[test] + #[bench_test] + fn schema_sig_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/schema/schema.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 7, + column: Some(5), + }; + + let mut got = completion(None, &program, &pos, &gs).unwrap(); + match &mut got { + CompletionResponse::Array(arr) => { + assert_eq!( + arr.iter().find(|item| item.label == "Person(b){}").unwrap(), + &CompletionItem { + label: "Person(b){}".to_string(), + kind: Some(CompletionItemKind::CLASS), + detail: Some( + "__main__\n\nschema Person[b: int](Base)\nAttributes:\nc: int" + .to_string() + ), + documentation: Some(lsp_types::Documentation::String("".to_string())), + insert_text: Some("Person(${1:b}){}".to_string()), + insert_text_format: Some(InsertTextFormat::SNIPPET), + ..Default::default() + } + ) + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + fn schema_attr_newline_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/newline/newline.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 8, + column: Some(4), + }; + + let mut got = completion(Some('\n'), &program, &pos, &gs).unwrap(); + match &mut got { + CompletionResponse::Array(arr) => { + arr.sort_by(|a, b| a.label.cmp(&b.label)); + assert_eq!( + arr[1], + CompletionItem { + label: "c".to_string(), + kind: Some(CompletionItemKind::FIELD), + detail: Some("c: int".to_string()), + documentation: None, + ..Default::default() + } + ) + } + CompletionResponse::List(_) => panic!("test failed"), + } + + // not complete in schema stmt + let pos = KCLPos { + filename: file.to_owned(), + line: 5, + column: Some(4), + }; + let got = completion(Some('\n'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert!(arr.is_empty()) + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + fn schema_docstring_newline_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/newline/docstring_newline.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 3, + column: Some(4), + }; + + let mut got = completion(Some('\n'), &program, &pos, &gs).unwrap(); + match &mut got { + CompletionResponse::Array(arr) => { + arr.sort_by(|a, b| a.label.cmp(&b.label)); + assert_eq!( + arr[0], + CompletionItem { + label: "\n\nAttributes\n----------\nname: \nworkloadType: \nreplica: \n\nExamples\n--------\n".to_string(), + detail: Some("generate docstring".to_string()), + kind: Some(CompletionItemKind::SNIPPET), + documentation: Some(lsp_types::Documentation::String("docstring for Server".to_string())), + ..Default::default() + } + ) + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + fn str_dot_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); + + // test complete str functions when at the end of literal str + let pos = KCLPos { + filename: file.to_owned(), + line: 1, + column: Some(10), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + + match &got { + CompletionResponse::Array(arr) => { + assert!(arr + .iter() + .all(|item| item.kind == Some(CompletionItemKind::FUNCTION))) + } + CompletionResponse::List(_) => panic!("test failed"), + }; + + let got_labels: Vec = match &got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let expected_labels: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_label(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_labels, expected_labels); + + let got_insert_text: Vec = match &got { + CompletionResponse::Array(arr) => arr + .iter() + .map(|item| item.insert_text.clone().unwrap()) + .collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_insert_text: Vec = STRING_MEMBER_FUNCTIONS + .iter() + .map(|(name, ty)| func_ty_complete_insert_text(name, &ty.into_func_type())) + .collect(); + assert_eq!(got_insert_text, expected_insert_text); + + let pos = KCLPos { + filename: file.to_owned(), + line: 2, + column: Some(6), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + assert_eq!(got_labels, expected_labels); + + // not complete inside literal str + let pos = KCLPos { + filename: file.to_owned(), + line: 2, + column: Some(5), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => assert!(arr.is_empty()), + CompletionResponse::List(_) => panic!("test failed"), + }; + + // not complete inside literal str + let pos = KCLPos { + filename: file.to_owned(), + line: 1, + column: Some(8), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => assert!(arr.is_empty()), + CompletionResponse::List(_) => panic!("test failed"), + }; + + let pos = KCLPos { + filename: file.to_owned(), + line: 3, + column: Some(2), + }; + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert!(arr + .iter() + .all(|item| item.kind == Some(CompletionItemKind::FUNCTION))) + } + CompletionResponse::List(_) => panic!("test failed"), + }; + } + + #[test] + fn schema_ty_attr_complete() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/schema_ty_attr/schema_ty_attr.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 13, + column: Some(2), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert_eq!( + arr[0], + CompletionItem { + label: "name".to_string(), + detail: Some("name: Name".to_string()), + kind: Some(CompletionItemKind::FIELD), + ..Default::default() + } + ) + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + fn schema_end_pos() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/schema/schema_pos/schema_pos.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 6, + column: Some(16), + }; + + let got = completion(None, &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert_eq!(arr.len(), 4); + let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); + assert!(labels.contains(&"min".to_string())); + assert!(labels.contains(&"max".to_string())); + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + fn comment_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 4, + column: Some(4), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + + match &got { + CompletionResponse::Array(arr) => { + assert_eq!(arr.len(), 0) + } + CompletionResponse::List(_) => panic!("test failed"), + }; + } + + #[test] + #[bench_test] + fn missing_expr_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/missing_expr/missing_expr.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 10, + column: Some(16), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert_eq!(arr.len(), 2); + let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); + assert!(labels.contains(&"cpu".to_string())); + assert!(labels.contains(&"memory".to_string())); + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + #[bench_test] + fn check_scope_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/check/check.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 4, + column: Some(10), + }; + + let got = completion(Some(':'), &program, &pos, &gs); + assert!(got.is_none()); + + let pos = KCLPos { + filename: file.to_owned(), + line: 5, + column: Some(9), + }; + + let got = completion(None, &program, &pos, &gs).unwrap(); + match got { + CompletionResponse::Array(arr) => { + assert_eq!(arr.len(), 3); + let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); + assert!(labels.contains(&"name".to_string())); + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + #[bench_test] + fn join_str_inner_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 6, + column: Some(28), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match &got { + CompletionResponse::Array(arr) => { + assert!(arr.is_empty()) + } + CompletionResponse::List(_) => panic!("test failed"), + } + + let pos = KCLPos { + filename: file.to_owned(), + line: 7, + column: Some(27), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + match &got { + CompletionResponse::Array(arr) => { + assert!(arr.is_empty()) + } + CompletionResponse::List(_) => panic!("test failed"), + } + } + + #[test] + #[bench_test] + fn schema_type_attr_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/schema/schema.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 18, + column: Some(15), + }; + + let mut got = completion(None, &program, &pos, &gs).unwrap(); + match &mut got { + CompletionResponse::Array(arr) => { + let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); + assert!(labels.contains(&"name".to_string())); + } + CompletionResponse::List(_) => panic!("test failed"), + } + + let pos = KCLPos { + filename: file.to_owned(), + line: 19, + column: Some(21), + }; + + let mut got = completion(None, &program, &pos, &gs).unwrap(); + match &mut got { + CompletionResponse::Array(arr) => { + let labels: Vec = arr.iter().map(|item| item.label.clone()).collect(); + assert!(labels.contains(&"name".to_string())); + } + CompletionResponse::List(_) => panic!("test failed"), + } + } +} diff --git a/kclvm/tools/src/LSP/src/db.rs b/kclvm/tools/src/LSP/src/db.rs index 09c6425c1..b2bce8fa1 100644 --- a/kclvm/tools/src/LSP/src/db.rs +++ b/kclvm/tools/src/LSP/src/db.rs @@ -1,3 +1,12 @@ +use indexmap::IndexSet; +use kclvm_ast::ast::Program; +use kclvm_error::Diagnostic; +use kclvm_sema::core::global_state::GlobalState; + /// Holds the result of the compile #[derive(Default, Clone)] -pub(crate) struct AnalysisDatabase {} +pub struct AnalysisDatabase { + pub prog: Program, + pub diags: IndexSet, + pub gs: GlobalState, +} diff --git a/kclvm/tools/src/LSP/src/document_symbol.rs b/kclvm/tools/src/LSP/src/document_symbol.rs index e567d0c3a..a45f5b552 100644 --- a/kclvm/tools/src/LSP/src/document_symbol.rs +++ b/kclvm/tools/src/LSP/src/document_symbol.rs @@ -1,12 +1,10 @@ use std::path::Path; -use kclvm_ast::ast::Program; use kclvm_ast::MAIN_PKG; -use kclvm_sema::resolver::scope::ProgramScope; -use kclvm_sema::resolver::scope::Scope; -use kclvm_sema::resolver::scope::ScopeKind; -use kclvm_sema::resolver::scope::ScopeObject; -use kclvm_sema::resolver::scope::ScopeObjectKind; +use kclvm_error::Position; +use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::core::symbol::KCLSymbol; +use kclvm_sema::core::symbol::SymbolKind as KCLSymbolKind; use lsp_types::Range; use lsp_types::{DocumentSymbol, DocumentSymbolResponse, SymbolKind}; @@ -14,92 +12,201 @@ use crate::to_lsp::lsp_pos; pub(crate) fn document_symbol( file: &str, - _program: &Program, - prog_scope: &ProgramScope, + gs: &GlobalState, ) -> Option { let mut documentsymbols: Vec = vec![]; - let scope = prog_scope.scope_map.get(MAIN_PKG).unwrap().borrow(); - // Get variable in scope - for obj in scope.elems.values().filter(|obj| { - if let Ok(canonicalized_path) = Path::new(&obj.borrow().start.filename).canonicalize() { - // skip schema definition - canonicalized_path.eq(Path::new(file)) - && obj.borrow().kind != ScopeObjectKind::Definition - } else { - false + + let dummy_pos = Position { + filename: file.to_string(), + line: 1, + column: Some(0), + }; + if let Some(scope) = gs.get_scopes().get_root_scope(MAIN_PKG.to_owned()) { + if let Some(defs) = gs.get_all_defs_in_scope(scope) { + for symbol_ref in defs { + match gs.get_symbols().get_symbol(symbol_ref) { + Some(symbol) => { + let def = symbol.get_definition(); + match def { + Some(def) => { + let symbol_range = symbol.get_range(); + // filter current file symbols + if let Ok(canonicalized_path) = + Path::new(&symbol_range.0.filename).canonicalize() + { + if canonicalized_path.eq(Path::new(file)) { + match def.get_kind() { + KCLSymbolKind::Schema => { + match &mut symbol_to_document_symbol(symbol) { + Some(schema_symbol) => { + let module_info = gs + .get_packages() + .get_module_info(&dummy_pos.filename); + let attrs = symbol.get_all_attributes( + gs.get_symbols(), + module_info, + ); + let mut children = vec![]; + + for attr in attrs { + match gs.get_symbols().get_symbol(attr) + { + Some(attr_symbol) => { + match symbol_to_document_symbol( + attr_symbol, + ) { + Some(symbol) => { + children.push(symbol) + } + None => {} + } + } + None => {} + } + } + + schema_symbol.children = Some(children); + documentsymbols.push(schema_symbol.clone()); + } + None => {} + } + } + _ => match symbol_to_document_symbol(symbol) { + Some(symbol) => documentsymbols.push(symbol), + None => {} + }, + } + } + } + } + None => {} + } + } + None => {} + } + } } - }) { - documentsymbols.push(scope_obj_to_document_symbol(obj.borrow().clone())); } - // Get schema definition in scope - for child in scope.children.iter().filter(|child| { - if let Ok(canonicalized_path) = Path::new(&child.borrow().start.filename).canonicalize() { - canonicalized_path.eq(Path::new(file)) - } else { - false - } - }) { - if let Some(symbol) = schema_scope_to_document_symbol(child.borrow().clone()) { - documentsymbols.push(symbol) + Some(DocumentSymbolResponse::Nested(documentsymbols)) +} + +fn symbol_to_document_symbol(symbol: &KCLSymbol) -> Option { + let sema_info = symbol.get_sema_info(); + let def = symbol.get_definition(); + match def { + Some(def) => { + let name = symbol.get_name(); + let symbol_range = symbol.get_range(); + let range = Range { + start: lsp_pos(&symbol_range.0), + end: lsp_pos(&symbol_range.1), + }; + let kind = def.get_kind(); + let kind = symbol_kind_to_document_symbol_kind(kind)?; + let detail = sema_info.ty.clone().map(|ty| ty.ty_str()); + + #[allow(deprecated)] + Some(DocumentSymbol { + name, + kind, + range, + selection_range: range, + detail, + tags: None, + children: None, + deprecated: None, + }) } + None => None, + } +} + +fn symbol_kind_to_document_symbol_kind(kind: KCLSymbolKind) -> Option { + match kind { + KCLSymbolKind::Schema => Some(SymbolKind::STRUCT), + KCLSymbolKind::Attribute => Some(SymbolKind::PROPERTY), + KCLSymbolKind::Value => Some(SymbolKind::VARIABLE), + KCLSymbolKind::Package => Some(SymbolKind::PACKAGE), + KCLSymbolKind::TypeAlias => Some(SymbolKind::TYPE_PARAMETER), + KCLSymbolKind::Unresolved => Some(SymbolKind::NULL), + KCLSymbolKind::Rule => Some(SymbolKind::FUNCTION), + KCLSymbolKind::Expression => None, + KCLSymbolKind::Comment => None, + KCLSymbolKind::Decorator => None, } - Some(DocumentSymbolResponse::Nested(documentsymbols)) } -#[allow(deprecated)] -fn schema_scope_to_document_symbol(scope: Scope) -> Option { - if let ScopeKind::Schema(schema_name) = &scope.kind { - let range = Range { - start: lsp_pos(&scope.start), - end: lsp_pos(&scope.end), +#[cfg(test)] +mod tests { + use lsp_types::{DocumentSymbol, DocumentSymbolResponse, Position, Range, SymbolKind}; + use proc_macro_crate::bench_test; + + use crate::{document_symbol::document_symbol, tests::compile_test_file}; + + #[allow(deprecated)] + fn build_document_symbol( + name: &str, + kind: SymbolKind, + range: ((u32, u32), (u32, u32)), + child: Option>, + detail: Option, + ) -> DocumentSymbol { + let range: Range = Range { + start: Position { + line: range.0 .0, + character: range.0 .1, + }, + end: Position { + line: range.1 .0, + character: range.1 .1, + }, }; - Some(DocumentSymbol { - name: schema_name.clone(), - kind: SymbolKind::STRUCT, - range, - selection_range: range, - children: Some( - scope - .elems - .iter() - .map(|(_, obj)| scope_obj_to_document_symbol(obj.borrow().clone())) - .collect(), - ), - detail: Some("schema".to_string()), + DocumentSymbol { + name: name.to_string(), + detail, + kind, tags: None, deprecated: None, - }) - } else { - None + range, + selection_range: range, + children: child, + } } -} -#[allow(deprecated)] -fn scope_obj_to_document_symbol(obj: ScopeObject) -> DocumentSymbol { - let kind = scope_obj_kind_to_document_symbol_kind(obj.kind); - let range = Range { - start: lsp_pos(&obj.start), - end: lsp_pos(&obj.end), - }; - DocumentSymbol { - name: obj.name.clone(), - kind, - range, - selection_range: range, - detail: Some(obj.ty.ty_str()), - tags: None, - children: None, - deprecated: None, - } -} + #[test] + #[bench_test] + fn document_symbol_test() { + let (file, _, _, _, gs) = compile_test_file("src/test_data/document_symbol.k"); -fn scope_obj_kind_to_document_symbol_kind(kind: ScopeObjectKind) -> SymbolKind { - match kind { - ScopeObjectKind::Variable => SymbolKind::VARIABLE, - ScopeObjectKind::Attribute => SymbolKind::PROPERTY, - ScopeObjectKind::Definition => SymbolKind::STRUCT, - ScopeObjectKind::Parameter => SymbolKind::VARIABLE, - ScopeObjectKind::TypeAlias => SymbolKind::TYPE_PARAMETER, - ScopeObjectKind::Module => SymbolKind::MODULE, + let mut res = document_symbol(file.as_str(), &gs).unwrap(); + let mut expect = vec![]; + expect.push(build_document_symbol( + "Person4", + SymbolKind::STRUCT, + ((0, 7), (0, 14)), + Some(vec![build_document_symbol( + "name", + SymbolKind::PROPERTY, + ((1, 4), (1, 8)), + None, + Some("str".to_string()), + )]), + Some("Person4".to_string()), + )); + expect.push(build_document_symbol( + "p", + SymbolKind::VARIABLE, + ((3, 0), (3, 1)), + None, + Some("Person4".to_string()), + )); + + match &mut res { + DocumentSymbolResponse::Flat(_) => panic!("test failed"), + DocumentSymbolResponse::Nested(got) => { + got.sort_by(|a, b| a.name.cmp(&b.name)); + assert_eq!(got, &expect) + } + } } } diff --git a/kclvm/tools/src/LSP/src/find_ref/find_refs.rs b/kclvm/tools/src/LSP/src/find_ref/find_refs.rs deleted file mode 100644 index f3926093c..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/find_refs.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::find_ref; -use crate::find_ref::go_to_def::go_to_def; -use kclvm_error::Position; - -/// Find all references of the item at the cursor location. -pub fn find_refs(path: String, pos: Position) -> Vec { - let declaration = go_to_def(pos.clone()); - let search = { - move |decl: Position| { - let name = find_ref::word_at_pos(pos); - if name.is_none() { - return vec![]; - } - // Get identifiers with same name - let candidates = find_ref::match_word(path, name.unwrap()); - // Check if the definition of candidate and declartion are the same - let refs: Vec = candidates - .into_iter() - .filter(|x| go_to_def(x.clone()).as_ref() == Some(&decl)) - .collect(); - refs - } - }; - match declaration { - Some(decl) => search(decl), - None => Vec::new(), - } -} diff --git a/kclvm/tools/src/LSP/src/find_ref/go_to_def.rs b/kclvm/tools/src/LSP/src/find_ref/go_to_def.rs deleted file mode 100644 index 95b64b7eb..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/go_to_def.rs +++ /dev/null @@ -1,6 +0,0 @@ -use kclvm_error::Position; - -/// Get the definition of an identifier. -pub fn go_to_def(pos: Position) -> Option { - Some(pos) -} diff --git a/kclvm/tools/src/LSP/src/find_ref/mod.rs b/kclvm/tools/src/LSP/src/find_ref/mod.rs deleted file mode 100644 index 86fe83f9a..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/mod.rs +++ /dev/null @@ -1,134 +0,0 @@ -#![allow(dead_code)] - -use anyhow::Result; -use kclvm_driver::get_kcl_files; -use kclvm_error::Position; - -mod find_refs; -mod go_to_def; -mod word_map; - -#[cfg(test)] -mod tests; - -// LineWord describes an arbitrary word in a certain line including -// start position, end position and the word itself. -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct LineWord { - startpos: u64, - endpos: u64, - word: String, -} - -// Get the word of the position. -pub fn word_at_pos(pos: Position) -> Option { - let text = read_file(&pos.filename); - if text.is_err() { - return None; - } - let text = text.unwrap(); - let lines: Vec<&str> = text.lines().collect(); - if pos.line >= lines.len() as u64 { - return None; - } - pos.column?; - let col = pos.column.unwrap(); - let line_words = line_to_words(lines[pos.line as usize].to_string()); - if line_words.is_empty() - || col < line_words.first().unwrap().startpos - || col >= line_words.last().unwrap().endpos - { - return None; - } - for line_word in line_words.into_iter() { - if col >= line_word.startpos && col < line_word.endpos { - return Some(line_word.word); - } - } - None -} - -pub fn read_file(path: &String) -> Result { - let text = std::fs::read_to_string(path)?; - Ok(text) -} - -// Split one line into identifier words. -pub fn line_to_words(text: String) -> Vec { - let mut chars: Vec = text.chars().collect(); - chars.push('\n'); - let mut start_pos = usize::MAX; - let mut continue_pos = usize::MAX - 1; // avoid overflow - let mut prev_word = false; - let mut words: Vec = vec![]; - for (i, ch) in chars.iter().enumerate() { - let is_id_start = rustc_lexer::is_id_start(*ch); - let is_id_continue = rustc_lexer::is_id_continue(*ch); - // If the character is valid identfier start and the previous character is not valid identifier continue, mark the start position. - if is_id_start && !prev_word { - start_pos = i; - } - match is_id_continue { - true => { - // Continue searching for the end position. - if start_pos != usize::MAX { - continue_pos = i; - } - } - false => { - // Find out the end position. - if continue_pos + 1 == i { - words.push(LineWord { - startpos: start_pos as u64, - endpos: i as u64, - word: chars[start_pos..i].iter().collect::().clone(), - }); - } - // Reset the start position. - start_pos = usize::MAX; - } - } - prev_word = is_id_continue; - } - words -} - -// Get all occurrences of the word in the entire path. -pub fn match_word(path: String, name: String) -> Vec { - let mut res = vec![]; - if let Ok(files) = get_kcl_files(path, true) { - // Searching in all files. - for file in files.into_iter() { - let text = read_file(&file); - if text.is_err() { - continue; - } - let text = text.unwrap(); - let lines: Vec<&str> = text.lines().collect(); - for (li, line) in lines.into_iter().enumerate() { - // Get the matching results for each line. - let matched: Vec = line_to_words(line.to_string()) - .into_iter() - .filter(|x| x.word == name) - .map(|x| Position { - filename: file.clone(), - line: li as u64, - column: Some(x.startpos), - }) - .collect(); - res.extend(matched); - } - } - } - res -} - -// Convert pos format -// The position in lsp protocol is different with position in ast node whose line number is 1 based. -pub fn kcl_pos_to_lsp_pos(pos: Position) -> Position { - Position { - filename: pos.filename, - line: pos.line - 1, - column: pos.column, - } -} diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/inherit.k b/kclvm/tools/src/LSP/src/find_ref/test_data/inherit.k deleted file mode 100644 index a1bef7126..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/inherit.k +++ /dev/null @@ -1,10 +0,0 @@ -schema Parent: - name: str - -schema Son(Parent): - age: int - son_name: str = name - -schema GrandSon(Son): - grand_son_name: str = name - a: str = name_not_exist diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/inherit_pkg.k b/kclvm/tools/src/LSP/src/find_ref/test_data/inherit_pkg.k deleted file mode 100644 index 39cdf9b1d..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/inherit_pkg.k +++ /dev/null @@ -1,4 +0,0 @@ -import pkg - -schema Son(pkg.Parent): - son_name: str = name diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit.k b/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit.k deleted file mode 100644 index a1bef7126..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit.k +++ /dev/null @@ -1,10 +0,0 @@ -schema Parent: - name: str - -schema Son(Parent): - age: int - son_name: str = name - -schema GrandSon(Son): - grand_son_name: str = name - a: str = name_not_exist diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit_pkg.k b/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit_pkg.k deleted file mode 100644 index 39cdf9b1d..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace/inherit_pkg.k +++ /dev/null @@ -1,4 +0,0 @@ -import pkg - -schema Son(pkg.Parent): - son_name: str = name diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit.k b/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit.k deleted file mode 100644 index a1bef7126..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit.k +++ /dev/null @@ -1,10 +0,0 @@ -schema Parent: - name: str - -schema Son(Parent): - age: int - son_name: str = name - -schema GrandSon(Son): - grand_son_name: str = name - a: str = name_not_exist diff --git a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit_pkg.k b/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit_pkg.k deleted file mode 100644 index 39cdf9b1d..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/test_data/test_word_workspace_map/inherit_pkg.k +++ /dev/null @@ -1,4 +0,0 @@ -import pkg - -schema Son(pkg.Parent): - son_name: str = name diff --git a/kclvm/tools/src/LSP/src/find_ref/tests.rs b/kclvm/tools/src/LSP/src/find_ref/tests.rs deleted file mode 100644 index e2886da35..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/tests.rs +++ /dev/null @@ -1,252 +0,0 @@ -use crate::find_ref; -use crate::find_ref::LineWord; -use kclvm_error::Position; - -#[cfg(test)] -mod tests { - use super::*; - use std::fs; - use std::path::Path; - use std::{collections::HashMap, hash::Hash}; - - fn check_line_to_words(code: &str, expect: Vec) { - assert_eq!(find_ref::line_to_words(code.to_string()), expect); - } - - fn test_eq_list(a: &[T], b: &[T]) -> bool - where - T: Eq + Hash, - { - fn count(items: &[T]) -> HashMap<&T, usize> - where - T: Eq + Hash, - { - let mut cnt = HashMap::new(); - for i in items { - *cnt.entry(i).or_insert(0) += 1 - } - cnt - } - count(a) == count(b) - } - - #[test] - fn test_line_to_words() { - let datas = vec![ - "alice_first_name = \"alice\"", - "0lice_first_name = \"alic0\"", - "alice = p.Parent { name: \"alice\" }", - ]; - let expect = vec![ - vec![ - LineWord { - startpos: 0, - endpos: 16, - word: "alice_first_name".to_string(), - }, - LineWord { - startpos: 20, - endpos: 25, - word: "alice".to_string(), - }, - ], - vec![LineWord { - startpos: 20, - endpos: 25, - word: "alic0".to_string(), - }], - vec![ - LineWord { - startpos: 0, - endpos: 5, - word: "alice".to_string(), - }, - LineWord { - startpos: 8, - endpos: 9, - word: "p".to_string(), - }, - LineWord { - startpos: 10, - endpos: 16, - word: "Parent".to_string(), - }, - LineWord { - startpos: 19, - endpos: 23, - word: "name".to_string(), - }, - LineWord { - startpos: 26, - endpos: 31, - word: "alice".to_string(), - }, - ], - ]; - for i in 0..datas.len() { - check_line_to_words(datas[i], expect[i].clone()); - } - } - - #[test] - fn test_word_at_pos() { - // use std::env; - // let parent_path = env::current_dir().unwrap(); - // println!("The current directory is {}", parent_path.display()); - let path_prefix = "./src/find_ref/".to_string(); - let datas = vec![ - Position { - filename: (path_prefix.clone() + "test_data/inherit.k"), - line: 0, - column: Some(0), - }, - Position { - filename: (path_prefix.clone() + "test_data/inherit.k"), - line: 1, - column: Some(5), - }, - Position { - filename: (path_prefix.clone() + "test_data/inherit.k"), - line: 3, - column: Some(7), - }, - Position { - filename: (path_prefix.clone() + "test_data/inherit.k"), - line: 3, - column: Some(10), - }, - Position { - filename: (path_prefix.clone() + "test_data/inherit.k"), - line: 4, - column: Some(8), - }, - Position { - filename: (path_prefix + "test_data/inherit.k"), - line: 4, - column: Some(100), - }, - ]; - let expect = vec![ - Some("schema".to_string()), - Some("name".to_string()), - Some("Son".to_string()), - None, - None, - None, - ]; - for i in 0..datas.len() { - assert_eq!(find_ref::word_at_pos(datas[i].clone()), expect[i]); - } - } - - fn test_word_workspace() -> String { - Path::new(".") - .join("src") - .join("find_ref") - .join("test_data") - .join("test_word_workspace") - .display() - .to_string() - } - - #[test] - fn test_match_word() { - let path = test_word_workspace(); - let datas = vec![String::from("Son")]; - let except = vec![vec![ - Position { - filename: Path::new(&test_word_workspace()) - .join("inherit_pkg.k") - .display() - .to_string(), - line: 2, - column: Some(7), - }, - Position { - filename: Path::new(&test_word_workspace()) - .join("inherit.k") - .display() - .to_string(), - line: 3, - column: Some(7), - }, - Position { - filename: Path::new(&test_word_workspace()) - .join("inherit.k") - .display() - .to_string(), - line: 7, - column: Some(16), - }, - ]]; - for i in 0..datas.len() { - assert!(test_eq_list( - &find_ref::match_word(path.clone(), datas[i].clone()), - &except[i] - )); - } - } - - fn test_word_workspace_map() -> String { - Path::new(".") - .join("src") - .join("find_ref") - .join("test_data") - .join("test_word_workspace_map") - .display() - .to_string() - } - - #[test] - fn test_word_map() { - let path = test_word_workspace_map(); - let mut mp = find_ref::word_map::WorkSpaceWordMap::new(path); - mp.build(); - let _res = fs::rename( - Path::new(&test_word_workspace_map()) - .join("inherit_pkg.k") - .display() - .to_string(), - Path::new(&test_word_workspace_map()) - .join("inherit_bak.k") - .display() - .to_string(), - ); - mp.rename_file( - Path::new(&test_word_workspace_map()) - .join("inherit_pkg.k") - .display() - .to_string(), - Path::new(&test_word_workspace_map()) - .join("inherit_bak.k") - .display() - .to_string(), - ); - mp.delete_file( - Path::new(&test_word_workspace_map()) - .join("inherit.k") - .display() - .to_string(), - ); - let _res = fs::rename( - Path::new(&test_word_workspace_map()) - .join("inherit_bak.k") - .display() - .to_string(), - Path::new(&test_word_workspace_map()) - .join("inherit_pkg.k") - .display() - .to_string(), - ); - - let except = vec![Position { - filename: Path::new(&test_word_workspace_map()) - .join("inherit_bak.k") - .display() - .to_string(), - line: 2, - column: Some(7), - }]; - assert_eq!(mp.get(&String::from("Son")), Some(except)); - } -} diff --git a/kclvm/tools/src/LSP/src/find_ref/word_map.rs b/kclvm/tools/src/LSP/src/find_ref/word_map.rs deleted file mode 100644 index 220eedc7a..000000000 --- a/kclvm/tools/src/LSP/src/find_ref/word_map.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::find_ref; - -use kclvm_driver::get_kcl_files; -use kclvm_error::Position; -use std::collections::HashMap; - -// Record all occurrences of the name in a file -#[derive(Default)] -pub struct FileWordMap { - file_name: String, - word_map: HashMap>, -} - -impl FileWordMap { - pub fn new(file_name: String) -> Self { - Self { - file_name, - word_map: HashMap::new(), - } - } - - // Clear records - pub fn clear(&mut self) { - self.word_map.clear(); - } - - // insert an occurrence of a name - pub fn insert(&mut self, name: String, pos: Position) { - self.word_map.entry(name).or_insert(Vec::new()).push(pos); - } - - // build the record map - // if text is missing, it will be read from the file system based on the filename - pub fn build(&mut self, text: Option) { - self.clear(); - let text = text.unwrap_or(find_ref::read_file(&self.file_name).unwrap()); - let lines: Vec<&str> = text.lines().collect(); - for (li, line) in lines.into_iter().enumerate() { - let words = find_ref::line_to_words(line.to_string()); - words.iter().for_each(|x| { - self.word_map - .entry(x.word.clone()) - .or_insert(Vec::new()) - .push(Position { - filename: self.file_name.clone(), - line: li as u64, - column: Some(x.startpos), - }) - }); - } - } - - // return all occurrence of a name - pub fn get(&self, name: &String) -> Option<&Vec> { - self.word_map.get(name) - } -} - -// Record all occurrences of the name in workspace -pub struct WorkSpaceWordMap { - path: String, - file_map: HashMap, -} - -impl WorkSpaceWordMap { - pub fn new(path: String) -> Self { - Self { - path, - file_map: HashMap::new(), - } - } - - // when user edit a file, the filemap of this file need to rebuild - pub fn change_file(&mut self, file_name: String, text: String) { - self.file_map - .entry(file_name.clone()) - .or_insert(FileWordMap::new(file_name)) - .build(Some(text)); - } - - // when user add a file, the workspacemap will add a new filemap for it - pub fn create_file(&mut self, file_name: String) { - self.file_map - .entry(file_name.clone()) - .or_insert(FileWordMap::new(file_name)) - .clear(); - } - - // when user delete a file, the workspacemap will remove the old filemap of it - pub fn delete_file(&mut self, file_name: String) { - self.file_map.remove(&file_name); - } - - // when user rename a file, the workspacemap will remove the old filemap of it and build a new filemap for it - pub fn rename_file(&mut self, old_name: String, new_name: String) { - self.delete_file(old_name); - self.create_file(new_name.clone()); - self.file_map.get_mut(&new_name).unwrap().build(None); - } - - // build & maintain the record map for each file under the path - pub fn build(&mut self) { - //TODO may use some cache from other component? - if let Ok(files) = get_kcl_files(&self.path, true) { - for file in files.into_iter() { - self.file_map - .insert(file.clone(), FileWordMap::new(file.clone())); - self.file_map.get_mut(&file).unwrap().build(None); - } - } - } - - // return all occurrence of a name in the workspace - pub fn get(self, name: &String) -> Option> { - let mut words = Vec::new(); - for (_, mp) in self.file_map.iter() { - if let Some(file_words) = mp.get(name) { - words.extend_from_slice(file_words); - } - } - Some(words) - } -} diff --git a/kclvm/tools/src/LSP/src/find_refs.rs b/kclvm/tools/src/LSP/src/find_refs.rs new file mode 100644 index 000000000..6c23b7ff9 --- /dev/null +++ b/kclvm/tools/src/LSP/src/find_refs.rs @@ -0,0 +1,385 @@ +use crate::from_lsp::{file_path_from_url, kcl_pos}; +use crate::goto_def::{find_def_with_gs, goto_definition_with_gs}; +use crate::to_lsp::lsp_location; +use crate::util::{parse_param_and_compile, Param}; + +use anyhow::Result; +use kclvm_ast::ast::Program; +use kclvm_error::Position as KCLPos; +use kclvm_parser::KCLModuleCache; +use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::resolver::scope::CachedScope; +use lsp_types::{Location, Url}; +use parking_lot::RwLock; +use ra_ap_vfs::Vfs; +use std::collections::HashMap; +use std::sync::{Arc, Mutex}; + +pub(crate) fn find_refs Result<(), anyhow::Error>>( + _program: &Program, + kcl_pos: &KCLPos, + include_declaration: bool, + word_index_map: Arc>>>>, + vfs: Option>>, + logger: F, + gs: &GlobalState, + module_cache: Option, + scope_cache: Option>>, +) -> Result, String> { + let def = find_def_with_gs(kcl_pos, gs, true); + match def { + Some(def_ref) => match gs.get_symbols().get_symbol(def_ref) { + Some(obj) => { + let (start, end) = obj.get_range(); + // find all the refs of the def + if let Some(def_loc) = lsp_location(start.filename.clone(), &start, &end) { + Ok(find_refs_from_def( + vfs, + word_index_map, + def_loc, + obj.get_name(), + include_declaration, + logger, + module_cache, + scope_cache, + )) + } else { + Err(format!("Invalid file path: {0}", start.filename)) + } + } + None => Err(String::from( + "Found more than one definitions, reference not supported", + )), + }, + None => Err(String::from( + "Definition item not found, result in no reference", + )), + } +} + +pub(crate) fn find_refs_from_def Result<(), anyhow::Error>>( + vfs: Option>>, + word_index_map: Arc>>>>, + def_loc: Location, + name: String, + include_declaration: bool, + logger: F, + module_cache: Option, + scope_cache: Option>>, +) -> Vec { + let mut ref_locations = vec![]; + for (_, word_index) in &mut *word_index_map.write() { + if let Some(mut locs) = word_index.get(name.as_str()).cloned() { + if locs.len() >= 20 { + let _ = logger( + "Found more than 20 matched symbols, only the first 20 will be processed" + .to_string(), + ); + locs = locs[0..20].to_vec(); + } + + let matched_locs: Vec = locs + .into_iter() + .filter(|ref_loc| { + // from location to real def + // return if the real def location matches the def_loc + match file_path_from_url(&ref_loc.uri) { + Ok(file_path) => { + match parse_param_and_compile( + Param { + file: file_path.clone(), + module_cache: module_cache.clone(), + scope_cache: scope_cache.clone(), + }, + vfs.clone(), + ) { + Ok((prog, _, _, gs)) => { + let ref_pos = kcl_pos(&file_path, ref_loc.range.start); + if *ref_loc == def_loc && !include_declaration { + return false; + } + // find def from the ref_pos + if let Some(real_def) = + goto_definition_with_gs(&prog, &ref_pos, &gs) + { + match real_def { + lsp_types::GotoDefinitionResponse::Scalar( + real_def_loc, + ) => real_def_loc == def_loc, + _ => false, + } + } else { + false + } + } + Err(err) => { + let _ = + logger(format!("{file_path} compilation failed: {}", err)); + false + } + } + } + Err(err) => { + let _ = logger(format!("compilation failed: {}", err)); + false + } + } + }) + .collect(); + ref_locations.extend(matched_locs); + } + } + ref_locations +} + +#[cfg(test)] +mod tests { + use super::find_refs_from_def; + use crate::util::build_word_index; + use lsp_types::{Location, Position, Range, Url}; + use parking_lot::RwLock; + use std::collections::HashMap; + use std::path::PathBuf; + use std::sync::Arc; + + fn logger(msg: String) -> Result<(), anyhow::Error> { + println!("{}", msg); + anyhow::Ok(()) + } + + fn check_locations_match(expect: Vec, actual: Vec) { + assert_eq!(expect, actual) + } + + fn setup_word_index_map(root: &str) -> HashMap>> { + HashMap::from([( + Url::from_file_path(root).unwrap(), + build_word_index(root.to_string(), true).unwrap(), + )]) + } + + #[test] + fn find_refs_from_variable_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/find_refs_test/main.k"); + let path = path.to_str().unwrap(); + + match lsp_types::Url::from_file_path(path) { + Ok(url) => { + let def_loc = Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }; + let expect = vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 4), + end: Position::new(1, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(2, 4), + end: Position::new(2, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 14), + end: Position::new(12, 15), + }, + }, + ]; + check_locations_match( + expect, + find_refs_from_def( + None, + Arc::new(RwLock::new(setup_word_index_map(path))), + def_loc, + "a".to_string(), + true, + logger, + None, + None, + ), + ); + } + Err(_) => assert!(false, "file not found"), + } + } + + #[test] + fn find_refs_include_declaration_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/find_refs_test/main.k"); + let path = path.to_str().unwrap(); + match lsp_types::Url::from_file_path(path) { + Ok(url) => { + let def_loc = Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }; + let expect = vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 4), + end: Position::new(1, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(2, 4), + end: Position::new(2, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 14), + end: Position::new(12, 15), + }, + }, + ]; + check_locations_match( + expect, + find_refs_from_def( + None, + Arc::new(RwLock::new(setup_word_index_map(path))), + def_loc, + "a".to_string(), + false, + logger, + None, + None, + ), + ); + } + Err(_) => assert!(false, "file not found"), + } + } + + #[test] + fn find_refs_from_schema_name_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/find_refs_test/main.k"); + let path = path.to_str().unwrap(); + match lsp_types::Url::from_file_path(path) { + Ok(url) => { + let def_loc = Location { + uri: url.clone(), + range: Range { + start: Position::new(4, 7), + end: Position::new(4, 11), + }, + }; + let expect = vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(4, 7), + end: Position::new(4, 11), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(8, 7), + end: Position::new(8, 11), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(11, 7), + end: Position::new(11, 11), + }, + }, + ]; + check_locations_match( + expect, + find_refs_from_def( + None, + Arc::new(RwLock::new(setup_word_index_map(path))), + def_loc, + "Name".to_string(), + true, + logger, + None, + None, + ), + ); + } + Err(_) => assert!(false, "file not found"), + } + } + + #[test] + fn find_refs_from_schema_attr_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/find_refs_test/main.k"); + let path = path.to_str().unwrap(); + match lsp_types::Url::from_file_path(path) { + Ok(url) => { + let def_loc = Location { + uri: url.clone(), + range: Range { + start: Position::new(5, 4), + end: Position::new(5, 8), + }, + }; + let expect = vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(5, 4), + end: Position::new(5, 8), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 8), + end: Position::new(12, 12), + }, + }, + ]; + check_locations_match( + expect, + find_refs_from_def( + None, + Arc::new(RwLock::new(setup_word_index_map(path))), + def_loc, + "name".to_string(), + true, + logger, + None, + None, + ), + ); + } + Err(_) => assert!(false, "file not found"), + } + } +} diff --git a/kclvm/tools/src/LSP/src/formatting.rs b/kclvm/tools/src/LSP/src/formatting.rs new file mode 100644 index 000000000..b5de6f561 --- /dev/null +++ b/kclvm/tools/src/LSP/src/formatting.rs @@ -0,0 +1,135 @@ +use kclvm_tools::format::{format_source, FormatOptions}; +use lsp_types::{Position, Range, TextEdit}; + +pub(crate) fn format( + file: String, + src: String, + range: Option, +) -> anyhow::Result>> { + let (source, is_formatted) = format_source( + &file, + &src, + &FormatOptions { + omit_errors: true, + ..Default::default() + }, + ) + .map_err(|err| anyhow::anyhow!("Formatting failed: {}", err))?; + if is_formatted { + Ok(Some(vec![TextEdit { + range: range.unwrap_or(Range::new( + Position::new(0, 0), + Position::new(u32::MAX, u32::MAX), + )), + new_text: source, + }])) + } else { + Ok(None) + } +} + +#[cfg(test)] +mod tests { + use std::{ops::Index, path::PathBuf}; + + use super::format; + use lsp_types::{Position, Range, TextEdit}; + use proc_macro_crate::bench_test; + + use crate::{from_lsp::text_range, tests::compile_test_file}; + + #[test] + fn format_signle_file_test() { + const FILE_INPUT_SUFFIX: &str = ".input"; + const FILE_OUTPUT_SUFFIX: &str = ".golden"; + const TEST_CASES: &[&str; 17] = &[ + "assert", + "check", + "blankline", + "breakline", + "codelayout", + "collection_if", + "comment", + "comp_for", + // "empty", + "import", + "indent", + "inline_comment", + "lambda", + "quant", + "schema", + "string", + "type_alias", + "unary", + ]; + + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let test_file = path; + let test_dir = test_file + .parent() + .unwrap() + .join("format") + .join("test_data") + .join("format_data"); + for case in TEST_CASES { + let test_file = test_dir + .join(format!("{}{}", case, FILE_INPUT_SUFFIX)) + .to_str() + .unwrap() + .to_string(); + let test_src = std::fs::read_to_string(&test_file).unwrap(); + let got = format(test_file.to_string(), test_src, None) + .unwrap() + .unwrap(); + let data_output = std::fs::read_to_string( + test_dir + .join(format!("{}{}", case, FILE_OUTPUT_SUFFIX)) + .to_str() + .unwrap(), + ) + .unwrap(); + + #[cfg(target_os = "windows")] + let data_output = data_output.replace("\r\n", "\n"); + + let expect = vec![TextEdit { + range: Range::new(Position::new(0, 0), Position::new(u32::MAX, u32::MAX)), + new_text: data_output, + }]; + println!("{:?}", test_file); + assert_eq!(expect, got); + } + + // empty test case, without change after fmt + let test_file = test_dir + .join(format!("{}{}", "empty", FILE_INPUT_SUFFIX)) + .to_str() + .unwrap() + .to_string(); + let test_src = std::fs::read_to_string(&test_file).unwrap(); + let got = format(test_file, test_src, None).unwrap(); + assert_eq!(got, None) + } + + #[test] + #[bench_test] + fn format_range_test() { + let (file, _program, _prog_scope, _, _gs) = + compile_test_file("src/test_data/format/format_range.k"); + let lsp_range = Range::new(Position::new(0, 0), Position::new(11, 0)); + let text = std::fs::read_to_string(file.clone()).unwrap(); + + let range = text_range(&text, lsp_range); + let src = text.index(range); + + let got = format(file, src.to_owned(), Some(lsp_range)) + .unwrap() + .unwrap(); + + let expected = vec![TextEdit { + range: lsp_range, + new_text: "a = 1\nb = 2\nc = 3\n".to_string(), + }]; + assert_eq!(got, expected) + } +} diff --git a/kclvm/tools/src/LSP/src/from_lsp.rs b/kclvm/tools/src/LSP/src/from_lsp.rs index 09f103810..eab37b973 100644 --- a/kclvm/tools/src/LSP/src/from_lsp.rs +++ b/kclvm/tools/src/LSP/src/from_lsp.rs @@ -19,11 +19,7 @@ pub(crate) fn kcl_pos(file: &str, pos: Position) -> KCLPos { KCLPos { filename: file.to_string(), line: (pos.line + 1) as u64, - column: if pos.character == 0 { - None - } else { - Some(pos.character as u64) - }, + column: Some(pos.character as u64), } } diff --git a/kclvm/tools/src/LSP/src/goto_def.rs b/kclvm/tools/src/LSP/src/goto_def.rs index 804449928..ae88a4e76 100644 --- a/kclvm/tools/src/LSP/src/goto_def.rs +++ b/kclvm/tools/src/LSP/src/goto_def.rs @@ -7,82 +7,69 @@ //! + schema attr //! + attr type +use crate::to_lsp::lsp_location; use indexmap::IndexSet; - -use kclvm_ast::ast::{Expr, Identifier, ImportStmt, Node, Program, SchemaExpr, Stmt}; - +use kclvm_ast::ast::Program; use kclvm_error::Position as KCLPos; - -use kclvm_sema::resolver::scope::{ProgramScope, ScopeObject}; -use lsp_types::{GotoDefinitionResponse, Url}; -use lsp_types::{Location, Range}; -use std::path::Path; - -use crate::to_lsp::lsp_pos; -use crate::util::{get_pos_from_real_path, get_real_path_from_external, inner_most_expr_in_stmt}; +use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::core::symbol::SymbolRef; +use lsp_types::GotoDefinitionResponse; // Navigates to the definition of an identifier. -pub(crate) fn goto_definition( - program: &Program, +pub(crate) fn goto_definition_with_gs( + _program: &Program, kcl_pos: &KCLPos, - prog_scope: &ProgramScope, + gs: &GlobalState, ) -> Option { - match program.pos_to_stmt(kcl_pos) { - Some(node) => match node.node { - Stmt::Import(stmt) => goto_def_for_import(&stmt, kcl_pos, prog_scope, program), - _ => { - let objs = find_definition_objs(node, kcl_pos, prog_scope); - let positions = objs - .iter() - .map(|obj| (obj.start.clone(), obj.end.clone())) - .collect(); - positions_to_goto_def_resp(&positions) - } + let mut res = IndexSet::new(); + let def = find_def_with_gs(kcl_pos, gs, true); + match def { + Some(def_ref) => match gs.get_symbols().get_symbol(def_ref) { + Some(def) => match def_ref.get_kind() { + kclvm_sema::core::symbol::SymbolKind::Package => { + let pkg_info = gs.get_packages().get_package_info(&def.get_name()).unwrap(); + for file in pkg_info.get_kfile_paths() { + let dummy_pos = KCLPos { + filename: file.clone(), + line: 1, + column: None, + }; + res.insert((dummy_pos.clone(), dummy_pos)); + } + } + _ => { + res.insert(def.get_range()); + } + }, + None => {} }, - None => None, + None => {} } + positions_to_goto_def_resp(&res) } -pub(crate) fn find_definition_objs( - node: Node, + +pub(crate) fn find_def_with_gs( kcl_pos: &KCLPos, - prog_scope: &ProgramScope, -) -> Vec { - let (inner_expr, parent) = inner_most_expr_in_stmt(&node.node, kcl_pos, None); - if let Some(expr) = inner_expr { - if let Expr::Identifier(id) = expr.node { - let name = get_identifier_last_name(&id); - let objs = if let Some(parent) = parent { - // find schema attr def - match parent.node { - Expr::Schema(schema_expr) => { - find_def_of_schema_attr(schema_expr, prog_scope, name) - } - _ => vec![], - } - } else { - find_objs_in_program_scope(&name, prog_scope) - }; - return objs; + gs: &GlobalState, + exact: bool, +) -> Option { + if exact { + match gs.look_up_exact_symbol(kcl_pos) { + Some(symbol_ref) => match gs.get_symbols().get_symbol(symbol_ref) { + Some(symbol) => symbol.get_definition(), + None => None, + }, + None => None, + } + } else { + match gs.look_up_closest_symbol(kcl_pos) { + Some(symbol_ref) => match gs.get_symbols().get_symbol(symbol_ref) { + Some(symbol) => symbol.get_definition(), + None => None, + }, + None => None, } } - vec![] -} - -// This function serves as the result of a global search, which may cause duplication. -// It needs to be pruned according to the situation. There are two actions todo: -// + AST Identifier provides location information for each name. -// + Scope provides a method similar to resolve_var of the resolver to replace this function. -pub(crate) fn find_objs_in_program_scope( - name: &str, - prog_scope: &ProgramScope, -) -> Vec { - let mut res = vec![]; - for s in prog_scope.scope_map.values() { - let mut objs = s.borrow().search_obj_by_name(name); - res.append(&mut objs); - } - - res } // Convert kcl position to GotoDefinitionResponse. This function will convert to @@ -94,103 +81,617 @@ fn positions_to_goto_def_resp( 0 => None, 1 => { let (start, end) = positions.iter().next().unwrap().clone(); - Some(lsp_types::GotoDefinitionResponse::Scalar(Location { - uri: Url::from_file_path(start.filename.clone()).unwrap(), - range: Range { - start: lsp_pos(&start), - end: lsp_pos(&end), - }, - })) + let loc = lsp_location(start.filename.clone(), &start, &end)?; + Some(lsp_types::GotoDefinitionResponse::Scalar(loc)) } _ => { let mut res = vec![]; for (start, end) in positions { - res.push(Location { - uri: Url::from_file_path(start.filename.clone()).unwrap(), - range: Range { - start: lsp_pos(start), - end: lsp_pos(end), - }, - }) + let loc = lsp_location(start.filename.clone(), start, end)?; + res.push(loc) } Some(lsp_types::GotoDefinitionResponse::Array(res)) } } } -fn goto_def_for_import( - stmt: &ImportStmt, - _kcl_pos: &KCLPos, - _prog_scope: &ProgramScope, - program: &Program, -) -> Option { - let pkgpath = &stmt.path; - let mut real_path = - Path::new(&program.root).join(pkgpath.replace('.', &std::path::MAIN_SEPARATOR.to_string())); - let mut positions = get_pos_from_real_path(&real_path); +#[cfg(test)] +mod tests { + use super::goto_definition_with_gs; + use crate::{ + from_lsp::file_path_from_url, + tests::{compare_goto_res, compile_test_file}, + }; + use indexmap::IndexSet; + use kclvm_error::Position as KCLPos; + use proc_macro_crate::bench_test; + use std::path::PathBuf; - if positions.is_empty() && !real_path.exists() { - real_path = - get_real_path_from_external(&stmt.pkg_name, pkgpath, program.root.clone().into()); - } + #[test] + #[bench_test] + fn goto_import_pkg_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + let pos = KCLPos { + filename: file, + line: 1, + column: Some(10), + }; - positions = get_pos_from_real_path(&real_path); + let res = goto_definition_with_gs(&program, &pos, &gs); - positions_to_goto_def_resp(&positions) -} + let mut expected_files = IndexSet::new(); + let path_str = path.to_str().unwrap(); + let test_files = [ + "src/test_data/goto_def_test/pkg/schema_def1.k", + "src/test_data/goto_def_test/pkg/schema_def.k", + ]; + expected_files.insert(format!("{}/{}", path_str, test_files[0])); + expected_files.insert(format!("{}/{}", path_str, test_files[1])); -// Todo: fix ConfigExpr -// ```kcl -// schema Person: -// name: str -// data: Data - -// schema Data: -// id: int - -// person = Person { -// data.id = 1 -// data: { -// id = 1 -// } -// data: Data { -// id = 3 -// } -// } -pub(crate) fn find_def_of_schema_attr( - schema_expr: SchemaExpr, - prog_scope: &ProgramScope, - attr_name: String, -) -> Vec { - let schema_name = get_identifier_last_name(&schema_expr.name.node); - let mut res = vec![]; - for scope in prog_scope.scope_map.values() { - let s = scope.borrow(); - if let Some(scope) = s.search_child_scope_by_name(&schema_name) { - let s = scope.borrow(); - if matches!(s.kind, kclvm_sema::resolver::scope::ScopeKind::Schema(_)) { - for (attr, obj) in &s.elems { - if attr == &attr_name { - res.push(obj.borrow().clone()); - } + match res.unwrap() { + lsp_types::GotoDefinitionResponse::Array(arr) => { + assert_eq!(expected_files.len(), arr.len()); + for loc in arr { + let got_path = file_path_from_url(&loc.uri).unwrap(); + assert!(expected_files.contains(&got_path)); } } + _ => { + unreachable!("test error") + } } } - res -} -pub(crate) fn get_identifier_last_name(id: &Identifier) -> String { - match id.names.len() { - 0 => "".to_string(), - 1 => id.names[0].clone(), - _ => { - if id.names.last().unwrap().clone() == *"" { - // MissingExpr - id.names.get(id.names.len() - 2).unwrap().clone() - } else { - id.names.last().unwrap().clone() + #[test] + #[bench_test] + fn goto_import_file_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test goto import file: import .pkg.schema_def + let pos = KCLPos { + filename: file, + line: 2, + column: Some(10), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + match res.unwrap() { + lsp_types::GotoDefinitionResponse::Scalar(loc) => { + let got_path = file_path_from_url(&loc.uri).unwrap(); + assert_eq!(got_path, expected_path.to_str().unwrap()) + } + _ => { + unreachable!("test error") } } } + + #[test] + #[bench_test] + fn goto_pkg_prefix_def_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + // test goto pkg prefix def: p = pkg.Person { <- pkg + let pos = KCLPos { + filename: file, + line: 4, + column: Some(7), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_files = IndexSet::new(); + let path_str = path.to_str().unwrap(); + let test_files = [ + "src/test_data/goto_def_test/pkg/schema_def1.k", + "src/test_data/goto_def_test/pkg/schema_def.k", + ]; + expected_files.insert(format!("{}/{}", path_str, test_files[0])); + expected_files.insert(format!("{}/{}", path_str, test_files[1])); + + match res.unwrap() { + lsp_types::GotoDefinitionResponse::Array(arr) => { + assert_eq!(expected_files.len(), arr.len()); + for loc in arr { + let got_path = file_path_from_url(&loc.uri).unwrap(); + assert!(expected_files.contains(&got_path)); + } + } + _ => { + unreachable!("test error") + } + } + } + + #[test] + #[bench_test] + fn goto_schema_def_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test goto schema definition: p = pkg.Person <- Person + let pos = KCLPos { + filename: file, + line: 4, + column: Some(11), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 13), + ); + } + + #[test] + #[bench_test] + fn goto_var_def_in_config_and_config_if_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 67, + column: Some(36), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 65, 11, 65, 14)); + + let pos = KCLPos { + filename: file.clone(), + line: 67, + column: Some(44), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 65, 16, 65, 21)); + let pos = KCLPos { + filename: file.clone(), + line: 64, + column: Some(11), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 69, 6, 69, 10)); + let pos = KCLPos { + filename: file.clone(), + line: 67, + column: Some(10), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 69, 6, 69, 10)); + } + + #[test] + #[bench_test] + fn goto_var_def_in_dict_comp_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 77, + column: Some(68), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 76, 143, 76, 145)); + + let pos = KCLPos { + filename: file.clone(), + line: 77, + column: Some(61), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 76, 143, 76, 145)); + } + + #[test] + #[bench_test] + fn goto_schema_attr_def_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test goto schema attr definition: name: "alice" + let pos = KCLPos { + filename: file, + line: 5, + column: Some(7), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 4, 4, 4, 8), + ); + } + + #[test] + #[bench_test] + fn goto_schema_attr_def_test1() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/goto_def.k"); + + // test goto schema attr definition, goto name in: s = p2.n.name + let pos = KCLPos { + filename: file, + line: 30, + column: Some(12), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 18, 4, 18, 8), + ); + } + + #[test] + #[bench_test] + fn test_goto_identifier_names() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/goto_def.k"); + + // test goto p2 in: s = p2.n.name + let pos = KCLPos { + filename: file.clone(), + line: 30, + column: Some(5), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 23, 0, 23, 2), + ); + + // test goto n in: s = p2.n.name + let pos = KCLPos { + filename: file.clone(), + line: 30, + column: Some(8), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 21, 1, 21, 2), + ); + + // test goto name in: s = p2.n.name + let pos = KCLPos { + filename: file, + line: 30, + column: Some(12), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 18, 4, 18, 8), + ); + } + + #[test] + #[bench_test] + fn goto_identifier_def_test() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + // test goto identifier definition: p1 = p + let pos = KCLPos { + filename: file.to_string(), + line: 9, + column: Some(6), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 3, 0, 3, 1)); + } + + #[test] + #[bench_test] + fn goto_assign_type_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test goto schema attr definition: name: "alice" + let pos = KCLPos { + filename: file.clone(), + line: 38, + column: Some(17), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 33, 7, 33, 15)); + } + + #[test] + #[bench_test] + fn goto_schema_attr_ty_def_test() { + // test goto schema attr type definition: p1: pkg.Person + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file, + line: 12, + column: Some(15), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 13), + ); + } + + #[test] + #[bench_test] + fn goto_schema_attr_ty_def_test1() { + // test goto schema attr type definition: p2: [pkg.Person] + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file, + line: 13, + column: Some(15), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 13), + ); + } + + #[test] + #[bench_test] + fn goto_schema_attr_ty_def_test3() { + // test goto schema attr type definition: p3: {str: pkg.Person} + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file, + line: 14, + column: Some(22), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 13), + ); + } + + #[test] + #[bench_test] + fn goto_schema_attr_ty_def_test4() { + // test goto schema attr type definition(Person): p4: pkg.Person | pkg.Person1 + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + let pos = KCLPos { + filename: file, + line: 15, + column: Some(17), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 13), + ); + } + + #[test] + #[bench_test] + fn goto_schema_attr_ty_def_test5() { + // test goto schema attr type definition(Person1): p4: pkg.Person | pkg.Person1 + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def1.k"); + + let pos = KCLPos { + filename: file, + line: 15, + column: Some(28), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 7, 0, 14), + ); + } + + #[test] + #[bench_test] + fn goto_local_var_def_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test goto local var def + let pos = KCLPos { + filename: file.clone(), + line: 47, + column: Some(11), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 43, 4, 43, 9)); + + let pos = KCLPos { + filename: file.clone(), + line: 49, + column: Some(11), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 43, 4, 43, 9)); + + let pos = KCLPos { + filename: file.clone(), + line: 51, + column: Some(11), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 43, 4, 43, 9)); + } + + #[test] + #[bench_test] + fn complex_select_goto_def() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 52, + column: Some(22), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 43, 4, 43, 9)); + } + + #[test] + #[bench_test] + fn schema_attribute_def_goto_def() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 19, + column: Some(5), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 18, 4, 18, 8)); + } + + #[test] + #[bench_test] + fn config_desuger_def_goto_def() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 82, + column: Some(9), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 18, 4, 18, 8)); + } + + #[test] + #[bench_test] + fn lambda_param_goto_def() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 86, + column: Some(4), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 84, 14, 84, 15)); + + let pos = KCLPos { + filename: file.clone(), + line: 86, + column: Some(8), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 84, 22, 84, 23)); + } + + #[test] + #[bench_test] + fn list_if_expr_test() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 91, + column: Some(8), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 88, 0, 88, 1)); + } + + #[test] + #[bench_test] + fn lambda_local_var_test() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 96, + column: Some(9), + }; + + let res = goto_definition_with_gs(&program, &pos, &gs); + compare_goto_res(res, (&file, 94, 11, 94, 12)); + } } diff --git a/kclvm/tools/src/LSP/src/hover.rs b/kclvm/tools/src/LSP/src/hover.rs index 2d2f948a7..1ea8a0f58 100644 --- a/kclvm/tools/src/LSP/src/hover.rs +++ b/kclvm/tools/src/LSP/src/hover.rs @@ -1,45 +1,87 @@ -use indexmap::IndexSet; use kclvm_ast::ast::Program; use kclvm_error::Position as KCLPos; -use kclvm_sema::resolver::scope::{ProgramScope, ScopeObjectKind}; +use kclvm_sema::{ + builtin::BUILTIN_DECORATORS, + core::global_state::GlobalState, + ty::{FunctionType, SchemaType}, +}; use lsp_types::{Hover, HoverContents, MarkedString}; -use crate::goto_def::find_definition_objs; +use crate::goto_def::find_def_with_gs; /// Returns a short text describing element at position. /// Specifically, the doc for schema and schema attr(todo) pub(crate) fn hover( - program: &Program, + _program: &Program, kcl_pos: &KCLPos, - prog_scope: &ProgramScope, + gs: &GlobalState, ) -> Option { - match program.pos_to_stmt(kcl_pos) { - Some(node) => { - let objs = find_definition_objs(node, kcl_pos, prog_scope); - let mut docs: IndexSet = IndexSet::new(); - for obj in &objs { - match obj.kind { - ScopeObjectKind::Definition => { - docs.insert(obj.ty.ty_str()); - let doc = obj.ty.into_schema_type().doc.clone(); - if !doc.is_empty() { - docs.insert(doc); + let mut docs: Vec = vec![]; + let def = find_def_with_gs(kcl_pos, gs, true); + match def { + Some(def_ref) => match gs.get_symbols().get_symbol(def_ref) { + Some(obj) => match def_ref.get_kind() { + kclvm_sema::core::symbol::SymbolKind::Schema => match &obj.get_sema_info().ty { + Some(schema_ty) => { + docs.extend(build_schema_hover_content(&schema_ty.into_schema_type())); + } + _ => {} + }, + kclvm_sema::core::symbol::SymbolKind::Attribute => { + let sema_info = obj.get_sema_info(); + match &sema_info.ty { + Some(ty) => { + docs.push(format!("{}: {}", &obj.get_name(), ty.ty_str())); + if let Some(doc) = &sema_info.doc { + if !doc.is_empty() { + docs.push(doc.clone()); + } + } } + _ => {} } - _ => { - docs.insert(obj.ty.ty_str()); + } + kclvm_sema::core::symbol::SymbolKind::Value => match &obj.get_sema_info().ty { + Some(ty) => match &ty.kind { + kclvm_sema::ty::TypeKind::Function(func_ty) => { + docs.extend(build_func_hover_content(func_ty, obj.get_name().clone())); + } + _ => { + docs.push(format!("{}: {}", &obj.get_name(), ty.ty_str())); + } + }, + _ => {} + }, + kclvm_sema::core::symbol::SymbolKind::Expression => return None, + kclvm_sema::core::symbol::SymbolKind::Decorator => { + match BUILTIN_DECORATORS.get(&obj.get_name()) { + Some(ty) => { + docs.extend(build_func_hover_content( + &ty.into_func_type(), + obj.get_name().clone(), + )); + } + None => todo!(), } } - } - docs_to_hover(docs) - } - None => None, + _ => { + let ty_str = match &obj.get_sema_info().ty { + Some(ty) => ty.ty_str(), + None => "".to_string(), + }; + docs.push(format!("{}: {}", &obj.get_name(), ty_str)); + } + }, + None => {} + }, + None => {} } + docs_to_hover(docs) } // Convert docs to Hover. This function will convert to // None, Scalar or Array according to the number of positions -fn docs_to_hover(docs: IndexSet) -> Option { +fn docs_to_hover(docs: Vec) -> Option { match docs.len() { 0 => None, 1 => Some(Hover { @@ -56,3 +98,443 @@ fn docs_to_hover(docs: IndexSet) -> Option { }), } } + +// Build hover content for schema definition +// Schema Definition hover +// ``` +// pkg +// schema Foo(Base)[param: type] +// ----------------- +// doc +// ----------------- +// Attributes: +// attr1: type +// attr2? type +// ``` +fn build_schema_hover_content(schema_ty: &SchemaType) -> Vec { + let mut docs = vec![]; + docs.push(schema_ty.schema_ty_signature_str()); + if !schema_ty.doc.is_empty() { + docs.push(schema_ty.doc.clone()); + } + let mut attrs = vec!["Attributes:".to_string()]; + for (name, attr) in &schema_ty.attrs { + attrs.push(format!( + "{}{}:{}", + name, + if attr.is_optional { "?" } else { "" }, + format!(" {}", attr.ty.ty_str()), + )); + } + docs.push(attrs.join("\n\n")); + docs +} + +// Build hover content for function call +// ``` +// pkg +// ----------------- +// function func_name(arg1: type, arg2: type, ..) -> type +// ----------------- +// doc +// ``` +fn build_func_hover_content(func_ty: &FunctionType, name: String) -> Vec { + let mut docs = vec![]; + if let Some(ty) = &func_ty.self_ty { + let self_ty = format!("{}\n\n", ty.ty_str()); + docs.push(self_ty); + } + + let mut sig = format!("fn {}(", name); + if func_ty.params.is_empty() { + sig.push(')'); + } else { + for (i, p) in func_ty.params.iter().enumerate() { + sig.push_str(&format!("{}: {}", p.name, p.ty.ty_str())); + + if i != func_ty.params.len() - 1 { + sig.push_str(", "); + } + } + sig.push(')'); + } + sig.push_str(&format!(" -> {}", func_ty.return_ty.ty_str())); + docs.push(sig); + + if !func_ty.doc.is_empty() { + docs.push(func_ty.doc.clone().replace('\n', "\n\n")); + } + docs +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use kclvm_error::Position as KCLPos; + use lsp_types::MarkedString; + use proc_macro_crate::bench_test; + + use crate::tests::compile_test_file; + + use super::hover; + + #[test] + #[bench_test] + fn schema_doc_hover_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let (file, program, _, _, gs) = compile_test_file("src/test_data/goto_def_test/goto_def.k"); + + let mut expected_path = path; + expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + + // test hover of schema doc: p = pkg.Person + let pos = KCLPos { + filename: file.clone(), + line: 4, + column: Some(11), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Array(vec) => { + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "pkg\n\nschema Person"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "hover doc test"); + } + if let MarkedString::String(s) = vec[2].clone() { + assert_eq!(s, "Attributes:\n\nname: str\n\nage: int"); + } + } + _ => unreachable!("test error"), + } + let pos = KCLPos { + filename: file, + line: 5, + column: Some(7), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Scalar(marked_string) => { + if let MarkedString::String(s) = marked_string { + assert_eq!(s, "name: str"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn schema_doc_hover_test1() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 16, + column: Some(8), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "__main__\n\nschema Person"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "hover doc test"); + } + if let MarkedString::String(s) = vec[2].clone() { + assert_eq!(s, "Attributes:\n\nname: str\n\nage?: int"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn schema_attr_hover_test() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 17, + column: Some(7), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "name: str"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "name doc test"); + } + } + _ => unreachable!("test error"), + } + + let pos = KCLPos { + filename: file.clone(), + line: 18, + column: Some(7), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "age: int"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "age doc test"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn func_def_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 22, + column: Some(18), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 2); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "fn encode(value: str, encoding: str) -> str"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!( + s, + "Encode the string `value` using the codec registered for encoding." + ); + } + } + _ => unreachable!("test error"), + } + + let pos = KCLPos { + filename: file.clone(), + line: 23, + column: Some(14), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 3); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "str\n\n"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "fn count(sub: str, start: int, end: int) -> int"); + } + if let MarkedString::String(s) = vec[2].clone() { + assert_eq!(s, "Return the number of non-overlapping occurrences of substring sub in the range [start, end]. Optional arguments start and end are interpreted as in slice notation."); + } + } + _ => unreachable!("test error"), + } + + let pos = KCLPos { + filename: file.clone(), + line: 25, + column: Some(4), + }; + let got = hover(&program, &pos, &gs).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 2); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "fn print() -> NoneType"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "Prints the values to a stream, or to the system stdout by default.\n\nOptional keyword arguments:\n\nsep: string inserted between values, default a space.\n\nend: string appended after the last value, default a newline."); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn complex_select_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/fib.k"); + let pos = KCLPos { + filename: file.clone(), + line: 14, + column: Some(22), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Scalar(marked_string) => { + if let MarkedString::String(s) = marked_string { + assert_eq!(s, "value: int"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn assignment_ty_in_lambda_hover() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/hover_test/ty_in_lambda.k"); + let pos = KCLPos { + filename: file.clone(), + line: 3, + column: Some(8), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Scalar(marked_string) => { + if let MarkedString::String(s) = marked_string { + assert_eq!(s, "result: {str:str}"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn str_var_func_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let pos = KCLPos { + filename: file.clone(), + line: 28, + column: Some(12), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 3); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "str\n\n"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "fn capitalize() -> str"); + } + if let MarkedString::String(s) = vec[2].clone() { + assert_eq!(s, "Return a copy of the string with its first character capitalized and the rest lowercased."); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn import_pkg_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/import_pkg.k"); + let pos = KCLPos { + filename: file.clone(), + line: 3, + column: Some(7), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 2); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "fib\n\nschema Fib"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "Attributes:\n\nn: int\n\nvalue: int"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn expr_after_config_if_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/hover.k"); + let pos = KCLPos { + filename: file.clone(), + line: 41, + column: Some(13), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Scalar(marked_string) => { + if let MarkedString::String(s) = marked_string { + assert_eq!(s, "stratege: str"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn schema_scope_variable_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/fib.k"); + let pos = KCLPos { + filename: file.clone(), + line: 3, + column: Some(11), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Scalar(marked_string) => { + if let MarkedString::String(s) = marked_string { + assert_eq!(s, "n1: int"); + } + } + _ => unreachable!("test error"), + } + } + + #[test] + #[bench_test] + fn decorator_hover() { + let (file, program, _, _, gs) = compile_test_file("src/test_data/hover_test/decorator.k"); + let pos = KCLPos { + filename: file.clone(), + line: 1, + column: Some(1), + }; + let got = hover(&program, &pos, &gs).unwrap(); + let expect_content = vec![MarkedString::String( + "fn deprecated(version: str, reason: str, strict: bool) -> any".to_string(), + ), MarkedString::String( + "This decorator is used to get the deprecation message according to the wrapped key-value pair.".to_string(), + )]; + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec, expect_content) + } + _ => unreachable!("test error"), + } + + let pos = KCLPos { + filename: file.clone(), + line: 3, + column: Some(8), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec, expect_content); + } + _ => unreachable!("test error"), + } + } +} diff --git a/kclvm/tools/src/LSP/src/lib.rs b/kclvm/tools/src/LSP/src/lib.rs index b2d0584bb..8aaf01612 100644 --- a/kclvm/tools/src/LSP/src/lib.rs +++ b/kclvm/tools/src/LSP/src/lib.rs @@ -1,16 +1,23 @@ mod analysis; +mod capabilities; mod completion; mod config; mod db; mod dispatcher; -mod find_ref; +mod document_symbol; +mod find_refs; +mod formatting; mod from_lsp; +mod goto_def; +mod hover; +mod main_loop; mod notification; +mod quick_fix; +pub mod rename; +mod request; +mod semantic_token; mod state; +#[cfg(test)] +mod tests; mod to_lsp; mod util; - -mod document_symbol; -mod goto_def; -mod hover; -mod request; diff --git a/kclvm/tools/src/LSP/src/main.rs b/kclvm/tools/src/LSP/src/main.rs index 912353023..1c3e58b85 100644 --- a/kclvm/tools/src/LSP/src/main.rs +++ b/kclvm/tools/src/LSP/src/main.rs @@ -1,6 +1,6 @@ +use crate::main_loop::main_loop; use config::Config; -use lsp_server::Connection; -use state::LanguageServerState; +use main_loop::app; mod analysis; mod capabilities; @@ -9,25 +9,55 @@ mod config; mod db; mod dispatcher; mod document_symbol; +mod find_refs; mod from_lsp; mod goto_def; mod hover; +mod main_loop; mod notification; +mod quick_fix; mod request; +mod semantic_token; mod state; mod to_lsp; mod util; +mod formatting; #[cfg(test)] mod tests; -/// Runs the main loop of the language server. This will receive requests and handle them. -pub fn main_loop(connection: Connection, config: Config) -> anyhow::Result<()> { - LanguageServerState::new(connection.sender, config).run(connection.receiver) +/// Main entry point for the `kcl-language-server` executable. +fn main() -> Result<(), anyhow::Error> { + let args: Vec = std::env::args().collect(); + let matches = app() + .arg_required_else_help(false) + .try_get_matches_from(args); + match matches { + Ok(arg_matches) => match arg_matches.subcommand() { + Some(("version", _)) => { + println!("{}", kclvm_version::get_version_info()); + Ok(()) + } + Some((subcommand, _)) => Err(anyhow::anyhow!("unknown subcommand: {}", subcommand)), + None => { + let status: Result = { + run_server().map_err(|e| anyhow::anyhow!("{}", e))?; + Ok(ExitStatus::Success) + }; + match status.unwrap() { + ExitStatus::Success => {} + ExitStatus::Error => std::process::exit(1), + }; + Ok(()) + } + }, + Err(e) => Err(e.into()), + } } +#[allow(dead_code)] /// Main entry point for the language server -pub fn run_server() -> anyhow::Result<()> { +fn run_server() -> anyhow::Result<()> { // Setup IO connections let (connection, io_threads) = lsp_server::Connection::stdio(); // Wait for a client to connect @@ -50,28 +80,15 @@ pub fn run_server() -> anyhow::Result<()> { .map_err(|_| anyhow::anyhow!("Initialize result error"))?; connection.initialize_finish(initialize_id, initialize_result)?; - let config = Config::default(); - main_loop(connection, config)?; + main_loop(connection, config, initialize_params)?; io_threads.join()?; Ok(()) } +#[allow(dead_code)] #[derive(Copy, Debug, Clone, PartialEq, Eq)] -pub enum ExitStatus { +enum ExitStatus { Success, Error, } - -/// Main entry point for the `kcl-language-server` executable. -fn main() -> Result<(), anyhow::Error> { - let status: Result = { - run_server().map_err(|e| anyhow::anyhow!("{}", e))?; - Ok(ExitStatus::Success) - }; - match status.unwrap() { - ExitStatus::Success => {} - ExitStatus::Error => std::process::exit(1), - }; - Ok(()) -} diff --git a/kclvm/tools/src/LSP/src/main_loop.rs b/kclvm/tools/src/LSP/src/main_loop.rs new file mode 100644 index 000000000..b0f8b16c1 --- /dev/null +++ b/kclvm/tools/src/LSP/src/main_loop.rs @@ -0,0 +1,24 @@ +use crate::config::Config; +use crate::state::LanguageServerState; +use clap::Command; +use lsp_server::Connection; +use lsp_types::InitializeParams; + +#[allow(dead_code)] +/// Runs the main loop of the language server. This will receive requests and handle them. +pub(crate) fn main_loop( + connection: Connection, + config: Config, + initialize_params: InitializeParams, +) -> anyhow::Result<()> { + LanguageServerState::new(connection.sender, config, initialize_params).run(connection.receiver) +} + +#[allow(dead_code)] +/// Get the kcl language server CLI application. +pub(crate) fn app() -> Command { + Command::new("kcl-language-server") + .version(kclvm_version::VERSION) + .about("KCL language server CLI.") + .subcommand(Command::new("version").about("Show the KCL language server version")) +} diff --git a/kclvm/tools/src/LSP/src/notification.rs b/kclvm/tools/src/LSP/src/notification.rs index d18a0cf35..deb10f807 100644 --- a/kclvm/tools/src/LSP/src/notification.rs +++ b/kclvm/tools/src/LSP/src/notification.rs @@ -1,8 +1,15 @@ -use lsp_types::notification::{DidChangeTextDocument, DidOpenTextDocument, DidSaveTextDocument}; +use lsp_types::notification::{ + Cancel, DidChangeTextDocument, DidChangeWatchedFiles, DidCloseTextDocument, + DidOpenTextDocument, DidSaveTextDocument, +}; +use std::path::Path; use crate::{ - dispatcher::NotificationDispatcher, from_lsp, state::LanguageServerState, + dispatcher::NotificationDispatcher, + from_lsp, + state::LanguageServerState, util::apply_document_changes, + util::{build_word_index_for_file_content, word_index_add, word_index_subtract}, }; impl LanguageServerState { @@ -15,12 +22,22 @@ impl LanguageServerState { .on::(LanguageServerState::on_did_open_text_document)? .on::(LanguageServerState::on_did_change_text_document)? .on::(LanguageServerState::on_did_save_text_document)? - // .on::(LanguageServerState::on_did_close_text_document)? - // .on::(LanguageServerState::on_did_change_watched_files)? + .on::(LanguageServerState::on_did_close_text_document)? + .on::(LanguageServerState::on_did_change_watched_files)? + .on::(LanguageServerState::cancel)? .finish(); Ok(()) } + fn cancel(&mut self, params: lsp_types::CancelParams) -> anyhow::Result<()> { + let id: lsp_server::RequestId = match params.id { + lsp_types::NumberOrString::Number(id) => id.into(), + lsp_types::NumberOrString::String(id) => id.into(), + }; + self.request_queue.incoming.complete(id); + Ok(()) + } + /// Called when a `DidOpenTextDocument` notification was received. fn on_did_open_text_document( &mut self, @@ -28,9 +45,15 @@ impl LanguageServerState { ) -> anyhow::Result<()> { let path = from_lsp::abs_path(¶ms.text_document.uri)?; self.log_message(format!("on did open file: {:?}", path)); - self.vfs - .write() - .set_file_contents(path.into(), Some(params.text_document.text.into_bytes())); + + self.vfs.write().set_file_contents( + path.clone().into(), + Some(params.text_document.text.into_bytes()), + ); + + if let Some(id) = self.vfs.read().file_id(&path.into()) { + self.opened_files.insert(id); + } Ok(()) } @@ -62,15 +85,59 @@ impl LanguageServerState { let path = from_lsp::abs_path(&text_document.uri)?; self.log_message(format!("on did_change file: {:?}", path)); + // update vfs let vfs = &mut *self.vfs.write(); let file_id = vfs .file_id(&path.clone().into()) .ok_or(anyhow::anyhow!("Already checked that the file_id exists!"))?; let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec())?; + let old_text = text.clone(); apply_document_changes(&mut text, content_changes); - vfs.set_file_contents(path.into(), Some(text.into_bytes())); + vfs.set_file_contents(path.into(), Some(text.clone().into_bytes())); + + // update word index + let old_word_index = build_word_index_for_file_content(old_text, &text_document.uri, true); + let new_word_index = + build_word_index_for_file_content(text.clone(), &text_document.uri, true); + let binding = from_lsp::file_path_from_url(&text_document.uri)?; + let file_path = Path::new(&binding); //todo rename + let word_index_map = &mut *self.word_index_map.write(); + for (key, value) in word_index_map { + let workspace_folder_path = Path::new(key.path()); + if file_path.starts_with(workspace_folder_path) { + word_index_subtract(value, old_word_index.clone()); + word_index_add(value, new_word_index.clone()); + } + } + + Ok(()) + } + /// Called when a `DidCloseTextDocument` notification was received. + fn on_did_close_text_document( + &mut self, + params: lsp_types::DidCloseTextDocumentParams, + ) -> anyhow::Result<()> { + let path = from_lsp::abs_path(¶ms.text_document.uri)?; + + if let Some(id) = self.vfs.read().file_id(&path.clone().into()) { + self.opened_files.remove(&id); + } + self.loader.handle.invalidate(path); + + Ok(()) + } + + /// Called when a `DidChangeWatchedFiles` was received + fn on_did_change_watched_files( + &mut self, + params: lsp_types::DidChangeWatchedFilesParams, + ) -> anyhow::Result<()> { + for change in params.changes { + let path = from_lsp::abs_path(&change.uri)?; + self.loader.handle.invalidate(path); + } Ok(()) } } diff --git a/kclvm/tools/src/LSP/src/quick_fix.rs b/kclvm/tools/src/LSP/src/quick_fix.rs new file mode 100644 index 000000000..cf256ed2b --- /dev/null +++ b/kclvm/tools/src/LSP/src/quick_fix.rs @@ -0,0 +1,240 @@ +use std::collections::HashMap; + +use kclvm_error::{DiagnosticId, ErrorKind, WarningKind}; +use lsp_types::{ + CodeAction, CodeActionKind, CodeActionOrCommand, Diagnostic, NumberOrString, TextEdit, Url, +}; +use serde_json::Value; + +pub(crate) fn quick_fix(uri: &Url, diags: &Vec) -> Vec { + let mut code_actions: Vec = vec![]; + for diag in diags { + if let Some(code) = &diag.code { + if let Some(id) = conver_code_to_kcl_diag_id(code) { + match id { + DiagnosticId::Error(error) => match error { + ErrorKind::CompileError => { + let replacement_texts = extract_suggested_replacements(&diag.data); + for replacement_text in replacement_texts { + let mut changes = HashMap::new(); + changes.insert( + uri.clone(), + vec![TextEdit { + range: diag.range, + new_text: replacement_text.clone(), + }], + ); + let action_title = format!( + "a local variable with a similar name exists: `{}`", + replacement_text + ); + code_actions.push(CodeActionOrCommand::CodeAction(CodeAction { + title: action_title, + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diag.clone()]), + edit: Some(lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }), + ..Default::default() + })); + } + } + _ => continue, + }, + DiagnosticId::Warning(warn) => match warn { + WarningKind::UnusedImportWarning => { + let mut changes = HashMap::new(); + changes.insert( + uri.clone(), + vec![TextEdit { + range: diag.range, + new_text: "".to_string(), + }], + ); + code_actions.push(CodeActionOrCommand::CodeAction(CodeAction { + title: WarningKind::UnusedImportWarning.name(), + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diag.clone()]), + edit: Some(lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }), + ..Default::default() + })) + } + WarningKind::ReimportWarning => { + let mut changes = HashMap::new(); + changes.insert( + uri.clone(), + vec![TextEdit { + range: diag.range, + new_text: "".to_string(), + }], + ); + code_actions.push(CodeActionOrCommand::CodeAction(CodeAction { + title: WarningKind::ReimportWarning.name(), + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diag.clone()]), + edit: Some(lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }), + ..Default::default() + })) + } + _ => continue, + }, + DiagnosticId::Suggestions => continue, + } + } + } + } + code_actions +} + +fn extract_suggested_replacements(data: &Option) -> Vec { + data.as_ref() + .and_then(|data| match data { + Value::Object(obj) => obj.get("suggested_replacement").map(|val| match val { + Value::String(s) => vec![s.clone()], + Value::Array(arr) => arr + .iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect(), + _ => vec![], + }), + _ => None, + }) + .unwrap_or_else(Vec::new) +} + +pub(crate) fn conver_code_to_kcl_diag_id(code: &NumberOrString) -> Option { + match code { + NumberOrString::Number(_) => None, + NumberOrString::String(code) => match code.as_str() { + "CompilerWarning" => Some(DiagnosticId::Warning(WarningKind::CompilerWarning)), + "UnusedImportWarning" => Some(DiagnosticId::Warning(WarningKind::UnusedImportWarning)), + "ReimportWarning" => Some(DiagnosticId::Warning(WarningKind::ReimportWarning)), + "CompileError" => Some(DiagnosticId::Error(ErrorKind::CompileError)), + "ImportPositionWarning" => { + Some(DiagnosticId::Warning(WarningKind::ImportPositionWarning)) + } + _ => None, + }, + } +} + +#[cfg(test)] +mod tests { + + use lsp_types::{ + CodeAction, CodeActionKind, CodeActionOrCommand, Diagnostic, Position, Range, TextEdit, + Url, WorkspaceEdit, + }; + use proc_macro_crate::bench_test; + use std::path::PathBuf; + + use super::quick_fix; + use crate::{ + to_lsp::kcl_diag_to_lsp_diags, + util::{parse_param_and_compile, Param}, + }; + use parking_lot::RwLock; + use std::sync::Arc; + + #[test] + #[bench_test] + fn quick_fix_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut test_file = path.clone(); + test_file.push("src/test_data/quick_fix.k"); + let file = test_file.to_str().unwrap(); + + let (_, _, diags, _) = parse_param_and_compile( + Param { + file: file.to_string(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); + + let diagnostics = diags + .iter() + .flat_map(|diag| kcl_diag_to_lsp_diags(diag, file)) + .collect::>(); + + let uri = Url::from_file_path(file).unwrap(); + let code_actions = quick_fix(&uri, &diagnostics); + + let expected = vec![ + CodeActionOrCommand::CodeAction(CodeAction { + title: "ReimportWarning".to_string(), + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diagnostics[0].clone()]), + edit: Some(WorkspaceEdit { + changes: Some( + vec![( + uri.clone(), + vec![TextEdit { + range: Range { + start: Position { + line: 1, + character: 0, + }, + end: Position { + line: 1, + character: 20, + }, + }, + new_text: "".to_string(), + }], + )] + .into_iter() + .collect(), + ), + ..Default::default() + }), + ..Default::default() + }), + CodeActionOrCommand::CodeAction(CodeAction { + title: "UnusedImportWarning".to_string(), + kind: Some(CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diagnostics[1].clone()]), + edit: Some(WorkspaceEdit { + changes: Some( + vec![( + uri.clone(), + vec![TextEdit { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 20, + }, + }, + new_text: "".to_string(), + }], + )] + .into_iter() + .collect(), + ), + ..Default::default() + }), + ..Default::default() + }), + ]; + + for (get, expected) in code_actions.iter().zip(expected.iter()) { + assert_eq!(get, expected) + } + + assert_eq!(expected[0], code_actions[0]); + assert_eq!(expected[1], code_actions[1]); + } +} diff --git a/kclvm/tools/src/LSP/src/rename.rs b/kclvm/tools/src/LSP/src/rename.rs new file mode 100644 index 000000000..7710ef770 --- /dev/null +++ b/kclvm/tools/src/LSP/src/rename.rs @@ -0,0 +1,924 @@ +use crate::{ + from_lsp::kcl_pos, + goto_def::find_def_with_gs, + util::{build_word_index_for_source_codes, VirtualLocation}, +}; +use anyhow::{anyhow, Result}; +use chumsky::chain::Chain; +use kclvm_ast::ast::{self, Program}; +use kclvm_error::diagnostic; +use kclvm_parser::{load_program, LoadProgramOptions, ParseSessionRef}; +use kclvm_query::{path::parse_attribute_path, selector::parse_symbol_selector_spec}; +use kclvm_sema::{ + advanced_resolver::AdvancedResolver, core::global_state::GlobalState, namer::Namer, + resolver::resolve_program_with_opts, +}; +use lsp_types::{Position, Range, TextEdit}; +use parking_lot::RwLock; +use ra_ap_vfs::{Vfs, VfsPath}; +use std::fs; +use std::path::PathBuf; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; + +/// [`rename_symbol_on_file`] will rename the symbol in the given files +/// It will load the file content from file system and save to vfs, and then call [`rename_symbol`] to rename the symbol +pub fn rename_symbol_on_file( + pkg_root: &str, + symbol_path: &str, + file_paths: &[String], + new_name: String, +) -> Result> { + // load file content from file system and save to vfs + let vfs: Arc> = Arc::new(RwLock::new(Default::default())); + let mut source_codes = HashMap::::new(); + for path in file_paths { + let content = fs::read_to_string(path.clone())?; + vfs.write().set_file_contents( + VfsPath::new_real_path(path.to_string()), + Some(content.clone().into_bytes()), + ); + source_codes.insert(path.to_string(), content.clone()); + } + let changes = rename_symbol(pkg_root, vfs, symbol_path, new_name, VfsPath::new_real_path)?; + let new_codes = apply_rename_changes(&changes, source_codes)?; + let mut changed_paths = vec![]; + for (path, content) in new_codes.iter() { + fs::write(path.clone(), content)?; + changed_paths.push(path.clone()); + } + Ok(changed_paths) +} + +/// [`rename_symbol_on_code`] will rename the symbol in the given code +/// It will create a vfs from the file paths and codes, and then call [`rename_symbol`] to rename the symbol +pub fn rename_symbol_on_code( + pkg_root: &str, + symbol_path: &str, + source_codes: HashMap, + new_name: String, +) -> Result> { + // prepare a vfs from given file_paths + let vfs: Arc> = Arc::new(RwLock::new(Default::default())); + for (filepath, code) in &source_codes { + vfs.write().set_file_contents( + VfsPath::new_virtual_path(filepath.clone()), + Some(code.as_bytes().to_vec()), + ); + } + let changes: HashMap> = rename_symbol( + pkg_root, + vfs, + symbol_path, + new_name, + VfsPath::new_virtual_path, + )?; + return apply_rename_changes(&changes, source_codes); +} + +fn package_path_to_file_path(pkg_path: &str, vfs: Arc>) -> Vec { + let pkg = PathBuf::from(pkg_path); + let vfs_read = vfs.read(); + let mut result: Vec = vec![]; + + // first search as directory(KCL package in the strict sense) + result.extend(vfs_read.iter().filter_map(|(_, vfs_path)| { + let path = PathBuf::from(vfs_path.to_string()); + if let Some(parent) = path.parent() { + if parent == pkg { + return Some(vfs_path.to_string()); + } + } + None + })); + + if result.is_empty() { + // then search as file(KCL module) + result.extend(vfs_read.iter().filter_map(|(_, vfs_path)| { + let path = PathBuf::from(vfs_path.to_string()); + if pkg.with_extension("k") == path { + return Some(vfs_path.to_string()); + } + None + })); + } + + result +} + +/// Select a symbol by the symbol path +/// The symbol path should be in the format of: `pkg.sub_pkg:name.sub_name` +/// returns the symbol name and definition range +fn select_symbol( + symbol_spec: &ast::SymbolSelectorSpec, + vfs: Arc>, + trans_vfs_path: F, +) -> Option<(String, diagnostic::Range)> +where + F: Fn(String) -> VfsPath, +{ + let mut pkg = PathBuf::from(&symbol_spec.pkg_root); + let fields = parse_attribute_path(&symbol_spec.field_path).unwrap_or_default(); + if !symbol_spec.pkgpath.is_empty() { + let pkg_names = symbol_spec.pkgpath.split("."); + for n in pkg_names { + pkg = pkg.join(n) + } + } + let pkg_path = pkg.as_path().to_str().unwrap(); + + let file_paths = package_path_to_file_path(pkg_path, vfs.clone()); + + if let Ok((_, gs)) = parse_files_with_vfs( + pkg_path.to_string(), + file_paths, + vfs.clone(), + trans_vfs_path, + ) { + if let Some(symbol_ref) = gs + .get_symbols() + .get_symbol_by_fully_qualified_name(&kclvm_ast::MAIN_PKG) + { + let mut owner_ref = symbol_ref; + let mut target = None; + for field in &fields { + let owner = gs.get_symbols().get_symbol(owner_ref).unwrap(); + target = owner.get_attribute(field, gs.get_symbols(), None); + if let Some(target) = target { + owner_ref = target; + } + } + let target_symbol = gs.get_symbols().get_symbol(target?)?; + return Some((target_symbol.get_name(), target_symbol.get_range().clone())); + } + } + None +} + +fn parse_files_with_vfs( + work_dir: String, + file_paths: Vec, + vfs: Arc>, + trans_vfs_path: F, +) -> anyhow::Result<(Program, GlobalState)> +where + F: Fn(String) -> VfsPath, +{ + let mut opt = LoadProgramOptions::default(); + opt.work_dir = work_dir; + opt.load_plugins = true; + opt.k_code_list = { + let mut list = vec![]; + let vfs = &vfs.read(); + for file in &file_paths { + match vfs.file_id(&trans_vfs_path(file.clone())) { + Some(id) => { + // Load code from vfs + list.push(String::from_utf8(vfs.file_contents(id).to_vec()).unwrap()); + } + None => {} + } + } + list + }; + + let files: Vec<&str> = file_paths.iter().map(|s| s.as_str()).collect(); + let sess: ParseSessionRef = ParseSessionRef::default(); + let mut program = load_program(sess.clone(), &files, Some(opt), None)?.program; + + let prog_scope = resolve_program_with_opts( + &mut program, + kclvm_sema::resolver::Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + None, + ); + + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + let node_ty_map = prog_scope.node_ty_map.clone(); + let global_state = AdvancedResolver::resolve_program(&program, gs, node_ty_map); + + Ok((program, global_state)) +} + +fn apply_rename_changes( + changes: &HashMap>, + source_codes: HashMap, +) -> Result> { + let mut result = HashMap::new(); + for (file_path, edits) in changes { + let file_content = source_codes + .get(file_path) + .ok_or(anyhow!("File content is None"))? + .to_string(); + let file_content_lines: Vec<&str> = file_content.lines().collect(); + let mut updated_lines: Vec = file_content_lines + .iter() + .map(|&line| line.to_string()) + .collect(); + + let mut to_removed = HashSet::new(); + + for edit in edits { + let start_line = edit.range.start.line as usize; + let end_line = edit.range.end.line as usize; + + if start_line == end_line { + // the text edit belongs to a single line + let line = &file_content_lines[start_line]; + let updated_line = apply_text_edit(edit, line); + updated_lines[start_line] = updated_line; + } else { + let start_line_text = &file_content_lines[start_line]; + let end_line_text = &file_content_lines[end_line]; + let start_line_edit = TextEdit { + range: Range { + start: edit.range.start, + end: Position { + line: edit.range.start.line, + character: start_line_text.len() as u32, + }, + }, + new_text: edit.new_text.clone(), + }; + let end_line_edit = TextEdit { + range: Range { + start: Position { + line: edit.range.end.line, + character: 0, + }, + end: edit.range.end, + }, + new_text: String::new(), + }; + let updated_start_line = apply_text_edit(&start_line_edit, start_line_text); + let updated_end_line = apply_text_edit(&end_line_edit, end_line_text); + updated_lines[start_line] = format!("{}{}", updated_start_line, updated_end_line); + + for line_num in (start_line + 1)..end_line + 1 { + // todo, record lines to be deleted, instead of update to empty string + // from start+1 to end + updated_lines[line_num] = String::new(); + to_removed.insert(line_num); + } + } + } + + let retained_lines: Vec<_> = updated_lines + .into_iter() + .enumerate() + .filter(|(index, _)| !to_removed.contains(index)) + .map(|(_, item)| item.to_string()) + .collect(); + + let new_file_content = retained_lines.join("\n"); + result.insert(file_path.to_string(), new_file_content); + } + Ok(result) +} + +/// apply_text_edit applys the text edit to a single line +fn apply_text_edit(edit: &TextEdit, line: &str) -> String { + let range = edit.range; + let start = range.start.character as usize; + let end = range.end.character as usize; + + let mut updated_line = line.to_owned(); + updated_line.replace_range(start..end, &edit.new_text); + updated_line +} + +/// match_pkgpath_and_code matches the pkgpath and code from the symbol selector spec +pub fn match_pkgpath_and_code( + selector: &ast::SymbolSelectorSpec, +) -> (Option, Option) { + let mut pkg = PathBuf::from(&selector.pkg_root); + let pkg_names = selector.pkgpath.split("."); + if !selector.pkgpath.is_empty() { + for n in pkg_names { + pkg = pkg.join(n) + } + } + + match pkg.as_path().to_str() { + Some(pkgpath) => (Some(pkgpath.to_string()), None), + None => (None, None), + } +} + +/// the rename_symbol API +/// find all the occurrences of the target symbol and return the text edit actions to rename them +/// pkg_root: the absolute file path to the root package +/// vfs: contains all the files and contents to be renamed +/// symbol_path: path to the symbol. The symbol path should be in the format of: `pkg.sub_pkg:name.sub_name` +/// new_name: the new name of the symbol +pub fn rename_symbol( + pkg_root: &str, + vfs: Arc>, + symbol_path: &str, + new_name: String, + trans_vfs_path: F, +) -> Result>> +where + F: Fn(String) -> VfsPath, +{ + // 1. from symbol path to the symbol + let symbol_spec = parse_symbol_selector_spec(pkg_root, symbol_path)?; + // 2. get the symbol name and definition range from symbol path + match select_symbol(&symbol_spec, vfs.clone(), &trans_vfs_path) { + Some((name, range)) => { + // 3. build word index, find refs within given scope + // vfs to source code contents + let mut source_codes = HashMap::::new(); + let vfs_content = vfs.read(); + for (file_id, vfspath) in vfs_content.iter() { + let content = std::str::from_utf8(vfs_content.file_contents(file_id)).unwrap(); + source_codes.insert(vfspath.to_string(), content.to_string()); + } + let word_index = build_word_index_for_source_codes(source_codes, true)?; + if let Some(locations) = word_index.get(&name) { + // 4. filter out the matched refs + // 4.1 collect matched words(names) and remove Duplicates of the file paths + let file_map = locations.iter().fold( + HashMap::>::new(), + |mut acc, loc| { + acc.entry(loc.filepath.clone()) + .or_insert(Vec::new()) + .push(loc); + acc + }, + ); + let mut refs = vec![]; + for (fp, locs) in file_map.iter() { + if let Ok((_, gs)) = parse_files_with_vfs( + pkg_root.to_string(), + vec![fp.to_string()], + vfs.clone(), + &trans_vfs_path, + ) { + for loc in locs { + let kcl_pos = kcl_pos(fp, loc.range.start); + if let Some(symbol_ref) = find_def_with_gs(&kcl_pos, &gs, true) { + if let Some(symbol_def) = gs.get_symbols().get_symbol(symbol_ref) { + if symbol_def.get_range() == range { + refs.push(loc) + } + } + } + } + }; + } + // 5. refs to rename actions + let changes = refs.into_iter().fold(HashMap::new(), |mut map, location| { + map.entry(location.filepath.clone()) + .or_insert_with(Vec::new) + .push(TextEdit { + range: location.range, + new_text: new_name.clone(), + }); + map + }); + return Ok(changes); + } else { + return Ok(HashMap::new()); + } + } + None => Err(anyhow!( + "get symbol from symbol path failed, {}", + symbol_path + )), + } +} + +#[cfg(test)] +mod tests { + use kclvm_ast::ast; + use kclvm_error::diagnostic; + use lsp_types::{Position, Range, TextEdit}; + use maplit::hashmap; + use parking_lot::RwLock; + use std::fs; + use std::path::PathBuf; + use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + }; + + use crate::rename::rename_symbol_on_code; + + use super::{ + apply_rename_changes, package_path_to_file_path, rename_symbol, rename_symbol_on_file, + select_symbol, + }; + + use ra_ap_vfs::{Vfs, VfsPath}; + + /// prepare_vfs constructs a vfs for test: + /// /mock_root + /// ├── config.k + /// └── base + /// ├── server.k + /// └── person.k + fn prepare_vfs() -> ( + PathBuf, + PathBuf, + PathBuf, + PathBuf, + PathBuf, + Arc>, + ) { + // mock paths + let root = PathBuf::from("/mock_root"); + let base_path = root.join("base"); + let server_path = root.join("base").join("server.k"); + let person_path = root.join("base").join("person.k"); + let config_path = root.join("config.k"); + // mock file contents + let person_content = r#"schema Person: + name: Name + age: int + +schema Name: + first: str + +a = { + abc: "d" +} + +d = a.abc +e = a["abc"] +"#; + let server_content = r#"schema Server: + name: str +"#; + let config_content = r#""#; + + // set vfs + let vfs: Arc> = Arc::new(RwLock::new(Default::default())); + vfs.write().set_file_contents( + VfsPath::new_virtual_path(person_path.as_path().to_str().unwrap().to_string()), + Some(person_content.as_bytes().to_owned()), + ); + vfs.write().set_file_contents( + VfsPath::new_virtual_path(server_path.as_path().to_str().unwrap().to_string()), + Some(server_content.as_bytes().to_owned()), + ); + vfs.write().set_file_contents( + VfsPath::new_virtual_path(config_path.as_path().to_str().unwrap().to_string()), + Some(config_content.as_bytes().to_owned()), + ); + + (root, base_path, person_path, server_path, config_path, vfs) + } + + #[test] + fn test_package_path_to_file_path() { + let (root, base_path, person_path, server_path, config_path, vfs) = prepare_vfs(); + + let files = package_path_to_file_path(base_path.as_path().to_str().unwrap(), vfs.clone()); + assert_eq!( + files, + vec![ + person_path.as_path().to_str().unwrap().to_string(), + server_path.as_path().to_str().unwrap().to_string() + ] + ); + + let files = package_path_to_file_path( + root.join("base").join("person").as_path().to_str().unwrap(), + vfs.clone(), + ); + assert_eq!( + files, + vec![person_path.as_path().to_str().unwrap().to_string()] + ); + + let files = + package_path_to_file_path(root.join("config").as_path().to_str().unwrap(), vfs.clone()); + assert_eq!( + files, + vec![config_path.as_path().to_str().unwrap().to_string()] + ); + } + + #[test] + fn test_select_symbol() { + let (root, _, person_path, server_path, _config_path, vfs) = prepare_vfs(); + let pkg_root = root.as_path().to_str().unwrap().to_string(); + + if let Some((name, range)) = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "Person.name".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ) { + assert_eq!(name, "name"); + assert_eq!( + range, + ( + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 2, + column: Some(4), + }, + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 2, + column: Some(8), + }, + ) + ); + } else { + assert!(false, "select symbol failed") + } + + if let Some((name, range)) = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "Name.first".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ) { + assert_eq!(name, "first"); + assert_eq!( + range, + ( + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 6, + column: Some(4), + }, + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 6, + column: Some(9), + }, + ) + ); + } else { + assert!(false, "select symbol failed") + } + + if let Some((name, range)) = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "Person".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ) { + assert_eq!(name, "Person"); + assert_eq!( + range, + ( + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 1, + column: Some(7), + }, + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 1, + column: Some(13), + }, + ) + ); + } else { + assert!(false, "select symbol failed") + } + + if let Some((name, range)) = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "a".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ) { + assert_eq!(name, "a"); + assert_eq!( + range, + ( + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 8, + column: Some(0), + }, + diagnostic::Position { + filename: person_path.as_path().to_str().unwrap().to_string(), + line: 8, + column: Some(1), + }, + ) + ); + } else { + assert!(false, "select symbol failed") + } + + if let Some((name, range)) = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "Server.name".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ) { + assert_eq!(name, "name"); + assert_eq!( + range, + ( + diagnostic::Position { + filename: server_path.as_path().to_str().unwrap().to_string(), + line: 2, + column: Some(4), + }, + diagnostic::Position { + filename: server_path.as_path().to_str().unwrap().to_string(), + line: 2, + column: Some(8), + }, + ) + ); + } else { + assert!(false, "select symbol failed") + } + } + + #[test] + fn test_select_symbol_failed() { + let (root, _, _, _, _, vfs) = prepare_vfs(); + let pkg_root = root.as_path().to_str().unwrap().to_string(); + let result = select_symbol( + &ast::SymbolSelectorSpec { + pkg_root: pkg_root.clone(), + pkgpath: "base".to_string(), + field_path: "name".to_string(), + }, + vfs.clone(), + VfsPath::new_virtual_path, + ); + assert!(result.is_none(), "should not find the target symbol") + } + + #[test] + fn test_rename() { + let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + root.push("src/test_data/rename_test/"); + + let mut main_path = root.clone(); + let mut base_path = root.clone(); + base_path.push("base/person.k"); + main_path.push("config.k"); + + let base_path = base_path.to_str().unwrap(); + let main_path = main_path.to_str().unwrap(); + + let vfs: Arc> = Arc::new(RwLock::new(Default::default())); + for path in vec![base_path, main_path] { + let content = fs::read_to_string(path).unwrap(); + vfs.write().set_file_contents( + VfsPath::new_virtual_path(path.to_string()), + Some(content.into_bytes()), + ); + } + + if let Ok(changes) = rename_symbol( + root.to_str().unwrap(), + vfs.clone(), + "base:Person", + "NewPerson".to_string(), + VfsPath::new_virtual_path, + ) { + assert_eq!(changes.len(), 2); + assert!(changes.contains_key(base_path)); + assert!(changes.contains_key(main_path)); + assert!(changes.get(base_path).unwrap().len() == 1); + assert!(changes.get(base_path).unwrap()[0].range.start == Position::new(0, 7)); + assert!(changes.get(main_path).unwrap().len() == 1); + assert!(changes.get(main_path).unwrap()[0].range.start == Position::new(2, 9)); + assert!(changes.get(main_path).unwrap()[0].new_text == "NewPerson".to_string()); + } else { + assert!(false, "rename failed") + } + + if let Ok(changes) = rename_symbol( + root.to_str().unwrap(), + vfs.clone(), + "base:Person.name", + "new_name".to_string(), + VfsPath::new_virtual_path, + ) { + assert_eq!(changes.len(), 2); + assert!(changes.contains_key(base_path)); + assert!(changes.contains_key(main_path)); + assert!(changes.get(base_path).unwrap().len() == 1); + assert!(changes.get(base_path).unwrap()[0].range.start == Position::new(1, 4)); + assert!(changes.get(main_path).unwrap().len() == 1); + assert!(changes.get(main_path).unwrap()[0].range.start == Position::new(4, 4)); + assert!(changes.get(main_path).unwrap()[0].new_text == "new_name".to_string()); + } else { + assert!(false, "rename failed") + } + } + + #[test] + fn test_apply_rename_changes() { + let path = "/mock_root/main.k".to_string(); + let mut source_codes = HashMap::new(); + source_codes.insert( + path.clone(), + r#"import .pkg.vars + +Bob = vars.Person { + name: "Bob" + age: 30 +}"# + .to_string(), + ); + + struct TestCase { + changes: HashMap>, + expected: String, + } + + let test_cases = vec![TestCase { + changes: HashMap::from([( + path.clone(), + vec![TextEdit { + range: Range { + start: Position { + line: 2, + character: 11, + }, + end: Position { + line: 2, + character: 17, + }, + }, + new_text: "Person2".to_string(), + }], + )]), + expected: "import .pkg.vars\n\nBob = vars.Person2 {\n name: \"Bob\"\n age: 30\n}" + .to_string(), + }]; + + for test_case in test_cases { + let result = apply_rename_changes(&test_case.changes, source_codes.clone()); + assert_eq!(result.unwrap().get(&path).unwrap(), &test_case.expected); + } + } + + #[test] + fn test_rename_symbol_on_file() { + let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + root.push("src/test_data/rename_test/"); + + let mut main_path = root.clone(); + let mut base_path = root.clone(); + base_path.push("base/person.k"); + main_path.push("config.k"); + let base_path_string = base_path.to_str().unwrap().to_string(); + let main_path_string = main_path.to_str().unwrap().to_string(); + + // before test, back up the old file content + for path in vec![base_path.clone(), main_path.clone()] { + let content = fs::read_to_string(path.clone()).unwrap(); + let backup_path = path.with_extension("bak"); + fs::write(backup_path.clone(), content).unwrap(); + } + + let result = rename_symbol_on_file( + root.to_str().unwrap(), + "base:Person", + &vec![base_path_string.clone(), main_path_string.clone()], + "NewPerson".to_string(), + ); + let expect_changed_paths: HashSet<_> = [base_path_string.clone(), main_path_string.clone()] + .iter() + .cloned() + .collect(); + let got_changed_paths: HashSet<_> = result.unwrap().iter().cloned().collect(); + assert_eq!(expect_changed_paths, got_changed_paths); + let base_new_content = fs::read_to_string(base_path.clone()).unwrap(); + let main_new_content = fs::read_to_string(main_path.clone()).unwrap(); + assert_eq!( + base_new_content, + r#"schema NewPerson: + name: Name + age: int + +schema Name: + first: str + +a = { + abc: "d" +} + +d = a.abc +e = a["abc"]"# + ); + assert_eq!(main_new_content, "import .base\n\na = base.NewPerson {\n age: 1,\n name: {\n first: \"aa\"\n }\n}"); + + // after test, restore the old file content + for path in vec![base_path.clone(), main_path.clone()] { + let backup_path = path.with_extension("bak"); + let content = fs::read_to_string(backup_path.clone()).unwrap(); + fs::write(path.clone(), content).unwrap(); + fs::remove_file(backup_path.clone()).unwrap(); + } + } + + #[test] + fn test_rename_symbol_on_code() { + let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + root.push("src/test_data/rename_test/"); + + let mut base_path = root.clone(); + let mut main_path = root.clone(); + + base_path.push("base/person.k"); + main_path.push("config.k"); + + let base_path_string = base_path.to_str().unwrap().to_string(); + let main_path_string = main_path.to_str().unwrap().to_string(); + + let base_source_code = r#"schema Person: + name: Name + age: int + +schema Name: + first: str + +a = { + abc: "d" +} + +d = a.abc +e = a["abc"]"#; + + let main_source_code = r#"import .base + +a = base.Person { + age: 1, + name: { + first: "aa" + } +}"#; + + let result: HashMap = rename_symbol_on_code( + root.to_str().unwrap(), + "base:Person", + hashmap! { + base_path_string.clone() => base_source_code.to_string(), + main_path_string.clone() => main_source_code.to_string(), + }, + "NewPerson".to_string(), + ) + .unwrap(); + + let base_new_content = result.get(base_path_string.clone().as_str()).unwrap(); + assert_eq!( + base_new_content, + r#"schema NewPerson: + name: Name + age: int + +schema Name: + first: str + +a = { + abc: "d" +} + +d = a.abc +e = a["abc"]"# + ); + + let main_new_content = result.get(main_path_string.clone().as_str()).unwrap(); + assert_eq!( + main_new_content, + r#"import .base + +a = base.NewPerson { + age: 1, + name: { + first: "aa" + } +}"# + ); + } +} diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index fd511c008..8ce458209 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -1,15 +1,24 @@ -use std::time::Instant; - -use anyhow::Ok; +use anyhow::anyhow; use crossbeam_channel::Sender; +use kclvm_config::modfile::KCL_FILE_SUFFIX; +use kclvm_sema::info::is_valid_kcl_name; +use lsp_types::{Location, SemanticTokensResult, TextEdit}; +use ra_ap_vfs::VfsPath; +use std::collections::HashMap; +use std::time::Instant; + use crate::{ completion::completion, + db::AnalysisDatabase, dispatcher::RequestDispatcher, document_symbol::document_symbol, - from_lsp::{file_path_from_url, kcl_pos}, - goto_def::goto_definition, - hover, + find_refs::find_refs, + formatting::format, + from_lsp::{self, file_path_from_url, kcl_pos}, + goto_def::goto_definition_with_gs, + hover, quick_fix, + semantic_token::semantic_tokens_full, state::{log_message, LanguageServerSnapshot, LanguageServerState, Task}, util::{parse_param_and_compile, Param}, }; @@ -41,118 +50,346 @@ impl LanguageServerState { Ok(()) })? .on::(handle_goto_definition)? + .on::(handle_reference)? .on::(handle_completion)? .on::(handle_hover)? .on::(handle_document_symbol)? + .on::(handle_code_action)? + .on::(handle_formatting)? + .on::(handle_range_formatting)? + .on::(handle_rename)? + .on::(handle_semantic_tokens_full)? .finish(); Ok(()) } } -/// Called when a `GotoDefinition` request was received. +impl LanguageServerSnapshot { + // defend against non-kcl files + pub(crate) fn verify_request_path(&self, path: &VfsPath, sender: &Sender) -> bool { + let res = self.vfs.read().file_id(path).is_some() + && self + .db + .read() + .get(&self.vfs.read().file_id(path).unwrap()) + .is_some(); + if !res { + let _ = log_message("Not a valid kcl path, request failed".to_string(), sender); + } + res + } + + pub(crate) fn get_db(&self, path: &VfsPath) -> anyhow::Result { + match self.vfs.read().file_id(path) { + Some(id) => match self.db.read().get(&id) { + Some(db) => Ok(db.clone()), + None => Err(anyhow::anyhow!(format!( + "Path {path} AnalysisDatabase not found" + ))), + }, + None => Err(anyhow::anyhow!(format!("Path {path} fileId not found"))), + } + } +} + +pub(crate) fn handle_semantic_tokens_full( + snapshot: LanguageServerSnapshot, + params: lsp_types::SemanticTokensParams, + sender: Sender, +) -> anyhow::Result> { + let file = file_path_from_url(¶ms.text_document.uri)?; + let path = from_lsp::abs_path(¶ms.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } + + match parse_param_and_compile( + Param { + file: file.clone(), + module_cache: snapshot.module_cache.clone(), + scope_cache: snapshot.scope_cache.clone(), + }, + Some(snapshot.vfs.clone()), + ) { + Ok((_, _, _, gs)) => { + let res = semantic_tokens_full(&file, &gs); + Ok(res) + } + Err(_) => Ok(None), + } +} + +pub(crate) fn handle_formatting( + _snapshot: LanguageServerSnapshot, + params: lsp_types::DocumentFormattingParams, + _sender: Sender, +) -> anyhow::Result>> { + let file = file_path_from_url(¶ms.text_document.uri)?; + let src = std::fs::read_to_string(file.clone())?; + format(file, src, None) +} + +pub(crate) fn handle_range_formatting( + snapshot: LanguageServerSnapshot, + params: lsp_types::DocumentRangeFormattingParams, + _sender: Sender, +) -> anyhow::Result>> { + let file = file_path_from_url(¶ms.text_document.uri)?; + let path = from_lsp::abs_path(¶ms.text_document.uri)?; + let vfs = &*snapshot.vfs.read(); + + let file_id = vfs + .file_id(&path.clone().into()) + .ok_or(anyhow::anyhow!("Already checked that the file_id exists!"))?; + + let text = String::from_utf8(vfs.file_contents(file_id).to_vec())?; + let range = from_lsp::text_range(&text, params.range); + if let Some(src) = text.get(range) { + format(file, src.to_owned(), Some(params.range)) + } else { + Ok(None) + } +} + +/// Called when a `textDocument/codeAction` request was received. +pub(crate) fn handle_code_action( + _snapshot: LanguageServerSnapshot, + params: lsp_types::CodeActionParams, + _sender: Sender, +) -> anyhow::Result> { + let mut code_actions: Vec = vec![]; + code_actions.extend(quick_fix::quick_fix( + ¶ms.text_document.uri, + ¶ms.context.diagnostics, + )); + Ok(Some(code_actions)) +} + +/// Called when a `textDocument/definition` request was received. pub(crate) fn handle_goto_definition( snapshot: LanguageServerSnapshot, params: lsp_types::GotoDefinitionParams, sender: Sender, ) -> anyhow::Result> { let file = file_path_from_url(¶ms.text_document_position_params.text_document.uri)?; - - let (program, prog_scope, _) = parse_param_and_compile( - Param { - file: file.to_string(), - }, - Some(snapshot.vfs), - )?; + let path = from_lsp::abs_path(¶ms.text_document_position_params.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } + let db = snapshot.get_db(&path.clone().into())?; let kcl_pos = kcl_pos(&file, params.text_document_position_params.position); - let res = goto_definition(&program, &kcl_pos, &prog_scope); + let res = goto_definition_with_gs(&db.prog, &kcl_pos, &db.gs); if res.is_none() { - log_message("Definition not found".to_string(), &sender)?; + log_message("Definition item not found".to_string(), &sender)?; } Ok(res) } -/// Called when a `Completion` request was received. +/// Called when a `textDocument/references` request was received +pub(crate) fn handle_reference( + snapshot: LanguageServerSnapshot, + params: lsp_types::ReferenceParams, + sender: Sender, +) -> anyhow::Result>> { + let include_declaration = params.context.include_declaration; + let file = file_path_from_url(¶ms.text_document_position.text_document.uri)?; + + let path = from_lsp::abs_path(¶ms.text_document_position.text_document.uri)?; + + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } + let db = snapshot.get_db(&path.clone().into())?; + let pos = kcl_pos(&file, params.text_document_position.position); + let log = |msg: String| log_message(msg, &sender); + let module_cache = snapshot.module_cache.clone(); + let scope_cache = snapshot.scope_cache.clone(); + match find_refs( + &db.prog, + &pos, + include_declaration, + snapshot.word_index_map.clone(), + Some(snapshot.vfs.clone()), + log, + &db.gs, + module_cache, + scope_cache, + ) { + core::result::Result::Ok(locations) => Ok(Some(locations)), + Err(msg) => { + log(format!("Find references failed: {msg}"))?; + Ok(None) + } + } +} + +/// Called when a `textDocument/completion` request was received. pub(crate) fn handle_completion( snapshot: LanguageServerSnapshot, params: lsp_types::CompletionParams, sender: Sender, ) -> anyhow::Result> { let file = file_path_from_url(¶ms.text_document_position.text_document.uri)?; + let path = from_lsp::abs_path(¶ms.text_document_position.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } - let (program, prog_scope, _) = parse_param_and_compile( - Param { - file: file.to_string(), - }, - Some(snapshot.vfs), - )?; let kcl_pos = kcl_pos(&file, params.text_document_position.position); - log_message( - format!( - "handle_completion {:?}", - params.text_document_position.position - ), - &sender, - )?; let completion_trigger_character = params .context .and_then(|ctx| ctx.trigger_character) .and_then(|s| s.chars().next()); + let (prog, gs) = match completion_trigger_character { + // Some trigger characters need to re-compile + Some(ch) => match ch { + '=' | ':' => { + match parse_param_and_compile( + Param { + file: file.clone(), + module_cache: snapshot.module_cache.clone(), + scope_cache: snapshot.scope_cache.clone(), + }, + Some(snapshot.vfs.clone()), + ) { + Ok((prog, _, _, gs)) => (prog, gs), + Err(_) => return Ok(None), + } + } + _ => { + let db = snapshot.get_db(&path.clone().into())?; + (db.prog, db.gs) + } + }, - let res = completion( - completion_trigger_character, - &program, - &kcl_pos, - &prog_scope, - ); + None => { + let db = snapshot.get_db(&path.clone().into())?; + (db.prog, db.gs) + } + }; + + let res = completion(completion_trigger_character, &prog, &kcl_pos, &gs); + + if res.is_none() { + log_message("Completion item not found".to_string(), &sender)?; + } Ok(res) } -/// Called when a `Completion` request was received. +/// Called when a `textDocument/hover` request was received. pub(crate) fn handle_hover( snapshot: LanguageServerSnapshot, params: lsp_types::HoverParams, sender: Sender, ) -> anyhow::Result> { let file = file_path_from_url(¶ms.text_document_position_params.text_document.uri)?; - - let (program, prog_scope, _) = parse_param_and_compile( - Param { - file: file.to_string(), - }, - Some(snapshot.vfs), - )?; + let path = from_lsp::abs_path(¶ms.text_document_position_params.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } + let db = snapshot.get_db(&path.clone().into())?; let kcl_pos = kcl_pos(&file, params.text_document_position_params.position); - log_message( - format!( - "handle_hover {:?}", - params.text_document_position_params.position - ), - &sender, - )?; - - let res = hover::hover(&program, &kcl_pos, &prog_scope); + let res = hover::hover(&db.prog, &kcl_pos, &db.gs); + if res.is_none() { + log_message("Hover definition not found".to_string(), &sender)?; + } Ok(res) } -/// Called when a `GotoDefinition` request was received. +/// Called when a `textDocument/documentSymbol` request was received. pub(crate) fn handle_document_symbol( snapshot: LanguageServerSnapshot, params: lsp_types::DocumentSymbolParams, sender: Sender, ) -> anyhow::Result> { let file = file_path_from_url(¶ms.text_document.uri)?; + let path = from_lsp::abs_path(¶ms.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) + && !file.ends_with(KCL_FILE_SUFFIX) + { + return Ok(None); + } - let (program, prog_scope, _) = parse_param_and_compile( + match parse_param_and_compile( Param { - file: file.to_string(), + file: file.clone(), + module_cache: snapshot.module_cache.clone(), + scope_cache: snapshot.scope_cache.clone(), }, - Some(snapshot.vfs), - )?; + Some(snapshot.vfs.clone()), + ) { + Ok((_, _, _, gs)) => { + let res = document_symbol(&file, &gs); + if res.is_none() { + log_message(format!("File {file} Document symbol not found"), &sender)?; + } + Ok(res) + } + Err(_) => Ok(None), + } +} - let res = document_symbol(&file, &program, &prog_scope); - if res.is_none() { - log_message("Document symbol not found".to_string(), &sender)?; +/// Called when a `textDocument/rename` request was received. +pub(crate) fn handle_rename( + snapshot: LanguageServerSnapshot, + params: lsp_types::RenameParams, + sender: Sender, +) -> anyhow::Result> { + // 1. check the new name validity + let new_name = params.new_name; + if !is_valid_kcl_name(new_name.as_str()) { + return Err(anyhow!("Can not rename to: {new_name}, invalid name")); + } + + // 2. find all the references of the symbol + let file = file_path_from_url(¶ms.text_document_position.text_document.uri)?; + let path = from_lsp::abs_path(¶ms.text_document_position.text_document.uri)?; + if !snapshot.verify_request_path(&path.clone().into(), &sender) { + return Ok(None); + } + let db = snapshot.get_db(&path.clone().into())?; + let kcl_pos = kcl_pos(&file, params.text_document_position.position); + let log = |msg: String| log_message(msg, &sender); + let references = find_refs( + &db.prog, + &kcl_pos, + true, + snapshot.word_index_map.clone(), + Some(snapshot.vfs.clone()), + log, + &db.gs, + snapshot.module_cache.clone(), + snapshot.scope_cache.clone(), + ); + match references { + Result::Ok(locations) => { + if locations.is_empty() { + let _ = log("Symbol not found".to_string()); + anyhow::Ok(None) + } else { + // 3. return the workspaceEdit to rename all the references with the new name + let mut workspace_edit = lsp_types::WorkspaceEdit::default(); + + let changes = locations.into_iter().fold( + HashMap::new(), + |mut map: HashMap>, location| { + let uri = location.uri; + map.entry(uri.clone()).or_default().push(TextEdit { + range: location.range, + new_text: new_name.clone(), + }); + map + }, + ); + workspace_edit.changes = Some(changes); + anyhow::Ok(Some(workspace_edit)) + } + } + Err(msg) => { + let err_msg = format!("Can not rename symbol: {msg}"); + log(err_msg.clone())?; + Err(anyhow!(err_msg)) + } } - Ok(res) } diff --git a/kclvm/tools/src/LSP/src/semantic_token.rs b/kclvm/tools/src/LSP/src/semantic_token.rs new file mode 100644 index 000000000..58e286e41 --- /dev/null +++ b/kclvm/tools/src/LSP/src/semantic_token.rs @@ -0,0 +1,181 @@ +use std::vec; + +use kclvm_error::Position; +use kclvm_sema::core::{ + global_state::GlobalState, + symbol::{KCLSymbol, SymbolKind}, +}; +use lsp_types::{SemanticToken, SemanticTokenType, SemanticTokens, SemanticTokensResult}; + +pub const LEGEND_TYPE: &[SemanticTokenType] = &[ + SemanticTokenType::VARIABLE, + SemanticTokenType::STRUCT, + SemanticTokenType::PROPERTY, + SemanticTokenType::NAMESPACE, + SemanticTokenType::TYPE, + SemanticTokenType::MACRO, + SemanticTokenType::COMMENT, + SemanticTokenType::PARAMETER, +]; + +pub(crate) struct KCLSemanticToken { + pub start: Position, + pub kind: u32, + pub length: u32, +} + +pub(crate) fn semantic_tokens_full(file: &str, gs: &GlobalState) -> Option { + let mut kcl_tokens: Vec = vec![]; + let sema_db = gs.get_sema_db(); + if let Some(file_sema) = sema_db.get_file_sema(&file.to_string()) { + let symbols = file_sema.get_symbols(); + for symbol_ref in symbols { + if let Some(symbol) = gs.get_symbols().get_symbol(*symbol_ref) { + let (start, end) = symbol.get_range(); + match get_kind(symbol_ref.get_kind(), symbol, gs) { + Some(kind) => { + kcl_tokens.push(KCLSemanticToken { + start: start.clone(), + kind, + length: if start.line == end.line { + (end.column.unwrap_or(0) - start.column.unwrap_or(0)) as u32 + } else { + symbol.get_name().len() as u32 + }, + }); + } + None => continue, + } + } + } + } + + Some(SemanticTokensResult::Tokens(SemanticTokens { + result_id: None, + data: kcl_semantic_tokens_to_semantic_tokens(&mut kcl_tokens), + })) +} + +pub(crate) fn get_kind(ty: SymbolKind, symbol: &KCLSymbol, gs: &GlobalState) -> Option { + match ty { + SymbolKind::Schema => Some(type_index(SemanticTokenType::STRUCT)), + SymbolKind::Attribute => Some(type_index(SemanticTokenType::PROPERTY)), + SymbolKind::Package => Some(type_index(SemanticTokenType::NAMESPACE)), + SymbolKind::TypeAlias => Some(type_index(SemanticTokenType::TYPE)), + SymbolKind::Value => Some(type_index(SemanticTokenType::VARIABLE)), + SymbolKind::Rule => Some(type_index(SemanticTokenType::MACRO)), + SymbolKind::Unresolved => match &symbol.get_definition() { + Some(def_ref) => match gs.get_symbols().get_symbol(*def_ref) { + Some(symbol) => get_kind(def_ref.get_kind(), symbol, gs), + None => Some(type_index(SemanticTokenType::VARIABLE)), + }, + None => Some(type_index(SemanticTokenType::VARIABLE)), + }, + SymbolKind::Expression => None, + SymbolKind::Comment => None, + SymbolKind::Decorator => Some(type_index(SemanticTokenType::PARAMETER)), + } +} + +pub(crate) fn type_index(ty: SemanticTokenType) -> u32 { + LEGEND_TYPE.iter().position(|it| *it == ty).unwrap() as u32 +} + +pub(crate) fn kcl_semantic_tokens_to_semantic_tokens( + tokens: &mut Vec, +) -> Vec { + tokens.sort_by(|a, b| { + if a.start.line == b.start.line { + a.start + .column + .unwrap_or(0) + .cmp(&b.start.column.unwrap_or(0)) + } else { + a.start.line.cmp(&b.start.line) + } + }); + let mut pre_line = 0; + let mut pre_start = 0; + + let semantic_tokens: Vec = tokens + .iter() + .map(|obj| { + // ref: https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71 + // A file can contain many tokens, perhaps even hundreds of thousands of tokens. Therefore, to improve + // the memory consumption around describing semantic tokens, we have decided to avoid allocating an object + // for each token and we represent tokens from a file as an array of integers. Furthermore, the position + // of each token is expressed relative to the token before it because most tokens remain stable relative to + // each other when edits are made in a file. + let line = obj.start.line - 1; + let start = obj.start.column.unwrap_or(0); + + let delta_line: u32 = (line - pre_line) as u32; + let delta_start: u32 = (if delta_line == 0 { + start - pre_start + } else { + start + }) as u32; + let length = obj.length; + let ret = SemanticToken { + delta_line, + delta_start, + length, + token_type: obj.kind, + token_modifiers_bitset: 0, + }; + pre_line = line; + pre_start = start; + ret + }) + .collect(); + semantic_tokens +} + +#[cfg(test)] +mod tests { + use crate::tests::compile_test_file; + use proc_macro_crate::bench_test; + + use super::semantic_tokens_full; + + #[test] + #[bench_test] + fn semantic_tokens_full_test() { + let (file, _, _, _, gs) = compile_test_file("src/test_data/sema_token.k"); + let expected = [ + (0, 15, 1, 3), // m + (1, 5, 3, 4), // num + (1, 7, 7, 1), // Persons + (1, 4, 4, 2), // name + (2, 0, 2, 0), // p5 + (0, 4, 7, 1), // Persons + (0, 10, 7, 1), // Persons + (1, 4, 4, 2), // name + (2, 0, 1, 0), // n + (0, 3, 3, 4), // num + ]; + let res = semantic_tokens_full(&file, &gs); + if let Some(tokens) = res { + match &tokens { + lsp_types::SemanticTokensResult::Tokens(tokens) => { + let get: Vec<(u32, u32, u32, u32)> = tokens + .data + .iter() + .map(|token| { + ( + token.delta_line, + token.delta_start, + token.length, + token.token_type, + ) + }) + .collect(); + assert_eq!(get, expected); + } + lsp_types::SemanticTokensResult::Partial(_) => { + panic!("test failed") + } + } + } + } +} diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index b824707fa..daa5636dd 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -1,14 +1,24 @@ +use crate::analysis::Analysis; use crate::config::Config; +use crate::db::AnalysisDatabase; +use crate::from_lsp::file_path_from_url; use crate::to_lsp::{kcl_diag_to_lsp_diags, url}; -use crate::util::{get_file_name, parse_param_and_compile, to_json, Param}; +use crate::util::{build_word_index, get_file_name, parse_param_and_compile, to_json, Param}; +use anyhow::Result; use crossbeam_channel::{select, unbounded, Receiver, Sender}; +use indexmap::IndexSet; +use kclvm_parser::KCLModuleCache; +use kclvm_sema::resolver::scope::CachedScope; use lsp_server::{ReqQueue, Response}; +use lsp_types::Url; use lsp_types::{ notification::{Notification, PublishDiagnostics}, - Diagnostic, PublishDiagnosticsParams, + Diagnostic, InitializeParams, Location, PublishDiagnosticsParams, }; use parking_lot::RwLock; -use ra_ap_vfs::Vfs; +use ra_ap_vfs::{FileId, Vfs}; +use std::collections::HashMap; +use std::sync::Mutex; use std::{sync::Arc, time::Instant}; pub(crate) type RequestHandler = fn(&mut LanguageServerState, lsp_server::Response); @@ -28,6 +38,11 @@ pub(crate) enum Event { Lsp(lsp_server::Message), } +pub(crate) struct Handle { + pub(crate) handle: H, + pub(crate) _receiver: C, +} + /// State for the language server pub(crate) struct LanguageServerState { /// Channel to send language server messages to the client @@ -53,6 +68,23 @@ pub(crate) struct LanguageServerState { /// True if the client requested that we shut down pub shutdown_requested: bool, + + /// Holds the state of the analysis process + pub analysis: Analysis, + + /// Documents that are currently kept in memory from the client + pub opened_files: IndexSet, + + /// The VFS loader + pub loader: Handle, Receiver>, + + /// The word index map + pub word_index_map: Arc>>>>, + + /// KCL parse cache + pub module_cache: Option, + /// KCL resolver cache + pub scope_cache: Option>>, } /// A snapshot of the state of the language server @@ -60,22 +92,60 @@ pub(crate) struct LanguageServerState { pub(crate) struct LanguageServerSnapshot { /// The virtual filesystem that holds all the file contents pub vfs: Arc>, + /// Holds the state of the analysis process + pub db: Arc>>, + /// Documents that are currently kept in memory from the client + pub opened_files: IndexSet, + /// The word index map + pub word_index_map: Arc>>>>, + /// KCL parse cache + pub module_cache: Option, + /// KCL resolver cache + pub scope_cache: Option>>, } #[allow(unused)] impl LanguageServerState { - pub fn new(sender: Sender, config: Config) -> Self { + pub fn new( + sender: Sender, + config: Config, + initialize_params: InitializeParams, + ) -> Self { let (task_sender, task_receiver) = unbounded::(); - LanguageServerState { + + let loader = { + let (sender, _receiver) = unbounded::(); + let handle: ra_ap_vfs_notify::NotifyHandle = + ra_ap_vfs::loader::Handle::spawn(Box::new(move |msg| sender.send(msg).unwrap())); + let handle = Box::new(handle) as Box; + Handle { handle, _receiver } + }; + + let state = LanguageServerState { sender, request_queue: ReqQueue::default(), _config: config, vfs: Arc::new(RwLock::new(Default::default())), thread_pool: threadpool::ThreadPool::default(), - task_sender, + task_sender: task_sender.clone(), task_receiver, shutdown_requested: false, - } + analysis: Analysis::default(), + opened_files: IndexSet::new(), + word_index_map: Arc::new(RwLock::new(HashMap::new())), + loader, + module_cache: Some(KCLModuleCache::default()), + scope_cache: Some(Arc::new(Mutex::new(CachedScope::default()))), + }; + + let word_index_map = state.word_index_map.clone(); + state.thread_pool.execute(move || { + if let Err(err) = build_word_index_map(word_index_map, initialize_params, true) { + log_message(err.to_string(), &task_sender); + } + }); + + state } /// Blocks until a new event is received from one of the many channels the language server @@ -106,26 +176,18 @@ impl LanguageServerState { // 1. Process the incoming event match event { Event::Task(task) => self.handle_task(task)?, - Event::Lsp(msg) => match msg { - lsp_server::Message::Request(req) => self.on_request(req, start_time)?, - lsp_server::Message::Notification(not) => self.on_notification(not)?, - // lsp_server::Message::Response(resp) => self.complete_request(resp), - _ => {} - }, + Event::Lsp(msg) => { + match msg { + lsp_server::Message::Request(req) => self.on_request(req, start_time)?, + lsp_server::Message::Notification(not) => self.on_notification(not)?, + // lsp_server::Message::Response(resp) => self.complete_request(resp), + _ => {} + } + } }; // 2. Process changes - // Todo: recompile and store result in db. Handle request and push diagnostis with db - // let state_changed: bool = self.process_vfs_changes(); - - // 3. Handle Diagnostics - let mut snapshot = self.snapshot(); - let task_sender = self.task_sender.clone(); - // Spawn the diagnostics in the threadpool - self.thread_pool.execute(move || { - let _result = handle_diagnostics(snapshot, task_sender); - }); - + self.process_vfs_changes(); Ok(()) } @@ -141,12 +203,78 @@ impl LanguageServerState { if changed_files.is_empty() { return false; } - self.log_message("process_vfs_changes".to_string()); // Construct an AnalysisChange to apply to the analysis - let vfs = self.vfs.read(); for file in changed_files { - // todo: recompile and record context + let vfs = self.vfs.read(); + let start = Instant::now(); + let filename = get_file_name(vfs, file.file_id); + match filename { + Ok(filename) => { + self.thread_pool.execute({ + let mut snapshot = self.snapshot(); + let sender = self.task_sender.clone(); + let module_cache = self.module_cache.clone(); + let scope_cache = self.scope_cache.clone(); + move || match url(&snapshot, file.file_id) { + Ok(uri) => { + match parse_param_and_compile( + Param { + file: filename.clone(), + module_cache, + scope_cache, + }, + Some(snapshot.vfs), + ) { + Ok((prog, _, diags, gs)) => { + let mut db = snapshot.db.write(); + db.insert( + file.file_id, + AnalysisDatabase { + prog, + diags: diags.clone(), + gs, + }, + ); + + let diagnostics = diags + .iter() + .flat_map(|diag| { + kcl_diag_to_lsp_diags(diag, filename.as_str()) + }) + .collect::>(); + sender.send(Task::Notify(lsp_server::Notification { + method: PublishDiagnostics::METHOD.to_owned(), + params: to_json(PublishDiagnosticsParams { + uri, + diagnostics, + version: None, + }) + .unwrap(), + })); + } + Err(err) => { + log_message( + format!("compile failed: {:?}", err.to_string()), + &sender, + ); + } + } + } + Err(_) => { + log_message( + format!("Interal bug: not a valid file:{:?}", filename), + &sender, + ); + } + } + }); + } + Err(_) => { + self.log_message(format!("{:?} not found", file.file_id)); + continue; + } + } } true } @@ -196,6 +324,11 @@ impl LanguageServerState { pub fn snapshot(&self) -> LanguageServerSnapshot { LanguageServerSnapshot { vfs: self.vfs.clone(), + db: self.analysis.db.clone(), + opened_files: self.opened_files.clone(), + word_index_map: self.word_index_map.clone(), + module_cache: self.module_cache.clone(), + scope_cache: self.scope_cache.clone(), } } @@ -209,46 +342,6 @@ impl LanguageServerState { } } -// todo: `handle_diagnostics` only gets diag from db and converts them to lsp diagnostics. -fn handle_diagnostics( - snapshot: LanguageServerSnapshot, - sender: Sender, -) -> anyhow::Result<()> { - let changed_files = { - let mut vfs = snapshot.vfs.write(); - vfs.take_changes() - }; - for file in changed_files { - let (filename, uri) = { - let vfs = snapshot.vfs.read(); - let filename = get_file_name(vfs, file.file_id)?; - let uri = url(&snapshot, file.file_id)?; - (filename, uri) - }; - let (_, _, diags) = parse_param_and_compile( - Param { - file: filename.clone(), - }, - Some(snapshot.vfs.clone()), - ) - .unwrap(); - - let diagnostics = diags - .iter() - .flat_map(|diag| kcl_diag_to_lsp_diags(diag, filename.as_str())) - .collect::>(); - sender.send(Task::Notify(lsp_server::Notification { - method: PublishDiagnostics::METHOD.to_owned(), - params: to_json(PublishDiagnosticsParams { - uri, - diagnostics, - version: None, - })?, - }))?; - } - Ok(()) -} - pub(crate) fn log_message(message: String, sender: &Sender) -> anyhow::Result<()> { let typ = lsp_types::MessageType::INFO; sender.send(Task::Notify(lsp_server::Notification::new( @@ -257,3 +350,24 @@ pub(crate) fn log_message(message: String, sender: &Sender) -> anyhow::Res )))?; Ok(()) } + +fn build_word_index_map( + word_index_map: Arc>>>>, + initialize_params: InitializeParams, + prune: bool, +) -> Result<()> { + if let Some(workspace_folders) = initialize_params.workspace_folders { + for folder in workspace_folders { + let path = file_path_from_url(&folder.uri)?; + if let Ok(word_index) = build_word_index(path.to_string(), prune) { + word_index_map.write().insert(folder.uri, word_index); + } + } + } else if let Some(root_uri) = initialize_params.root_uri { + let path = file_path_from_url(&root_uri)?; + if let Ok(word_index) = build_word_index(path.to_string(), prune) { + word_index_map.write().insert(root_uri, word_index); + } + } + Ok(()) +} diff --git a/kclvm/tools/src/LSP/src/test_data/compile_unit/a.k b/kclvm/tools/src/LSP/src/test_data/compile_unit/a.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/compile_unit/b.k b/kclvm/tools/src/LSP/src/test_data/compile_unit/b.k new file mode 100644 index 000000000..d25d49e0f --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/compile_unit/b.k @@ -0,0 +1 @@ +a = 1 \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/compile_unit/kcl.yaml b/kclvm/tools/src/LSP/src/test_data/compile_unit/kcl.yaml new file mode 100644 index 000000000..12f641005 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/compile_unit/kcl.yaml @@ -0,0 +1,4 @@ +kcl_cli_configs: + files: + - main.k + - a.k \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/compile_unit/main.k b/kclvm/tools/src/LSP/src/test_data/compile_unit/main.k new file mode 100644 index 000000000..93d88b96d --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/compile_unit/main.k @@ -0,0 +1,3 @@ +import .b + +_b = b.a diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k new file mode 100644 index 000000000..dbf87d567 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k @@ -0,0 +1,27 @@ +import .pkg +import .pkg.subpkg as sub + +schema Person2: + a: bool + b: "abc" | "def" + c: [int] + d: 1 + e: True + f: {str:str} + g: sub.Person1 + +p: Person2{ + a # complete `True` and `False` + + b # complete `"abc"` and `"def"` + + c # complete `[]` + + d # complete `1` + + e # complete `True` + + f # complete `{}` + + g # complete `subpkg.Person1{}` +} diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/file1.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/file2.k b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/file2.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/subpkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/subpkg/file1.k new file mode 100644 index 000000000..3ab0802b2 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/pkg/subpkg/file1.k @@ -0,0 +1,3 @@ +schema Person1: + name: str + age: int \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/check/check.k b/kclvm/tools/src/LSP/src/test_data/completion_test/check/check.k new file mode 100644 index 000000000..1cdaab92d --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/check/check.k @@ -0,0 +1,5 @@ +schema Person: + name: str + + check: + \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k index 7c0150c4f..18eacc29e 100644 --- a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/completion.k @@ -16,6 +16,15 @@ p2 = p.name. # complete builtin (str) function p3 = subpkg. # complete user module definition import math -math. # complete user module definition +math. # complete system module definition "a". + +p4 = Person{ + +} + +schema P: + a: int = 1 + +aaaa = P{}. diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k new file mode 100644 index 000000000..9b694fdf4 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k @@ -0,0 +1,7 @@ +a = "aaa" +"aaa" +a +# a + +join_str = "hello world ${}" +join_recover_str = "hello world ${" \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/missing_expr/missing_expr.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/missing_expr/missing_expr.k new file mode 100644 index 000000000..baebba0f5 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/missing_expr/missing_expr.k @@ -0,0 +1,10 @@ +schema ResourceRequirement: + cpu?: str + memory?: str + +schema ResourceRequirements: + limits?: ResourceRequirement + requests?: ResourceRequirement + + check: + limits? diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/schema_ty_attr/schema_ty_attr.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/schema_ty_attr/schema_ty_attr.k new file mode 100644 index 000000000..696ab652f --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/schema_ty_attr/schema_ty_attr.k @@ -0,0 +1,13 @@ +schema Name: + name: str + +schema Person: + name: Name + +p = Person{ + name: Name{ + name: "a" + } +} + +p. \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/import/builtin_pkg.k b/kclvm/tools/src/LSP/src/test_data/completion_test/import/builtin_pkg.k new file mode 100644 index 000000000..e49b15106 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/import/builtin_pkg.k @@ -0,0 +1 @@ +import \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/kcl.mod b/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/kcl.mod new file mode 100644 index 000000000..b7ca134eb --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/kcl.mod @@ -0,0 +1,4 @@ +[package] + +[dependencies] +k8s = "1.28" diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/main.k b/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/main.k new file mode 100644 index 000000000..8becefd02 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/import/external/main.k @@ -0,0 +1 @@ +import k8s \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/newline/docstring_newline.k b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/docstring_newline.k new file mode 100644 index 000000000..d4bbd0ba2 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/docstring_newline.k @@ -0,0 +1,6 @@ +schema Server: + """ + """ + name: str + workloadType: "Deployment" | "StatefulSet" + replica: int = 1 diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline.k b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline.k new file mode 100644 index 000000000..263155647 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/newline/newline.k @@ -0,0 +1,9 @@ +schema Base: + a: int + +schema Person[b: int](Base): + c: int + +p1= Person(b){ + +} diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema.k b/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema.k new file mode 100644 index 000000000..8a9cc7269 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema.k @@ -0,0 +1,20 @@ +schema Base: + a: int + +schema Person[b: int](Base): + c: int + +p = + +schema Name: + name: str + +schema Config: + names: [Name] + names1: {str: Name} + names2: str | Name + +Config{ + names: [{ }] + names1: {"a": { }} +} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema_pos/schema_pos.k b/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema_pos/schema_pos.k new file mode 100644 index 000000000..170ab9cae --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/schema/schema_pos/schema_pos.k @@ -0,0 +1,6 @@ +schema Params: + min: int + max: int + + check: + min <= diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/completion.k b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/completion.k new file mode 100644 index 000000000..1bac86b60 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/completion.k @@ -0,0 +1,30 @@ +import .pkg # complete import path +import .pkg.subpkg +schema Person: + name: str + age: int + +p = Person { + name: "alice" + age: 1 +} + +p1 = p # complete schema attr + +p2 = p.name # complete builtin (str) function + +p3 = subpkg # complete user module definition + +import math +math # complete system module definition + +"a" + +p4 = Person{ + +} + +schema P: + a: int = 1 + +aaaa = P{} diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/file1.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/file2.k b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/file2.k new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/subpkg/file1.k b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/subpkg/file1.k new file mode 100644 index 000000000..3ab0802b2 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/without_dot/pkg/subpkg/file1.k @@ -0,0 +1,3 @@ +schema Person1: + name: str + age: int \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/diagnostics.k b/kclvm/tools/src/LSP/src/test_data/diagnostics.k index e9e013c8f..f24dac378 100644 --- a/kclvm/tools/src/LSP/src/test_data/diagnostics.k +++ b/kclvm/tools/src/LSP/src/test_data/diagnostics.k @@ -3,4 +3,9 @@ a = b: str = 1 c: Person = Person { age: 1 -} \ No newline at end of file +} + +d = 1 +d = 2 +number = 2 +count = nu \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/find_refs_test/main.k b/kclvm/tools/src/LSP/src/test_data/find_refs_test/main.k new file mode 100644 index 000000000..496868958 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/find_refs_test/main.k @@ -0,0 +1,15 @@ +a = "demo" +b = a +c = a + +schema Name: + name: str + +schema Person: + n: Name + +p2 = Person { + n: Name{ + name: a + } +} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/format/format_range.k b/kclvm/tools/src/LSP/src/test_data/format/format_range.k new file mode 100644 index 000000000..b80849aac --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/format/format_range.k @@ -0,0 +1,12 @@ + +a=1 + + +b= 2 + + +c =3 + + + +d = 4 \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_def.k b/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_def.k index 58f3943f0..aaa5ba56a 100644 --- a/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_def.k +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_test/goto_def.k @@ -12,4 +12,86 @@ schema Person3: p1: pkg.Person p2: [pkg.Person] p3: {str: pkg.Person} - p4: pkg.Person | pkg.Person1 \ No newline at end of file + p4: pkg.Person | pkg.Person1 + + +schema Name: + name: str + +schema Person: + n: Name + +p2 = Person { + n: Name{ + name: pkg.m.name + } +} + +s = p2.n.name + +a: int = 1 + +schema Reviewer: + teams?: [int] + users?: [int] + +reviewers: [Reviewer] = [Reviewer {teams: [1]}] + +schema Fib: + n1 = n - 1 + n2 = n1 - 1 + n: int + value: int + + if n <= 1: + value = 1 + elif n == 2: + value = 1 + else: + value = Fib {n = n1}.value + Fib {n = n2}.value +fib8 = Fib {n = 8}.value + +schema_map: {str: Person} = { + person: p2 + person1: p2 +} + +p3 = schema_map.person.n.name + +params = option("params") +toMatch = params.toMatch +toAdd = params.toAdd +items = [item | { + # If all annotations are matched, patch more annotations + if all key, value in toMatch { + item.metadata.annotations[key] == value + }: + metadata.annotations: toAdd +} for item in option("items")] + + +capabilities = option("params").capabilities or ["SETUID", "SETFCAP"] +items1 = [item | { + if item.kind == "Pod": + spec.containers: [{ + "securityContext": {"capabilities": {"add" += [cc] if cc not in (container?.securityContext?.capabilities?.drop or []) else [] for cc in capabilities}} + } for container in item.spec.containers] +} for item in option("items")] + +p4 = Person { + n.name: "a" +} + +func = lambda x: int, y: int -> int { + x + y +} + +b = True +command: [str] = [ + if b: + "a" +] + +f = lambda a: [str], b: [str], c: [str] -> [str] { + c + a + b +} diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_test/kcl.mod b/kclvm/tools/src/LSP/src/test_data/goto_def_test/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_test/pkg/schema_def.k b/kclvm/tools/src/LSP/src/test_data/goto_def_test/pkg/schema_def.k index cf10ad080..13e310f76 100644 --- a/kclvm/tools/src/LSP/src/test_data/goto_def_test/pkg/schema_def.k +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_test/pkg/schema_def.k @@ -4,3 +4,7 @@ schema Person: """ name: str age: int + +m : {str: str} = { + name: "a" +} diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/kcl.mod b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/kcl.mod new file mode 100644 index 000000000..2f4e3935d --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "dep-with-line" +edition = "0.0.1" +version = "0.0.1" + diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/kcl.mod.lock b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/kcl.mod.lock new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/main.k b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/main.k new file mode 100644 index 000000000..0df3165c8 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/dep-with-line/main.k @@ -0,0 +1 @@ +The_first_kcl_program = 'Hello World aa!' \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod new file mode 100644 index 000000000..076c66f4d --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod @@ -0,0 +1,7 @@ +[package] +name = "b" +edition = "0.0.1" +version = "0.0.1" + +[dependencies] +dep-with-line = { path = "../dep-with-line" } diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod.lock b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod.lock new file mode 100644 index 000000000..9c32b8db3 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/kcl.mod.lock @@ -0,0 +1,6 @@ +[dependencies] + [dependencies.dep-with-line] + name = "dep-with-line" + full_name = "dep-with-line_" + sum = "O2Z1djaB1lC38kNfhwUUYAlqGKE7seUqqys3DPcJfEw=" + path = "../dep-with-line" diff --git a/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/main.k b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/main.k new file mode 100644 index 000000000..e78a5fba4 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/goto_def_with_line_test/main_pkg/main.k @@ -0,0 +1,3 @@ +import dep_with_line as dwl + +The_first_kcl_program = dwl.The_first_kcl_program \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/goto_import_def_test/kcl.mod b/kclvm/tools/src/LSP/src/test_data/goto_import_def_test/kcl.mod index e660e645f..7afba4cdb 100644 --- a/kclvm/tools/src/LSP/src/test_data/goto_import_def_test/kcl.mod +++ b/kclvm/tools/src/LSP/src/test_data/goto_import_def_test/kcl.mod @@ -4,4 +4,4 @@ edition = "0.0.1" version = "0.0.4" [dependencies] -konfig = { git = "https://github.com/awesome-kusion/konfig.git", tag = "v0.0.1" } \ No newline at end of file +konfig = { git = "https://github.com/awesome-kusion/konfig.git", tag = "v0.0.1" } diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/assign_in_lambda.k b/kclvm/tools/src/LSP/src/test_data/hover_test/assign_in_lambda.k new file mode 100644 index 000000000..cd8ca643d --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/assign_in_lambda.k @@ -0,0 +1,6 @@ +lambda { + containers = [] + if True: + containers = [] + images: [str] = [c.image for c in containers] +} diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/decorator.k b/kclvm/tools/src/LSP/src/test_data/hover_test/decorator.k new file mode 100644 index 000000000..90df4d87e --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/decorator.k @@ -0,0 +1,5 @@ +@deprecated() +schema ObsoleteSchema: + @deprecated(version="1.16", reason="use firstName and lastName instead", strict=True) + attr: str + diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/fib.k b/kclvm/tools/src/LSP/src/test_data/hover_test/fib.k new file mode 100644 index 000000000..96926c055 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/fib.k @@ -0,0 +1,14 @@ +schema Fib: + n1 = n - 1 + n2 = n1 - 1 + n: int + value: int + + if n <= 1: + value = 1 + elif n == 2: + value = 1 + else: + value = Fib {n = n1}.value + Fib {n = n2}.value + +fib8 = Fib {n = 8}.value diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k b/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k new file mode 100644 index 000000000..d4ed155e5 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k @@ -0,0 +1,43 @@ +schema Person: + """ + hover doc test + + Attributes + ---------- + name : str, default is False, required + name doc test + age : int, default is False, optional + age doc test + + """ + name: str + age?: int + +p = Person{ + name: "Alice" + age: 1 +} + +import base64 +abdc = base64.encode("1") +abcd = "a".count() + +print(1) + +a = "".capitalize() +b = a.capitalize() + +schema Deployment: + spec: DeploymentSpec + +schema DeploymentSpec: + stratege: str + replicas?: int + +d = Deployment{ + spec: DeploymentSpec { + if True: + replicas = 1 + stratege: "a" + } +} diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/import_pkg.k b/kclvm/tools/src/LSP/src/test_data/hover_test/import_pkg.k new file mode 100644 index 000000000..a972f027f --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/import_pkg.k @@ -0,0 +1,3 @@ +import .fib + +fib.Fib{} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/ty_in_lambda.k b/kclvm/tools/src/LSP/src/test_data/hover_test/ty_in_lambda.k new file mode 100644 index 000000000..4b9a1929c --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/ty_in_lambda.k @@ -0,0 +1,9 @@ +_b = True +a = lambda item: {str:}, c: {str:} -> {str:str} { + result = {"aaa": "bbb"} + if _b : + result = {} + result +} + +result = {"ccc": "ddd"} diff --git a/kclvm/tools/src/LSP/src/test_data/quick_fix.k b/kclvm/tools/src/LSP/src/test_data/quick_fix.k new file mode 100644 index 000000000..3f5bd5a63 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/quick_fix.k @@ -0,0 +1,2 @@ +import load_pkg_test +import load_pkg_test diff --git a/kclvm/tools/src/LSP/src/test_data/rename_test/base/person.k b/kclvm/tools/src/LSP/src/test_data/rename_test/base/person.k new file mode 100644 index 000000000..781b5249f --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/rename_test/base/person.k @@ -0,0 +1,13 @@ +schema Person: + name: Name + age: int + +schema Name: + first: str + +a = { + abc: "d" +} + +d = a.abc +e = a["abc"] \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/rename_test/config.k b/kclvm/tools/src/LSP/src/test_data/rename_test/config.k new file mode 100644 index 000000000..746f34df6 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/rename_test/config.k @@ -0,0 +1,8 @@ +import .base + +a = base.Person { + age: 1, + name: { + first: "aa" + } +} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/rename_test/main.k b/kclvm/tools/src/LSP/src/test_data/rename_test/main.k new file mode 100644 index 000000000..efd22bf88 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/rename_test/main.k @@ -0,0 +1,6 @@ +import .pkg.vars + +Bob = vars.Person { + name: "Bob" + age: 30 +} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/rename_test/pkg/vars.k b/kclvm/tools/src/LSP/src/test_data/rename_test/pkg/vars.k new file mode 100644 index 000000000..6f32c0650 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/rename_test/pkg/vars.k @@ -0,0 +1,13 @@ +schema Person: + name: str + age: int + +John = Person { + name: "John" + age: 20 +} + +Alice = Person { + name: "Alice" + age: 30 +} \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/test_data/rename_test/server.k b/kclvm/tools/src/LSP/src/test_data/rename_test/server.k new file mode 100644 index 000000000..291e67dc6 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/rename_test/server.k @@ -0,0 +1,2 @@ +schema Server: + name: str diff --git a/kclvm/tools/src/LSP/src/test_data/sema_token.k b/kclvm/tools/src/LSP/src/test_data/sema_token.k new file mode 100644 index 000000000..74be332c8 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/sema_token.k @@ -0,0 +1,9 @@ +import math as m +type num = int | float +schema Persons: + name: str + +p5: Persons = Persons { + name: "alice" +} +n: num = 1 \ No newline at end of file diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index f7ced6512..2ddd03add 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -1,216 +1,441 @@ +use crossbeam_channel::after; +use crossbeam_channel::select; +use indexmap::IndexSet; +use kclvm_ast::MAIN_PKG; +use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::resolver::scope::CachedScope; +use lsp_server::RequestId; +use lsp_server::Response; +use lsp_types::notification::Exit; +use lsp_types::request::GotoTypeDefinitionResponse; +use lsp_types::CompletionContext; +use lsp_types::CompletionItem; +use lsp_types::CompletionItemKind; +use lsp_types::CompletionParams; +use lsp_types::CompletionResponse; +use lsp_types::CompletionTriggerKind; +use lsp_types::DocumentFormattingParams; +use lsp_types::DocumentSymbolParams; +use lsp_types::GotoDefinitionParams; +use lsp_types::GotoDefinitionResponse; +use lsp_types::Hover; +use lsp_types::HoverContents; +use lsp_types::HoverParams; +use lsp_types::InitializeParams; +use lsp_types::MarkedString; +use lsp_types::PublishDiagnosticsParams; +use lsp_types::ReferenceContext; +use lsp_types::ReferenceParams; +use lsp_types::RenameParams; +use lsp_types::TextDocumentIdentifier; +use lsp_types::TextDocumentItem; +use lsp_types::TextDocumentPositionParams; +use lsp_types::TextEdit; +use lsp_types::Url; +use lsp_types::WorkspaceEdit; +use lsp_types::WorkspaceFolder; + +use serde::Serialize; +use std::cell::Cell; +use std::cell::RefCell; +use std::collections::HashMap; use std::env; +use std::path::Path; use std::path::PathBuf; use std::process::Command; +use std::sync::Arc; +use std::sync::Mutex; +use std::thread; +use std::time::Duration; -use indexmap::IndexSet; use kclvm_ast::ast::Program; -use kclvm_error::Diagnostic; +use kclvm_error::Diagnostic as KCLDiagnostic; use kclvm_error::Position as KCLPos; -use kclvm_sema::builtin::MATH_FUNCTION_NAMES; -use kclvm_sema::builtin::STRING_MEMBER_FUNCTIONS; +use kclvm_parser::KCLModuleCache; use kclvm_sema::resolver::scope::ProgramScope; -use lsp_types::CompletionResponse; -use lsp_types::DocumentSymbol; -use lsp_types::DocumentSymbolResponse; -use lsp_types::MarkedString; -use lsp_types::SymbolKind; -use lsp_types::Url; + +use lsp_types::Diagnostic; +use lsp_types::DiagnosticRelatedInformation; +use lsp_types::DiagnosticSeverity; +use lsp_types::Location; +use lsp_types::NumberOrString; use lsp_types::{Position, Range, TextDocumentContentChangeEvent}; +use parking_lot::RwLock; +use proc_macro_crate::bench_test; -use crate::document_symbol::document_symbol; +use lsp_server::{Connection, Message, Notification, Request}; + +use crate::completion::completion; +use crate::config::Config; use crate::from_lsp::file_path_from_url; + +use crate::goto_def::goto_definition_with_gs; use crate::hover::hover; -use crate::{ - completion::{completion, into_completion_items}, - goto_def::goto_definition, - util::{apply_document_changes, parse_param_and_compile, Param}, -}; +use crate::main_loop::main_loop; +use crate::to_lsp::kcl_diag_to_lsp_diags; +use crate::util::to_json; +use crate::util::{apply_document_changes, parse_param_and_compile, Param}; + +macro_rules! wait_async_compile { + () => { + thread::sleep(Duration::from_secs(2)); + }; +} -fn compile_test_file(testfile: &str) -> (String, Program, ProgramScope, IndexSet) { +pub(crate) fn compare_goto_res( + res: Option, + pos: (&String, u32, u32, u32, u32), +) { + match res.unwrap() { + lsp_types::GotoDefinitionResponse::Scalar(loc) => { + let got_path = file_path_from_url(&loc.uri).unwrap(); + assert_eq!(got_path, pos.0.to_string()); + + let (got_start, got_end) = (loc.range.start, loc.range.end); + + let expected_start = Position { + line: pos.1, // zero-based + character: pos.2, + }; + + let expected_end = Position { + line: pos.3, // zero-based + character: pos.4, + }; + assert_eq!(got_start, expected_start); + assert_eq!(got_end, expected_end); + } + _ => { + unreachable!("test error") + } + } +} + +pub(crate) fn compile_test_file( + testfile: &str, +) -> ( + String, + Program, + ProgramScope, + IndexSet, + GlobalState, +) { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut test_file = path; test_file.push(testfile); let file = test_file.to_str().unwrap().to_string(); - let (program, prog_scope, diags) = - parse_param_and_compile(Param { file: file.clone() }, None).unwrap(); - (file, program, prog_scope, diags) + let (program, prog_scope, diags, gs) = parse_param_and_compile( + Param { + file: file.clone(), + module_cache: Some(KCLModuleCache::default()), + scope_cache: Some(Arc::new(Mutex::new(CachedScope::default()))), + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); + (file, program, prog_scope, diags, gs) +} + +fn build_lsp_diag( + pos: (u32, u32, u32, u32), + message: String, + severity: Option, + related_info: Vec<(String, (u32, u32, u32, u32), String)>, + code: Option, + data: Option, +) -> Diagnostic { + let related_information = if related_info.is_empty() { + None + } else { + Some( + related_info + .iter() + .map(|(file, pos, msg)| DiagnosticRelatedInformation { + location: Location { + uri: Url::from_file_path(file).unwrap(), + range: Range { + start: Position { + line: pos.0, + character: pos.1, + }, + end: Position { + line: pos.2, + character: pos.3, + }, + }, + }, + message: msg.clone(), + }) + .collect(), + ) + }; + Diagnostic { + range: lsp_types::Range { + start: Position { + line: pos.0, + character: pos.1, + }, + end: Position { + line: pos.2, + character: pos.3, + }, + }, + severity, + code, + code_description: None, + source: None, + message, + related_information, + tags: None, + data, + } +} + +fn build_expect_diags() -> Vec { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut test_file = path.clone(); + test_file.push("src/test_data/diagnostics.k"); + let file = test_file.to_str().unwrap(); + let expected_diags: Vec = vec![ + build_lsp_diag( + (1, 4, 1, 4), + "expected one of [\"identifier\", \"literal\", \"(\", \"[\", \"{\"] got newline" + .to_string(), + Some(DiagnosticSeverity::ERROR), + vec![], + Some(NumberOrString::String("InvalidSyntax".to_string())), + None, + ), + build_lsp_diag( + (0, 0, 0, 10), + "pkgpath abc not found in the program".to_string(), + Some(DiagnosticSeverity::ERROR), + vec![], + Some(NumberOrString::String("CannotFindModule".to_string())), + None, + ), + build_lsp_diag( + (0, 0, 0, 10), + format!( + "Cannot find the module abc from {}/src/test_data/abc", + path.to_str().unwrap() + ), + Some(DiagnosticSeverity::ERROR), + vec![], + Some(NumberOrString::String("CannotFindModule".to_string())), + None, + ), + build_lsp_diag( + (8, 0, 8, 1), + "Can not change the value of 'd', because it was declared immutable".to_string(), + Some(DiagnosticSeverity::ERROR), + vec![( + file.to_string(), + (7, 0, 7, 1), + "The variable 'd' is declared here".to_string(), + )], + Some(NumberOrString::String("ImmutableError".to_string())), + None, + ), + build_lsp_diag( + (7, 0, 7, 1), + "The variable 'd' is declared here".to_string(), + Some(DiagnosticSeverity::ERROR), + vec![( + file.to_string(), + (8, 0, 8, 1), + "Can not change the value of 'd', because it was declared immutable".to_string(), + )], + Some(NumberOrString::String("ImmutableError".to_string())), + None, + ), + build_lsp_diag( + (2, 0, 2, 1), + "expected str, got int(1)".to_string(), + Some(DiagnosticSeverity::ERROR), + vec![], + Some(NumberOrString::String("TypeError".to_string())), + None, + ), + build_lsp_diag( + (10, 8, 10, 10), + "name 'nu' is not defined, did you mean '[\"number\", \"n\", \"num\"]'?".to_string(), + Some(DiagnosticSeverity::ERROR), + vec![], + Some(NumberOrString::String("CompileError".to_string())), + Some(serde_json::json!({ "suggested_replacement": ["number", "n", "num"] })), + ), + build_lsp_diag( + (0, 0, 0, 10), + "Module 'abc' imported but unused".to_string(), + Some(DiagnosticSeverity::WARNING), + vec![], + Some(NumberOrString::String("UnusedImportWarning".to_string())), + None, + ), + ]; + expected_diags } #[test] +#[bench_test] fn diagnostics_test() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut test_file = path.clone(); test_file.push("src/test_data/diagnostics.k"); let file = test_file.to_str().unwrap(); - let (_, _, diags) = parse_param_and_compile( + let (_, _, diags, _) = parse_param_and_compile( Param { file: file.to_string(), + module_cache: None, + scope_cache: None, }, - None, + Some(Arc::new(RwLock::new(Default::default()))), ) .unwrap(); - let msgs = [ - "expected one of [\"identifier\", \"literal\", \"(\", \"[\", \"{\"] got newline", - "pkgpath abc not found in the program", - &format!( - "Cannot find the module abc from {}/src/test_data/abc", - path.to_str().unwrap() - ), - "expected str, got int(1)", - "Module 'abc' imported but unused", - ]; - assert_eq!(diags.len(), msgs.len()); - for (diag, m) in diags.iter().zip(msgs.iter()) { - assert_eq!(diag.messages[0].message, m.to_string()); + let diagnostics = diags + .iter() + .flat_map(|diag| kcl_diag_to_lsp_diags(diag, file)) + .collect::>(); + + let expected_diags: Vec = build_expect_diags(); + for (get, expected) in diagnostics.iter().zip(expected_diags.iter()) { + assert_eq!(get, expected) } } #[test] -fn goto_import_pkg_test() { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); - let pos = KCLPos { - filename: file, - line: 1, - column: Some(10), - }; +#[bench_test] +fn test_apply_document_changes() { + macro_rules! change { + [$($sl:expr, $sc:expr; $el:expr, $ec:expr => $text:expr),+] => { + vec![$(TextDocumentContentChangeEvent { + range: Some(Range { + start: Position { line: $sl, character: $sc }, + end: Position { line: $el, character: $ec }, + }), + range_length: None, + text: String::from($text), + }),+] + }; + } - let res = goto_definition(&program, &pos, &prog_scope); - let mut expeced_files = IndexSet::new(); - let path_str = path.to_str().unwrap(); - let test_files = [ - "src/test_data/goto_def_test/pkg/schema_def1.k", - "src/test_data/goto_def_test/pkg/schema_def.k", - ]; - expeced_files.insert(format!("{}/{}", path_str, test_files[0])); - expeced_files.insert(format!("{}/{}", path_str, test_files[1])); + let mut text = String::new(); + apply_document_changes(&mut text, vec![]); + assert_eq!(text, ""); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Array(arr) => { - assert_eq!(expeced_files.len(), arr.len()); - for loc in arr { - let got_path = loc.uri.path().to_string(); - assert!(expeced_files.contains(&got_path)); - } - } - _ => { - unreachable!("test error") - } - } -} + // Test if full updates work (without a range) + apply_document_changes( + &mut text, + vec![TextDocumentContentChangeEvent { + range: None, + range_length: None, + text: String::from("the"), + }], + ); -#[test] -fn goto_import_file_test() { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + assert_eq!(text, "the"); + apply_document_changes(&mut text, change![0, 3; 0, 3 => " quick"]); + assert_eq!(text, "the quick"); - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); + apply_document_changes(&mut text, change![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); + assert_eq!(text, "quick foxes"); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + apply_document_changes(&mut text, change![0, 11; 0, 11 => "\ndream"]); + assert_eq!(text, "quick foxes\ndream"); - // test goto import file: import .pkg.schema_def - let pos = KCLPos { - filename: file, - line: 2, - column: Some(10), - }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()) - } - _ => { - unreachable!("test error") - } - } -} + apply_document_changes(&mut text, change![1, 0; 1, 0 => "have "]); + assert_eq!(text, "quick foxes\nhave dream"); -#[test] -fn goto_schema_def_test() { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + apply_document_changes( + &mut text, + change![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], + ); + assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); + apply_document_changes( + &mut text, + change![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"], + ); + assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + apply_document_changes( + &mut text, + change![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], + ); + assert_eq!( + text, + "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n" + ); - // test goto schema definition: p = pkg.Person - let pos = KCLPos { - filename: file, - line: 4, - column: Some(11), - }; - let res = goto_definition(&program, &pos, &prog_scope); + apply_document_changes(&mut text, change![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); + assert_eq!(text, "the quick \nthey have quiet dreams\n"); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); + text = String::from("❤️"); + apply_document_changes(&mut text, change![0, 0; 0, 0 => "a"]); + assert_eq!(text, "a❤️"); - let (got_start, got_end) = (loc.range.start, loc.range.end); + // todo: Non-ASCII char + // text = String::from("a\nb"); + // apply_document_changes(&mut text, change![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); + // assert_eq!(text, "adcb"); - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; + // text = String::from("a\nb"); + // apply_document_changes(&mut text, change![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); + // assert_eq!(text, "ațc\ncb"); +} - let expected_end = Position { - line: 5, // zero-based - character: 13, - }; - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); - } - _ => { - unreachable!("test error") - } +#[test] +#[bench_test] +fn file_path_from_url_test() { + if cfg!(windows) { + let url = + Url::parse("file:///c%3A/Users/abc/Desktop/%E4%B8%AD%E6%96%87/ab%20c/abc.k").unwrap(); + let path = file_path_from_url(&url).unwrap(); + assert_eq!(path, "c:\\Users\\abc\\Desktop\\中文\\ab c\\abc.k"); + } else { + let url = Url::parse("file:///Users/abc/Desktop/%E4%B8%AD%E6%96%87/ab%20c/abc.k").unwrap(); + let path = file_path_from_url(&url).unwrap(); + assert_eq!(path, "/Users/abc/Desktop/中文/ab c/abc.k"); } } #[test] -fn goto_identifier_def_test() { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); - - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); +fn test_lsp_with_kcl_mod_in_order() { + goto_import_external_file_test(); + println!("goto_import_external_file_test PASS"); + goto_import_pkg_with_line_test(); + println!("goto_import_pkg_with_line_test PASS"); + complete_import_external_file_test(); + println!("complete_import_external_file_test PASS"); +} - // test goto identifier definition: p1 = p +fn goto_import_pkg_with_line_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let (file, program, _, _, gs) = + compile_test_file("src/test_data/goto_def_with_line_test/main_pkg/main.k"); let pos = KCLPos { - filename: file.to_string(), - line: 9, - column: Some(6), + filename: file, + line: 1, + column: Some(27), }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, file); - - let (got_start, got_end) = (loc.range.start, loc.range.end); - - let expected_start = Position { - line: 3, // zero-based - character: 0, - }; - let expected_end = Position { - line: 3, // zero-based - character: 1, - }; + let res = goto_definition_with_gs(&program, &pos, &gs); - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); + match res.unwrap() { + lsp_types::GotoDefinitionResponse::Scalar(loc) => { + let got_path = file_path_from_url(&loc.uri).unwrap(); + let expected_path = path + .join("src/test_data/goto_def_with_line_test/dep-with-line/main.k") + .canonicalize() + .unwrap() + .display() + .to_string(); + assert_eq!(got_path, expected_path) } _ => { unreachable!("test error") @@ -218,171 +443,314 @@ fn goto_identifier_def_test() { } } -#[test] -fn goto_schema_attr_ty_def_test() { - // test goto schema attr type definition: p1: pkg.Person - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); +fn complete_import_external_file_test() { + let path = PathBuf::from(".") + .join("src") + .join("test_data") + .join("completion_test") + .join("import") + .join("external") + .join("main.k") + .canonicalize() + .unwrap() + .display() + .to_string(); - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); + let _ = Command::new("kcl") + .arg("mod") + .arg("metadata") + .arg("--update") + .current_dir( + PathBuf::from(".") + .join("src") + .join("test_data") + .join("completion_test") + .join("import") + .join("external") + .canonicalize() + .unwrap() + .display() + .to_string(), + ) + .output() + .unwrap(); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + let (program, _, _, gs) = parse_param_and_compile( + Param { + file: path.to_string(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); let pos = KCLPos { - filename: file, - line: 12, - column: Some(15), + filename: path.to_string(), + line: 1, + column: Some(11), }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); - - let (got_start, got_end) = (loc.range.start, loc.range.end); - - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; + let res = completion(Some('.'), &program, &pos, &gs).unwrap(); - let expected_end = Position { - line: 5, // zero-based - character: 13, - }; - - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); - } - _ => { - unreachable!("test error") - } - } + let got_labels: Vec = match &res { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let expected_labels: Vec<&str> = vec![ + "api", + "apiextensions_apiserver", + "apimachinery", + "kube_aggregator", + "vendor", + ]; + assert_eq!(got_labels, expected_labels); } -#[test] -fn goto_schema_attr_ty_def_test1() { - // test goto schema attr type definition: p2: [pkg.Person] - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); +fn goto_import_external_file_test() { + let path = PathBuf::from(".") + .join("src") + .join("test_data") + .join("goto_import_def_test") + .join("main.k") + .canonicalize() + .unwrap() + .display() + .to_string(); + + let _ = Command::new("kcl") + .arg("mod") + .arg("metadata") + .arg("--update") + .current_dir( + PathBuf::from(".") + .join("src") + .join("test_data") + .join("goto_import_def_test") + .canonicalize() + .unwrap() + .display() + .to_string(), + ) + .output() + .unwrap(); - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); + let (program, _, diags, gs) = parse_param_and_compile( + Param { + file: path.to_string(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + assert_eq!(diags.len(), 0); + // test goto import file: import .pkg.schema_def let pos = KCLPos { - filename: file, - line: 13, - column: Some(15), + filename: path.to_string(), + line: 1, + column: Some(57), }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); - - let (got_start, got_end) = (loc.range.start, loc.range.end); + let res = goto_definition_with_gs(&program, &pos, &gs); + assert!(res.is_some()); +} - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; +// LSP e2e test - let expected_end = Position { - line: 5, // zero-based - character: 13, - }; +/// A `Project` represents a project that a language server can work with. Call the [`server`] +/// method to instantiate a language server that will serve information about the project. +pub struct Project {} - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); - } - _ => { - unreachable!("test error") - } +impl Project { + /// Instantiates a language server for this project. + pub fn server(self, initialize_params: InitializeParams) -> Server { + let config = Config::default(); + Server::new(config, initialize_params) } } -#[test] -fn goto_schema_attr_ty_def_test3() { - // test goto schema attr type definition: p3: {str: pkg.Person} - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); +/// An object that runs the language server main loop and enables sending and receiving messages +/// to and from it. +pub struct Server { + next_request_id: Cell, + worker: Option>, + client: Connection, + messages: RefCell>, +} - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); +impl Server { + /// Constructs and initializes a new `Server` + pub fn new(config: Config, initialize_params: InitializeParams) -> Self { + let (connection, client) = Connection::memory(); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + let worker = std::thread::spawn(move || { + main_loop(connection, config, initialize_params).unwrap(); + }); - let pos = KCLPos { - filename: file, - line: 14, - column: Some(22), - }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); + Self { + next_request_id: Cell::new(1), + worker: Some(worker), + client, + messages: RefCell::new(Vec::new()), + } + } - let (got_start, got_end) = (loc.range.start, loc.range.end); + /// Sends a request to the language server, returning the response + pub fn send_request(&self, params: R::Params) { + let id = self.next_request_id.get(); + self.next_request_id.set(id.wrapping_add(1)); + let r = Request::new(id.into(), R::METHOD.to_string(), params); + self.client.sender.send(r.into()).unwrap(); + } - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; + /// Sends an LSP notification to the main loop. + pub(crate) fn notification(&self, params: N::Params) + where + N::Params: Serialize, + { + let r = Notification::new(N::METHOD.to_string(), params); + self.send_notification(r) + } - let expected_end = Position { - line: 5, // zero-based - character: 13, - }; + /// Sends a server notification to the main loop + fn send_notification(&self, not: Notification) { + self.client.sender.send(Message::Notification(not)).unwrap(); + } - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); + /// A function to wait for a specific message to arrive + fn wait_for_message_cond(&self, n: usize, cond: &dyn Fn(&Message) -> bool) { + let mut total = 0; + for msg in self.messages.borrow().iter() { + if cond(msg) { + total += 1 + } } - _ => { - unreachable!("test error") + while total < n { + let msg = self.recv().expect("no response"); + if cond(&msg) { + total += 1; + } } } -} -#[test] -fn goto_schema_attr_ty_def_test4() { - // test goto schema attr type definition(Person): p4: pkg.Person | pkg.Person1 - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + /// Receives a message from the message or timeout. + pub(crate) fn recv(&self) -> Option { + let timeout = Duration::from_secs(5); + let msg = select! { + recv(self.client.receiver) -> msg => msg.ok(), + recv(after(timeout)) -> _ => panic!("timed out"), + }; + if let Some(ref msg) = msg { + self.messages.borrow_mut().push(msg.clone()); + } + msg + } - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); + /// Receives a message from the message, if timeout, return None. + pub(crate) fn recv_without_timeout(&self) -> Option { + let timeout = Duration::from_secs(5); + let msg = select! { + recv(self.client.receiver) -> msg => msg.ok(), + recv(after(timeout)) -> _ => return None, + }; + if let Some(ref msg) = msg { + self.messages.borrow_mut().push(msg.clone()); + } + msg + } - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + /// Sends a request to the main loop and receives its response + fn send_and_receive(&self, r: Request) -> Response { + let id = r.id.clone(); + self.client.sender.send(r.into()).unwrap(); + while let Some(msg) = self.recv() { + match msg { + Message::Request(req) => { + panic!("did not expect a request as a response to a request: {req:?}") + } + Message::Notification(_) => (), + Message::Response(res) => { + assert_eq!(res.id, id); + return res; + } + } + } + panic!("did not receive a response to our request"); + } - let pos = KCLPos { - filename: file, - line: 15, - column: Some(17), - }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); + fn receive_response(&self, id: RequestId) -> Option { + while let Some(msg) = self.recv_without_timeout() { + match msg { + Message::Request(req) => { + panic!("did not expect a request as a response to a request: {req:?}") + } + Message::Notification(_) => (), + Message::Response(res) => { + if res.id == id { + return Some(res); + } + } + } + } + None + } +} - let (got_start, got_end) = (loc.range.start, loc.range.end); +impl Drop for Server { + fn drop(&mut self) { + // Send the proper shutdown sequence to ensure the main loop terminates properly + self.notification::(()); - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; + // Cancel the main_loop + if let Some(worker) = self.worker.take() { + worker.join().unwrap(); + } + } +} - let expected_end = Position { - line: 5, // zero-based - character: 13, - }; +#[test] +fn notification_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/diagnostics.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); + // Wait for first "textDocument/publishDiagnostics" notification + server.wait_for_message_cond(1, &|msg: &Message| match msg { + Message::Notification(not) => not.method == "textDocument/publishDiagnostics", + _ => false, + }); + + let msgs = server.messages.borrow(); + + match msgs.last().unwrap() { + Message::Notification(not) => { + assert_eq!( + not.params, + to_json(PublishDiagnosticsParams { + uri: Url::from_file_path(path).unwrap(), + diagnostics: build_expect_diags(), + version: None, + }) + .unwrap() + ); } _ => { unreachable!("test error") @@ -391,383 +759,1193 @@ fn goto_schema_attr_ty_def_test4() { } #[test] -fn goto_schema_attr_ty_def_test5() { - // test goto schema attr type definition(Person1): p4: pkg.Person | pkg.Person1 - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); - - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def1.k"); +fn close_file_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/diagnostics.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src.clone(), + }, + }, + ); - let pos = KCLPos { - filename: file, - line: 15, - column: Some(28), - }; - let res = goto_definition(&program, &pos, &prog_scope); - match res.unwrap() { - lsp_types::GotoDefinitionResponse::Scalar(loc) => { - let got_path = loc.uri.path(); - assert_eq!(got_path, expected_path.to_str().unwrap()); + // Mock close file + server.notification::( + lsp_types::DidCloseTextDocumentParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + }, + ); - let (got_start, got_end) = (loc.range.start, loc.range.end); + // Mock reopen file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); +} - let expected_start = Position { - line: 0, // zero-based - character: 0, - }; +#[test] +fn non_kcl_file_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + let server = Project {}.server(InitializeParams::default()); + let mut path = root.clone(); + path.push("src/test_data/diagnostics.kcl"); + + // Mock open a Non-KCL file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path.clone()).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: "".to_string(), + }, + }, + ); - let expected_end = Position { - line: 2, // zero-based - character: 13, - }; + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/documentSymbol".to_string(), + DocumentSymbolParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, + ); - assert_eq!(got_start, expected_start); - assert_eq!(got_end, expected_end); - } - _ => unreachable!("test error"), - } + // Send request and wait for it's response + let res = server.send_and_receive(r); + assert!(res.result.is_some()); } #[test] -fn test_apply_document_changes() { - macro_rules! change { - [$($sl:expr, $sc:expr; $el:expr, $ec:expr => $text:expr),+] => { - vec![$(TextDocumentContentChangeEvent { - range: Some(Range { - start: Position { line: $sl, character: $sc }, - end: Position { line: $el, character: $ec }, - }), - range_length: None, - text: String::from($text), - }),+] - }; - } +fn cancel_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/goto_def_test/goto_def.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); - let mut text = String::new(); - apply_document_changes(&mut text, vec![]); - assert_eq!(text, ""); + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); - // Test if full updates work (without a range) - apply_document_changes( - &mut text, - vec![TextDocumentContentChangeEvent { - range: None, - range_length: None, - text: String::from("the"), - }], + // send request + server.send_request::(GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(23, 9), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + + // cancel request + server.notification::(lsp_types::CancelParams { + id: NumberOrString::Number(id), + }); + + assert!(server.receive_response(id.into()).is_none()); +} + +#[test] +fn goto_def_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/goto_def_test/goto_def.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + + wait_async_compile!(); + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/definition".to_string(), + GotoDefinitionParams { + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(23, 9), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }, ); - assert_eq!(text, "the"); - apply_document_changes(&mut text, change![0, 3; 0, 3 => " quick"]); - assert_eq!(text, "the quick"); + // Send request and wait for it's response + let res = server.send_and_receive(r); - apply_document_changes(&mut text, change![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]); - assert_eq!(text, "quick foxes"); + assert_eq!( + res.result.unwrap(), + to_json(GotoDefinitionResponse::Scalar(Location { + uri: Url::from_file_path(path).unwrap(), + range: Range { + start: Position::new(20, 7), + end: Position::new(20, 13), + }, + })) + .unwrap() + ); +} - apply_document_changes(&mut text, change![0, 11; 0, 11 => "\ndream"]); - assert_eq!(text, "quick foxes\ndream"); +#[test] +fn complete_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/completion_test/dot/completion.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + wait_async_compile!(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/completion".to_string(), + CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(11, 7), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context: Some(CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, + trigger_character: Some(".".to_string()), + }), + }, + ); - apply_document_changes(&mut text, change![1, 0; 1, 0 => "have "]); - assert_eq!(text, "quick foxes\nhave dream"); + // Send request and wait for it's response + let res = server.send_and_receive(r); - apply_document_changes( - &mut text, - change![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"], - ); - assert_eq!(text, "the quick foxes\nhave quiet dreams\n"); + assert_eq!( + res.result.unwrap(), + to_json(CompletionResponse::Array(vec![ + CompletionItem { + label: "name".to_string(), + kind: Some(CompletionItemKind::FIELD), + detail: Some("name: str".to_string()), + ..Default::default() + }, + CompletionItem { + label: "age".to_string(), + kind: Some(CompletionItemKind::FIELD), + detail: Some("age: int".to_string()), + ..Default::default() + } + ])) + .unwrap() + ) +} - apply_document_changes( - &mut text, - change![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"], +#[test] +fn hover_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/hover_test/hover.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + wait_async_compile!(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/hover".to_string(), + HoverParams { + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(15, 7), + }, + work_done_progress_params: Default::default(), + }, ); - assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n"); - apply_document_changes( - &mut text, - change![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"], + // Send request and wait for it's response + let res = server.send_and_receive(r); + + assert_eq!( + res.result.unwrap(), + to_json(Hover { + contents: HoverContents::Array(vec![ + MarkedString::String("__main__\n\nschema Person".to_string()), + MarkedString::String("hover doc test".to_string()), + MarkedString::String("Attributes:\n\nname: str\n\nage?: int".to_string()), + ]), + range: None + }) + .unwrap() + ) +} + +#[test] +fn hover_assign_in_lambda_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/hover_test/assign_in_lambda.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + wait_async_compile!(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/hover".to_string(), + HoverParams { + text_document_position_params: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + position: Position::new(4, 7), + }, + work_done_progress_params: Default::default(), + }, ); + + // Send request and wait for it's response + let res = server.send_and_receive(r); + assert_eq!( - text, - "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n" + res.result.unwrap(), + to_json(Hover { + contents: HoverContents::Scalar(MarkedString::String("images: [str]".to_string()),), + range: None + }) + .unwrap() + ) +} + +#[test] +fn formatting_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + + path.push("src/test_data/format/format_range.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let server = Project {}.server(InitializeParams::default()); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: Url::from_file_path(path).unwrap(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, ); - apply_document_changes(&mut text, change![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); - assert_eq!(text, "the quick \nthey have quiet dreams\n"); + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/formatting".to_string(), + DocumentFormattingParams { + text_document: TextDocumentIdentifier { + uri: Url::from_file_path(path).unwrap(), + }, + options: Default::default(), + work_done_progress_params: Default::default(), + }, + ); - text = String::from("❤️"); - apply_document_changes(&mut text, change![0, 0; 0, 0 => "a"]); - assert_eq!(text, "a❤️"); + // Send request and wait for it's response + let res = server.send_and_receive(r); - // todo: Non-ASCII char - // text = String::from("a\nb"); - // apply_document_changes(&mut text, change![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]); - // assert_eq!(text, "adcb"); + assert_eq!( + res.result.unwrap(), + to_json(Some(vec![TextEdit { + range: Range::new(Position::new(0, 0), Position::new(u32::MAX, u32::MAX),), + new_text: "a = 1\nb = 2\nc = 3\nd = 4\n".to_string() + }])) + .unwrap() + ) +} - // text = String::from("a\nb"); - // apply_document_changes(&mut text, change![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]); - // assert_eq!(text, "ațc\ncb"); +// Integration testing of lsp and konfig +fn konfig_path() -> PathBuf { + let konfig_path = Path::new(".") + .canonicalize() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .parent() + .unwrap() + .join("test") + .join("integration") + .join("konfig"); + konfig_path } #[test] -fn completion_test() { - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/completion_test/dot/completion.k"); +fn konfig_goto_def_test_base() { + let konfig_path = konfig_path(); + let mut base_path = konfig_path.clone(); + base_path.push("appops/nginx-example/base/base.k"); + let base_path_str = base_path.to_str().unwrap().to_string(); + let (program, _, _, gs) = parse_param_and_compile( + Param { + file: base_path_str.clone(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); - // test completion for schema attr + // schema def let pos = KCLPos { - filename: file.to_owned(), - line: 12, - column: Some(7), + filename: base_path_str.clone(), + line: 7, + column: Some(30), }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/server.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 12, 7, 12, 13), + ); - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - let mut items = IndexSet::new(); - items.insert("name".to_string()); - items.insert("age".to_string()); - - let expect: CompletionResponse = into_completion_items(&items).into(); + // schema def + let pos = KCLPos { + filename: base_path_str.clone(), + line: 9, + column: Some(32), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/container/container.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 5, 7, 5, 11), + ); - assert_eq!(got, expect); - items.clear(); + // schema attr + let pos = KCLPos { + filename: base_path_str.clone(), + line: 9, + column: Some(9), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/server.k"); + compare_goto_res( + res, + ( + &expected_path.to_str().unwrap().to_string(), + 115, + 4, + 115, + 17, + ), + ); + // schema attr let pos = KCLPos { - filename: file.to_owned(), - line: 14, - column: Some(12), + filename: base_path_str.clone(), + line: 10, + column: Some(10), }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/container/container.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 69, 4, 69, 9), + ); - // test completion for str builtin function - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - let binding = STRING_MEMBER_FUNCTIONS; - for k in binding.keys() { - items.insert(format!("{}{}", k, "()")); - } - let expect: CompletionResponse = into_completion_items(&items).into(); + // import pkg + let pos = KCLPos { + filename: base_path_str.clone(), + line: 2, + column: Some(49), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/service/service.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 0, 0, 0), + ); +} - assert_eq!(got, expect); - items.clear(); +#[test] +fn konfig_goto_def_test_main() { + let konfig_path = konfig_path(); + let mut main_path = konfig_path.clone(); + main_path.push("appops/nginx-example/dev/main.k"); + let main_path_str = main_path.to_str().unwrap().to_string(); + let (program, _, _, gs) = parse_param_and_compile( + Param { + file: main_path_str.clone(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); - // test completion for import pkg path + // schema def let pos = KCLPos { - filename: file.to_owned(), - line: 1, - column: Some(12), + filename: main_path_str.clone(), + line: 6, + column: Some(31), }; - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - items.insert("file1".to_string()); - items.insert("file2".to_string()); - items.insert("subpkg".to_string()); + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/server.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 12, 7, 12, 13), + ); - let expect: CompletionResponse = into_completion_items(&items).into(); - assert_eq!(got, expect); - items.clear(); + // schema attr + let pos = KCLPos { + filename: main_path_str.clone(), + line: 7, + column: Some(14), + }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/frontend/server.k"); + compare_goto_res( + res, + ( + &expected_path.to_str().unwrap().to_string(), + 112, + 4, + 112, + 22, + ), + ); - // test completion for import pkg' schema + // import pkg let pos = KCLPos { - filename: file.to_owned(), - line: 16, - column: Some(12), + filename: main_path_str.clone(), + line: 2, + column: Some(61), }; + let res = goto_definition_with_gs(&program, &pos, &gs); + let mut expected_path = konfig_path.clone(); + expected_path.push("base/pkg/kusion_models/kube/templates/resource.k"); + compare_goto_res( + res, + (&expected_path.to_str().unwrap().to_string(), 0, 0, 0, 0), + ); +} - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - items.insert("Person1".to_string()); - let expect: CompletionResponse = into_completion_items(&items).into(); - assert_eq!(got, expect); - items.clear(); +#[test] +fn konfig_completion_test_main() { + let konfig_path = konfig_path(); + let mut main_path = konfig_path.clone(); + main_path.push("appops/nginx-example/dev/main.k"); + let main_path_str = main_path.to_str().unwrap().to_string(); + let (program, _, _, gs) = parse_param_and_compile( + Param { + file: main_path_str.clone(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); + // pkg's definition(schema) completion let pos = KCLPos { - filename: file.to_owned(), - line: 19, - column: Some(5), + filename: main_path_str.clone(), + line: 6, + column: Some(27), + }; + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), }; - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - items.extend(MATH_FUNCTION_NAMES.iter().map(|s| s.to_string())); - let expect: CompletionResponse = into_completion_items(&items).into(); - assert_eq!(got, expect); - items.clear(); - // test completion for literal str builtin function + let expected_labels: Vec = ["Job", "Server"] + .iter() + .map(|attr| attr.to_string()) + .collect(); + assert_eq!(got_labels, expected_labels); + + // schema attr completion let pos = KCLPos { - filename: file, - line: 21, + filename: main_path_str.clone(), + line: 7, column: Some(4), }; + let got = completion(None, &program, &pos, &gs).unwrap(); + let mut got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let mut attr = [ + "frontend", + "service", + "container", + "res_tpl", + "rbac", + "backend", + "resource", + "metadata", + "apis", + "corev1", + "monitoringv1", + "monitoringv1alpha1", + "kubevelav1beta1", + "commons", + "vaultv1", + "manifests", + "__META_APP_NAME", + "__META_ENV_TYPE_NAME", + "__META_CLUSTER_NAME", + "appConfiguration", + "checkIdentical", + "manifestsResourceMap", + "remove_duplicated_iter", + "__renderServerFrontendInstances__", + "__renderServerBackendInstances__", + "__renderJobFrontendInstances__", + "__renderJobBackendInstances__", + "__renderFrontendInstances__", + "__renderBackendInstances__", + "__rbac_map__", + "__prometheus_map__", + "__vault_map__", + "__k8s__", + "__array_of_resource_map___", + "__resource_map_original___", + "_providerResource", + "_providerResourceMapping", + "__resource_map___", + "__is_kubevela_application__", + "getId", + "kubevela_app", + "kubevela_output", + "server_output", + "schedulingStrategy", + "name", + "workloadType", + "renderType", + "replicas", + "image", + "mainContainer", + "sidecarContainers", + "initContainers", + "useBuiltInLabels", + "labels", + "annotations", + "useBuiltInSelector", + "selector", + "podMetadata", + "volumes", + "needNamespace", + "enableMonitoring", + "configMaps", + "secrets", + "services", + "ingresses", + "serviceAccount", + "storage", + "database", + ]; + assert_eq!(got_labels.sort(), attr.sort()); - let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - let binding = STRING_MEMBER_FUNCTIONS; - for k in binding.keys() { - items.insert(format!("{}{}", k, "()")); - } - let expect: CompletionResponse = into_completion_items(&items).into(); - - assert_eq!(got, expect); + // import path completion + let pos = KCLPos { + filename: main_path_str.clone(), + line: 1, + column: Some(35), + }; + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + let mut got_labels: Vec = match got { + CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), + CompletionResponse::List(_) => panic!("test failed"), + }; + let mut pkgs = [ + "common", + "configmap", + "container", + "ingress", + "job", + "rbac", + "resource", + "secret", + "server", + "service", + "serviceaccount", + "sidecar", + "storage", + "strategy", + "volume", + ]; + assert_eq!(got_labels.sort(), pkgs.sort()); } #[test] -fn schema_doc_hover_test() { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - - let (file, program, prog_scope, _) = - compile_test_file("src/test_data/goto_def_test/goto_def.k"); +fn konfig_hover_test_main() { + let konfig_path = konfig_path(); + let mut main_path = konfig_path.clone(); + main_path.push("appops/nginx-example/dev/main.k"); + let main_path_str = main_path.to_str().unwrap().to_string(); + let (program, _, _, gs) = parse_param_and_compile( + Param { + file: main_path_str.clone(), + module_cache: None, + scope_cache: None, + }, + Some(Arc::new(RwLock::new(Default::default()))), + ) + .unwrap(); - let mut expected_path = path; - expected_path.push("src/test_data/goto_def_test/pkg/schema_def.k"); + // schema def hover + let pos = KCLPos { + filename: main_path_str.clone(), + line: 6, + column: Some(32), + }; + let got = hover(&program, &pos, &gs).unwrap(); + match got.contents { + HoverContents::Array(arr) => { + let expect: Vec = ["base.pkg.kusion_models.kube.frontend\n\nschema Server", + "Server is abstaction of Deployment and StatefulSet.", + "Attributes:\n\nname?: str\n\nworkloadType: str(Deployment) | str(StatefulSet)\n\nrenderType?: str(Server) | str(KubeVelaApplication)\n\nreplicas: int\n\nimage: str\n\nschedulingStrategy: SchedulingStrategy\n\nmainContainer: Main\n\nsidecarContainers?: [Sidecar]\n\ninitContainers?: [Sidecar]\n\nuseBuiltInLabels?: bool\n\nlabels?: {str:str}\n\nannotations?: {str:str}\n\nuseBuiltInSelector?: bool\n\nselector?: {str:str}\n\npodMetadata?: ObjectMeta\n\nvolumes?: [Volume]\n\nneedNamespace?: bool\n\nenableMonitoring?: bool\n\nconfigMaps?: [ConfigMap]\n\nsecrets?: [Secret]\n\nservices?: [Service]\n\ningresses?: [Ingress]\n\nserviceAccount?: ServiceAccount\n\nstorage?: ObjectStorage\n\ndatabase?: DataBase"] + .iter() + .map(|s| MarkedString::String(s.to_string())) + .collect(); + assert_eq!(expect, arr); + } + _ => unreachable!("test error"), + } - // test hover of schema doc: p = pkg.Person + // schema attr def hover let pos = KCLPos { - filename: file.clone(), - line: 4, - column: Some(11), + filename: main_path_str.clone(), + line: 7, + column: Some(15), }; - let got = hover(&program, &pos, &prog_scope).unwrap(); + let got = hover(&program, &pos, &gs).unwrap(); match got.contents { - lsp_types::HoverContents::Array(vec) => { - if let MarkedString::String(s) = vec[0].clone() { - assert_eq!(s, "Person"); - } - if let MarkedString::String(s) = vec[1].clone() { - assert_eq!(s, "hover doc test"); - } + HoverContents::Array(arr) => { + let expect: Vec = [ + "schedulingStrategy: SchedulingStrategy", + "SchedulingStrategy represents scheduling strategy.", + ] + .iter() + .map(|s| MarkedString::String(s.to_string())) + .collect(); + assert_eq!(expect, arr); } _ => unreachable!("test error"), } + + // variable hover let pos = KCLPos { - filename: file, - line: 5, - column: Some(7), + filename: main_path_str.clone(), + line: 6, + column: Some(3), }; - let got = hover(&program, &pos, &prog_scope).unwrap(); + let got = hover(&program, &pos, &gs).unwrap(); match got.contents { - lsp_types::HoverContents::Scalar(marked_string) => { - if let MarkedString::String(s) = marked_string { - assert_eq!(s, "str"); - } + HoverContents::Scalar(s) => { + assert_eq!( + s, + MarkedString::String("appConfiguration: Server".to_string()) + ); } _ => unreachable!("test error"), } } -#[allow(deprecated)] -fn build_document_symbol( - name: &str, - kind: SymbolKind, - range: ((u32, u32), (u32, u32)), - child: Option>, - detail: Option, -) -> DocumentSymbol { - let range: Range = Range { - start: Position { - line: range.0 .0, - character: range.0 .1, - }, - end: Position { - line: range.1 .0, - character: range.1 .1, +#[test] +fn lsp_version_test() { + let args = vec!["kcl-language-server".to_string(), "version".to_string()]; + let matches = crate::main_loop::app() + .arg_required_else_help(false) + .try_get_matches_from(args); + match matches { + Ok(arg_match) => match arg_match.subcommand() { + Some(("version", _)) => {} + _ => panic!("test failed"), }, - }; - DocumentSymbol { - name: name.to_string(), - detail, - kind, - tags: None, - deprecated: None, - range, - selection_range: range, - children: child, + Err(_) => panic!("test failed"), } } #[test] -fn document_symbol_test() { - let (file, program, prog_scope, _) = compile_test_file("src/test_data/document_symbol.k"); - - let res = document_symbol(file.as_str(), &program, &prog_scope).unwrap(); - let mut expect = vec![]; - expect.push(build_document_symbol( - "p", - SymbolKind::VARIABLE, - ((3, 0), (3, 1)), - None, - Some("Person4".to_string()), - )); - expect.push(build_document_symbol( - "Person4", - SymbolKind::STRUCT, - ((0, 7), (1, 13)), - Some(vec![build_document_symbol( - "name", - SymbolKind::PROPERTY, - ((1, 4), (1, 8)), - None, - Some("str".to_string()), - )]), - Some("schema".to_string()), - )); - let expect = DocumentSymbolResponse::Nested(expect); - assert_eq!(res, expect) +fn lsp_run_test() { + let args = vec!["kcl-language-server".to_string()]; + let matches = crate::main_loop::app() + .arg_required_else_help(false) + .try_get_matches_from(args); + match matches { + Ok(arg_match) => match arg_match.subcommand() { + None => {} + _ => panic!("test failed"), + }, + Err(_) => panic!("test failed"), + } } #[test] -fn file_path_from_url_test() { - if cfg!(windows) { - let url = - Url::parse("file:///c%3A/Users/abc/Desktop/%E4%B8%AD%E6%96%87/ab%20c/abc.k").unwrap(); - let path = file_path_from_url(&url).unwrap(); - assert_eq!(path, "c:\\Users\\abc\\Desktop\\中文\\ab c\\abc.k"); - } else { - let url = Url::parse("file:///Users/abc/Desktop/%E4%B8%AD%E6%96%87/ab%20c/abc.k").unwrap(); - let path = file_path_from_url(&url).unwrap(); - assert_eq!(path, "/Users/abc/Desktop/中文/ab c/abc.k"); +fn lsp_invalid_subcommand_test() { + let args = vec!["kcl-language-server".to_string(), "invalid".to_string()]; + let matches = crate::main_loop::app() + .arg_required_else_help(false) + .try_get_matches_from(args); + match matches { + Ok(_) => panic!("test failed"), + Err(e) => match e.kind() { + clap::error::ErrorKind::InvalidSubcommand => {} + _ => panic!("test failed"), + }, } } #[test] -fn goto_import_external_file_test() { - let path = PathBuf::from(".") +fn find_refs_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("src") .join("test_data") - .join("goto_import_def_test") - .join("main.k") - .canonicalize() + .join("find_refs_test"); + let mut path = root.clone(); + path.push("main.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let mut initialize_params = InitializeParams::default(); + initialize_params.workspace_folders = Some(vec![WorkspaceFolder { + uri: Url::from_file_path(root.clone()).unwrap(), + name: "test".to_string(), + }]); + let server = Project {}.server(initialize_params); + + // Wait for async build word_index_map + wait_async_compile!(); + + let url = Url::from_file_path(path).unwrap(); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: url.clone(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + + wait_async_compile!(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let r: Request = Request::new( + id.into(), + "textDocument/references".to_string(), + ReferenceParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: url.clone() }, + position: Position::new(0, 1), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context: ReferenceContext { + include_declaration: true, + }, + }, + ); + + // Send request and wait for it's response + let res = server.send_and_receive(r); + + assert_eq!( + res.result.unwrap(), + to_json(vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 4), + end: Position::new(1, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(2, 4), + end: Position::new(2, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 14), + end: Position::new(12, 15), + }, + }, + ]) .unwrap() - .display() - .to_string(); + ); +} - let _ = Command::new("kpm") - .arg("metadata") - .arg("--update") - .current_dir( - PathBuf::from(".") - .join("src") - .join("test_data") - .join("goto_import_def_test") - .canonicalize() - .unwrap() - .display() +#[test] +fn find_refs_with_file_change_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src") + .join("test_data") + .join("find_refs_test"); + let mut path = root.clone(); + path.push("main.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let mut initialize_params = InitializeParams::default(); + initialize_params.workspace_folders = Some(vec![WorkspaceFolder { + uri: Url::from_file_path(root.clone()).unwrap(), + name: "test".to_string(), + }]); + let server = Project {}.server(initialize_params); + + // Wait for async build word_index_map + wait_async_compile!(); + + let url = Url::from_file_path(path).unwrap(); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: url.clone(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + + // Mock change file content + server.notification::( + lsp_types::DidChangeTextDocumentParams { + text_document: lsp_types::VersionedTextDocumentIdentifier { + uri: url.clone(), + version: 1, + }, + content_changes: vec![lsp_types::TextDocumentContentChangeEvent { + range: None, + range_length: None, + text: r#"a = "demo" + +schema Name: + name: str + +schema Person: + n: Name + +p2 = Person { + n: Name{ + name: a + } +}"# .to_string(), - ) - .output() - .unwrap(); + }], + }, + ); + wait_async_compile!(); + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + // Mock trigger find references + let r: Request = Request::new( + id.into(), + "textDocument/references".to_string(), + ReferenceParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: url.clone() }, + position: Position::new(0, 1), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + context: ReferenceContext { + include_declaration: true, + }, + }, + ); + + // Send request and wait for it's response + let res = server.send_and_receive(r); + assert_eq!( + res.result.unwrap(), + to_json(vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(10, 14), + end: Position::new(10, 15), + }, + }, + ]) + .unwrap() + ); +} + +#[test] +fn rename_test() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src") + .join("test_data") + .join("rename_test"); + let mut path = root.clone(); + let mut main_path = root.clone(); + path.push("pkg/vars.k"); + main_path.push("main.k"); + + let path = path.to_str().unwrap(); + let src = std::fs::read_to_string(path).unwrap(); + let mut initialize_params = InitializeParams::default(); + initialize_params.workspace_folders = Some(vec![WorkspaceFolder { + uri: Url::from_file_path(root.clone()).unwrap(), + name: "test".to_string(), + }]); + let server = Project {}.server(initialize_params); + + // Wait for async build word_index_map + wait_async_compile!(); + + let url = Url::from_file_path(path).unwrap(); + let main_url = Url::from_file_path(main_path).unwrap(); + + // Mock open file + server.notification::( + lsp_types::DidOpenTextDocumentParams { + text_document: TextDocumentItem { + uri: url.clone(), + language_id: "KCL".to_string(), + version: 0, + text: src, + }, + }, + ); + wait_async_compile!(); + + let id = server.next_request_id.get(); + server.next_request_id.set(id.wrapping_add(1)); + + let new_name = String::from("Person2"); + let r: Request = Request::new( + id.into(), + "textDocument/rename".to_string(), + RenameParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: url.clone() }, + position: Position::new(0, 7), + }, + new_name: new_name.clone(), + work_done_progress_params: Default::default(), + }, + ); + + // Send request and wait for it's response + let res = server.send_and_receive(r); + let mut expect = WorkspaceEdit::default(); + expect.changes = Some(HashMap::from_iter(vec![ + ( + url.clone(), + vec![ + TextEdit { + range: Range { + start: Position::new(0, 7), + end: Position::new(0, 13), + }, + new_text: new_name.clone(), + }, + TextEdit { + range: Range { + start: Position::new(4, 7), + end: Position::new(4, 13), + }, + new_text: new_name.clone(), + }, + TextEdit { + range: Range { + start: Position::new(9, 8), + end: Position::new(9, 14), + }, + new_text: new_name.clone(), + }, + ], + ), + ( + main_url.clone(), + vec![TextEdit { + range: Range { + start: Position::new(2, 11), + end: Position::new(2, 17), + }, + new_text: new_name.clone(), + }], + ), + ])); + assert_eq!(res.result.unwrap(), to_json(expect).unwrap()); +} + +#[test] +fn compile_unit_test() { + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut test_file = path.clone(); + test_file.push("src/test_data/compile_unit/b.k"); + let file = test_file.to_str().unwrap(); - let (program, prog_scope, diags) = parse_param_and_compile( + let (prog, ..) = parse_param_and_compile( Param { - file: path.to_string(), + file: file.to_string(), + module_cache: None, + scope_cache: None, }, - None, + Some(Arc::new(RwLock::new(Default::default()))), ) .unwrap(); - - assert_eq!(diags.len(), 0); - - // test goto import file: import .pkg.schema_def - let pos = KCLPos { - filename: path.to_string(), - line: 1, - column: Some(15), - }; - let res = goto_definition(&program, &pos, &prog_scope); - assert!(res.is_some()); + // b.k is not contained in kcl.yaml but need to be contained in main pkg + assert!(prog + .pkgs + .get(MAIN_PKG) + .unwrap() + .iter() + .any(|m| m.filename == file)) } diff --git a/kclvm/tools/src/LSP/src/to_lsp.rs b/kclvm/tools/src/LSP/src/to_lsp.rs index 0fbcd9012..820a8d430 100644 --- a/kclvm/tools/src/LSP/src/to_lsp.rs +++ b/kclvm/tools/src/LSP/src/to_lsp.rs @@ -1,9 +1,11 @@ use kclvm_error::Diagnostic as KCLDiagnostic; +use kclvm_error::DiagnosticId; use kclvm_error::Level; use kclvm_error::Message; use kclvm_error::Position as KCLPos; use lsp_types::*; use ra_ap_vfs::FileId; +use serde_json::json; use crate::state::LanguageServerSnapshot; use std::{ @@ -20,22 +22,70 @@ pub fn lsp_pos(pos: &KCLPos) -> Position { } } +pub fn lsp_location(file_path: String, start: &KCLPos, end: &KCLPos) -> Option { + let uri = Url::from_file_path(file_path).ok()?; + Some(Location { + uri, + range: Range { + start: lsp_pos(start), + end: lsp_pos(end), + }, + }) +} + /// Convert KCL Message to LSP Diagnostic -fn kcl_msg_to_lsp_diags(msg: &Message, severity: DiagnosticSeverity) -> Diagnostic { - let kcl_pos = msg.pos.clone(); - let start_position = lsp_pos(&kcl_pos); - let end_position = lsp_pos(&kcl_pos); +fn kcl_msg_to_lsp_diags( + msg: &Message, + severity: DiagnosticSeverity, + related_msg: Vec, + code: Option, +) -> Diagnostic { + let range = msg.range.clone(); + let start_position = lsp_pos(&range.0); + let end_position = lsp_pos(&range.1); + + let data = msg + .suggested_replacement + .as_ref() + .map(|s_vec| { + s_vec + .iter() + .filter(|s| !s.is_empty()) + .collect::>() + }) + .filter(|v| !v.is_empty()) + .map(|s| json!({ "suggested_replacement": s })); + + let related_information = if related_msg.is_empty() { + None + } else { + Some( + related_msg + .iter() + .map(|m| DiagnosticRelatedInformation { + location: Location { + uri: Url::from_file_path(m.range.0.filename.clone()).unwrap(), + range: Range { + start: lsp_pos(&m.range.0), + end: lsp_pos(&m.range.1), + }, + }, + message: m.message.clone(), + }) + .collect(), + ) + }; Diagnostic { range: Range::new(start_position, end_position), severity: Some(severity), - code: None, + code, code_description: None, source: None, message: msg.message.clone(), - related_information: None, + related_information, tags: None, - data: None, + data, } } @@ -44,17 +94,44 @@ fn kcl_err_level_to_severity(level: Level) -> DiagnosticSeverity { Level::Error => DiagnosticSeverity::ERROR, Level::Warning => DiagnosticSeverity::WARNING, Level::Note => DiagnosticSeverity::HINT, + Level::Suggestions => DiagnosticSeverity::HINT, } } /// Convert KCL Diagnostic to LSP Diagnostics. -/// Because the diagnostic of KCL contains multiple messages, and each messages corresponds to a diagnostic of LSP, the return value is a vec pub fn kcl_diag_to_lsp_diags(diag: &KCLDiagnostic, file_name: &str) -> Vec { - diag.messages - .iter() - .filter(|msg| msg.pos.filename == file_name) - .map(|msg| kcl_msg_to_lsp_diags(msg, kcl_err_level_to_severity(diag.level))) - .collect() + let mut diags = vec![]; + for (idx, msg) in diag.messages.iter().enumerate() { + if msg.range.0.filename == file_name { + let mut related_msg = diag.messages.clone(); + related_msg.remove(idx); + let code = if diag.code.is_some() { + Some(kcl_diag_id_to_lsp_diag_code(diag.code.clone().unwrap())) + } else { + None + }; + + let lsp_diag = kcl_msg_to_lsp_diags( + msg, + kcl_err_level_to_severity(diag.level), + related_msg, + code, + ); + + diags.push(lsp_diag); + } + } + diags +} + +/// Convert KCL Diagnostic ID to LSP Diagnostics code. +/// Todo: use unique id/code instead of name() +pub(crate) fn kcl_diag_id_to_lsp_diag_code(id: DiagnosticId) -> NumberOrString { + match id { + DiagnosticId::Error(err) => NumberOrString::String(err.name()), + DiagnosticId::Warning(warn) => NumberOrString::String(warn.name()), + DiagnosticId::Suggestions => NumberOrString::String("suggestion".to_string()), + } } /// Returns the `Url` associated with the specified `FileId`. diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index 8769eec42..2dd1c0d6a 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -1,22 +1,39 @@ -use std::path::PathBuf; -use std::{fs, sync::Arc}; - use indexmap::IndexSet; -use kclvm_ast::ast::{ConfigEntry, Expr, Identifier, Node, NodeRef, Program, Stmt, Type}; +use kclvm_ast::ast::{ + ConfigEntry, Expr, Identifier, Node, NodeRef, PosTuple, Program, SchemaExpr, SchemaStmt, Stmt, + Type, +}; +use kclvm_ast::node_ref; use kclvm_ast::pos::ContainsPos; -use kclvm_config::modfile::KCL_FILE_EXTENSION; -use kclvm_driver::kpm_metadata::fetch_metadata; + +use kclvm_driver::kpm::fetch_metadata; use kclvm_driver::{get_kcl_files, lookup_compile_unit}; use kclvm_error::Diagnostic; use kclvm_error::Position as KCLPos; -use kclvm_parser::{load_program, ParseSession}; -use kclvm_sema::resolver::{resolve_program, scope::ProgramScope}; +use kclvm_parser::entry::get_dir_files; +use kclvm_parser::{load_program, KCLModuleCache, ParseSession}; +use kclvm_sema::advanced_resolver::AdvancedResolver; +use kclvm_sema::core::global_state::GlobalState; +use kclvm_sema::namer::Namer; + +use kclvm_sema::resolver::resolve_program_with_opts; +use kclvm_sema::resolver::scope::{CachedScope, ProgramScope}; + +use kclvm_span::symbol::reserved; use kclvm_utils::pkgpath::rm_external_pkg_name; -use lsp_types::Url; +use lsp_types::{Location, Position, Range, Url}; use parking_lot::{RwLock, RwLockReadGuard}; use ra_ap_vfs::{FileId, Vfs}; use serde::{de::DeserializeOwned, Serialize}; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; + +use std::{ + fs, + sync::{Arc, Mutex}, +}; + use crate::from_lsp; #[allow(unused)] @@ -51,13 +68,19 @@ pub fn get_file_name(vfs: RwLockReadGuard, file_id: FileId) -> anyhow::Resu pub(crate) struct Param { pub file: String, + pub module_cache: Option, + pub scope_cache: Option>>, } pub(crate) fn parse_param_and_compile( param: Param, vfs: Option>>, -) -> anyhow::Result<(Program, ProgramScope, IndexSet)> { - let (files, opt) = lookup_compile_unit(¶m.file, true); +) -> anyhow::Result<(Program, ProgramScope, IndexSet, GlobalState)> { + let (mut files, opt) = lookup_compile_unit(¶m.file, true); + if !files.contains(¶m.file) { + files.push(param.file.clone()); + } + let files: Vec<&str> = files.iter().map(|s| s.as_str()).collect(); let mut opt = opt.unwrap_or_default(); opt.load_plugins = true; @@ -68,11 +91,26 @@ pub(crate) fn parse_param_and_compile( opt.k_code_list.append(&mut k_code_list); } let sess = Arc::new(ParseSession::default()); - let mut program = load_program(sess.clone(), &files, Some(opt)).unwrap(); - let prog_scope = resolve_program(&mut program); + let mut program = load_program(sess.clone(), &files, Some(opt), param.module_cache)?.program; + + let prog_scope = resolve_program_with_opts( + &mut program, + kclvm_sema::resolver::Options { + merge_program: false, + type_erasure: false, + ..Default::default() + }, + param.scope_cache, + ); + + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + let node_ty_map = prog_scope.node_ty_map.clone(); + let global_state = AdvancedResolver::resolve_program(&program, gs, node_ty_map); + sess.append_diagnostic(prog_scope.handler.diagnostics.clone()); let diags = sess.1.borrow().diagnostics.clone(); - Ok((program, prog_scope, diags)) + Ok((program, prog_scope, diags, global_state)) } /// Update text with TextDocumentContentChangeEvent param @@ -107,10 +145,24 @@ fn load_files_code_from_vfs(files: &[&str], vfs: Arc>) -> anyhow::Re } None => { // In order to ensure that k_file corresponds to k_code, load the code from the file system if not exist - res.push( - fs::read_to_string(path) - .map_err(|_| anyhow::anyhow!("can't convert file to url: {}", file))?, - ); + let p: &Path = path.as_ref(); + if p.is_file() { + res.push( + fs::read_to_string(path) + .map_err(|_| anyhow::anyhow!("can't convert file to url: {}", file))?, + ); + } else if p.is_dir() { + let k_files = get_dir_files(p.to_str().unwrap(), false) + .map_err(|_| anyhow::anyhow!("can't get dir files: {} ", file))?; + for k_file in k_files { + let k_file_path = Path::new(k_file.as_str()); + res.push( + fs::read_to_string(k_file_path).map_err(|_| { + anyhow::anyhow!("can't convert file to url: {}", file) + })?, + ); + } + } } } } @@ -162,6 +214,19 @@ macro_rules! walk_list_if_contains { }; } +fn transfer_ident_names(names: Vec, pos: &PosTuple) -> Vec> { + let mut new_names = vec![]; + let mut col = pos.2; + for name in &names { + let mut name_pos = pos.clone(); + name_pos.2 = col; + name_pos.4 = col + name.len() as u64; + new_names.push(Node::node_with_pos(name.clone(), name_pos)); + col = col + name.len() as u64 + ".".len() as u64; + } + new_names +} + /// Recursively finds the inner most expr and its schema_def expr if in a schema expr(e.g., schema_attr and schema_expr) /// in a stmt according to the position. pub(crate) fn inner_most_expr_in_stmt( @@ -171,25 +236,10 @@ pub(crate) fn inner_most_expr_in_stmt( ) -> (Option>, Option>) { match stmt { Stmt::Assign(assign_stmt) => { - if let Some(ty) = &assign_stmt.type_annotation { - // build a temp identifier with string - return ( - Some(Node::node_with_pos( - Expr::Identifier(Identifier { - names: vec![ty.node.clone()], - pkgpath: "".to_string(), - ctx: kclvm_ast::ast::ExprContext::Load, - }), - ( - ty.filename.clone(), - ty.line, - ty.column, - ty.end_line, - ty.end_column, - ), - )), - schema_def, - ); + if let Some(ty) = &assign_stmt.ty { + if ty.contains_pos(pos) { + return (build_identifier_from_ty_string(ty, pos), schema_def); + } } walk_if_contains!(assign_stmt.value, pos, schema_def); @@ -257,7 +307,16 @@ pub(crate) fn inner_most_expr_in_stmt( walk_if_contains!( Node::node_with_pos( Expr::Identifier(Identifier { - names: vec![schema_stmt.name.node.clone()], + names: transfer_ident_names( + vec![schema_stmt.name.node.clone()], + &( + schema_stmt.name.filename.clone(), + schema_stmt.name.line, + schema_stmt.name.column, + schema_stmt.name.end_line, + schema_stmt.name.end_column, + ), + ), pkgpath: "".to_string(), ctx: kclvm_ast::ast::ExprContext::Load, }), @@ -295,6 +354,24 @@ pub(crate) fn inner_most_expr_in_stmt( (None, schema_def) } Stmt::SchemaAttr(schema_attr_expr) => { + walk_if_contains!( + Node::node_with_pos( + Expr::Identifier(Identifier { + names: vec![*schema_attr_expr.name.clone()], + pkgpath: "".to_string(), + ctx: kclvm_ast::ast::ExprContext::Load, + }), + ( + schema_attr_expr.name.filename.clone(), + schema_attr_expr.name.line, + schema_attr_expr.name.column, + schema_attr_expr.name.end_line, + schema_attr_expr.name.end_column, + ), + ), + pos, + schema_def + ); if schema_attr_expr.ty.contains_pos(pos) { return ( build_identifier_from_ty_string(&schema_attr_expr.ty, pos), @@ -336,7 +413,6 @@ pub(crate) fn inner_most_expr( match &expr.node { Expr::Identifier(_) => (Some(expr.clone()), schema_def), Expr::Selector(select_expr) => { - walk_if_contains_with_new_expr!(select_expr.attr, pos, schema_def, Expr::Identifier); walk_if_contains!(select_expr.value, pos, schema_def); (Some(expr.clone()), schema_def) } @@ -417,7 +493,17 @@ pub(crate) fn inner_most_expr( walk_if_contains!(starred_exor.value, pos, schema_def); (Some(expr.clone()), schema_def) } - Expr::DictComp(_) => (Some(expr.clone()), schema_def), + Expr::DictComp(dict_comp) => { + walk_option_if_contains!(dict_comp.entry.key, pos, schema_def); + walk_if_contains!(dict_comp.entry.value, pos, schema_def); + + for generator in &dict_comp.generators { + if generator.contains_pos(pos) { + walk_if_contains_with_new_expr!(generator, pos, schema_def, Expr::CompClause); + } + } + (Some(expr.clone()), schema_def) + } Expr::ConfigIfEntry(config_if_entry_expr) => { walk_if_contains!(config_if_entry_expr.if_cond, pos, schema_def); for item in &config_if_entry_expr.items { @@ -474,9 +560,15 @@ pub(crate) fn inner_most_expr( for default in &argument.defaults { walk_option_if_contains!(default, pos, schema_def); } - for ty in argument.type_annotation_list.iter().flatten() { + for ty in argument.ty_list.iter().flatten() { if ty.contains_pos(pos) { - return (Some(build_identifier_from_string(ty)), schema_def); + return ( + Some(build_identifier_from_string(&node_ref!( + ty.node.to_string(), + ty.pos() + ))), + schema_def, + ); } } (Some(expr.clone()), schema_def) @@ -514,7 +606,48 @@ fn inner_most_expr_in_config_entry( if config_entry.node.value.contains_pos(pos) { inner_most_expr(&config_entry.node.value, pos, None) } else { - (None, None) + (None, schema_def) + } +} + +pub(crate) fn is_in_schema_expr( + program: &Program, + pos: &KCLPos, +) -> Option<(Node, SchemaExpr)> { + match program.pos_to_stmt(pos) { + Some(node) => { + let parent_expr = inner_most_expr_in_stmt(&node.node, pos, None).1; + match parent_expr { + Some(expr) => match expr.node { + Expr::Schema(schema) => Some((node, schema)), + _ => None, + }, + None => None, + } + } + None => None, + } +} + +pub(crate) fn is_in_docstring( + program: &Program, + pos: &KCLPos, +) -> Option<(NodeRef, SchemaStmt)> { + match program.pos_to_stmt(pos) { + Some(node) => match node.node.clone() { + Stmt::Schema(schema) => match schema.doc { + Some(ref doc) => { + if doc.contains_pos(pos) { + Some((doc.clone(), schema)) + } else { + None + } + } + None => None, + }, + _ => None, + }, + None => None, } } @@ -522,7 +655,16 @@ fn inner_most_expr_in_config_entry( fn build_identifier_from_string(s: &NodeRef) -> Node { Node::node_with_pos( Expr::Identifier(Identifier { - names: vec![s.node.clone()], + names: transfer_ident_names( + vec![s.node.clone()], + &( + s.filename.clone(), + s.line, + s.column, + s.end_line, + s.end_column, + ), + ), pkgpath: "".to_string(), ctx: kclvm_ast::ast::ExprContext::Load, }), @@ -584,43 +726,11 @@ fn build_identifier_from_ty_string(ty: &NodeRef, pos: &KCLPos) -> Option None, + Type::Function(_) => None, } } -/// [`get_pos_from_real_path`] will return the start and the end position [`kclvm_error::Position`] -/// in an [`IndexSet`] from the [`real_path`]. -pub(crate) fn get_pos_from_real_path( - real_path: &PathBuf, -) -> IndexSet<(kclvm_error::Position, kclvm_error::Position)> { - let mut positions = IndexSet::new(); - let mut k_file = real_path.clone(); - k_file.set_extension(KCL_FILE_EXTENSION); - - if k_file.is_file() { - let start = KCLPos { - filename: k_file.to_str().unwrap().to_string(), - line: 1, - column: None, - }; - let end = start.clone(); - positions.insert((start, end)); - } else if real_path.is_dir() { - if let Ok(files) = get_kcl_files(real_path, false) { - positions.extend(files.iter().map(|file| { - let start = KCLPos { - filename: file.clone(), - line: 1, - column: None, - }; - let end = start.clone(); - (start, end) - })) - } - } - positions -} - -/// [`get_real_path_from_external`] will ask for the local path for [`pkg_name`] with subdir [`pkgpath`] from `kpm`. +/// [`get_real_path_from_external`] will ask for the local path for [`pkg_name`] with subdir [`pkgpath`]. /// If the external package, whose [`pkg_name`] is 'my_package', is stored in '\user\my_package_v0.0.1'. /// The [`pkgpath`] is 'my_package.examples.apps'. /// @@ -651,3 +761,607 @@ pub(crate) fn get_real_path_from_external( pkgpath.split('.').for_each(|s| real_path.push(s)); real_path } + +#[allow(unused)] +pub(crate) fn build_word_index_for_source_codes( + source_codes: HashMap, + prune: bool, +) -> anyhow::Result>> { + let mut index: HashMap> = HashMap::new(); + for (filepath, content) in source_codes.iter() { + for (key, values) in build_word_index_for_file_content_with_vfs( + content.to_string(), + filepath.to_string(), + prune, + ) { + index.entry(key).or_default().extend(values); + } + } + Ok(index) +} + +pub(crate) fn build_word_index_for_file_paths( + paths: &[String], + prune: bool, +) -> anyhow::Result>> { + let mut index: HashMap> = HashMap::new(); + for p in paths { + // str path to url + if let Ok(url) = Url::from_file_path(p) { + // read file content and save the word to word index + let text = read_file(p)?; + for (key, values) in build_word_index_for_file_content(text, &url, prune) { + index.entry(key).or_default().extend(values); + } + } + } + Ok(index) +} + +/// scan and build a word -> Locations index map +pub(crate) fn build_word_index( + path: String, + prune: bool, +) -> anyhow::Result>> { + let files = get_kcl_files(path.clone(), true)?; + build_word_index_for_file_paths(&files, prune) +} + +#[allow(unused)] +pub(crate) struct VirtualLocation { + pub(crate) filepath: String, + pub(crate) range: Range, +} + +pub(crate) fn build_word_index_for_file_content_with_vfs( + content: String, + filepath: String, + prune: bool, +) -> HashMap> { + let mut index: HashMap> = HashMap::new(); + let lines: Vec<&str> = content.lines().collect(); + let mut in_docstring = false; + for (li, line) in lines.into_iter().enumerate() { + if prune && !in_docstring && line.trim_start().starts_with("\"\"\"") { + in_docstring = true; + continue; + } + if prune && in_docstring { + if line.trim_end().ends_with("\"\"\"") { + in_docstring = false; + } + continue; + } + let words = line_to_words(line.to_string(), prune); + for (key, values) in words { + index + .entry(key) + .or_default() + .extend(values.iter().map(|w| VirtualLocation { + filepath: filepath.clone(), + range: Range { + start: Position::new(li as u32, w.start_col), + end: Position::new(li as u32, w.end_col), + }, + })); + } + } + index +} + +pub(crate) fn build_word_index_for_file_content( + content: String, + url: &Url, + prune: bool, +) -> HashMap> { + let mut index: HashMap> = HashMap::new(); + let lines: Vec<&str> = content.lines().collect(); + let mut in_docstring = false; + for (li, line) in lines.into_iter().enumerate() { + if prune && !in_docstring && line.trim_start().starts_with("\"\"\"") { + in_docstring = true; + continue; + } + if prune && in_docstring { + if line.trim_end().ends_with("\"\"\"") { + in_docstring = false; + } + continue; + } + let words = line_to_words(line.to_string(), prune); + for (key, values) in words { + index + .entry(key) + .or_default() + .extend(values.iter().map(|w| Location { + uri: url.clone(), + range: Range { + start: Position::new(li as u32, w.start_col), + end: Position::new(li as u32, w.end_col), + }, + })); + } + } + index +} + +pub(crate) fn word_index_add( + from: &mut HashMap>, + add: HashMap>, +) { + for (key, value) in add { + from.entry(key).or_default().extend(value); + } +} + +pub(crate) fn word_index_subtract( + from: &mut HashMap>, + remove: HashMap>, +) { + for (key, value) in remove { + for v in value { + from.entry(key.clone()).and_modify(|locations| { + locations.retain(|loc| loc != &v); + }); + } + } +} + +// Word describes an arbitrary word in a certain line including +// start position, end position and the word itself. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Word { + start_col: u32, + end_col: u32, + word: String, +} + +impl Word { + fn new(start_col: u32, end_col: u32, word: String) -> Self { + Self { + start_col, + end_col, + word, + } + } +} + +pub fn read_file(path: &String) -> anyhow::Result { + let text = std::fs::read_to_string(path)?; + Ok(text) +} + +// Split one line into identifier words. +fn line_to_words(text: String, prune: bool) -> HashMap> { + let mut result = HashMap::new(); + let mut chars: Vec = text.chars().collect(); + chars.push('\n'); + let mut start_pos = usize::MAX; + let mut continue_pos = usize::MAX - 1; // avoid overflow + let mut prev_word = false; + let mut words: Vec = vec![]; + for (i, ch) in chars.iter().enumerate() { + if prune && *ch == '#' { + break; + } + let is_id_start = rustc_lexer::is_id_start(*ch); + let is_id_continue = rustc_lexer::is_id_continue(*ch); + // If the character is valid identifier start and the previous character is not valid identifier continue, mark the start position. + if is_id_start && !prev_word { + start_pos = i; + } + if is_id_continue { + // Continue searching for the end position. + if start_pos != usize::MAX { + continue_pos = i; + } + } else { + // Find out the end position. + if continue_pos + 1 == i { + let word = chars[start_pos..i].iter().collect::().clone(); + // skip word if it should be pruned + if !prune || !reserved::is_reserved_word(&word) { + words.push(Word::new(start_pos as u32, i as u32, word)); + } + } + // Reset the start position. + start_pos = usize::MAX; + } + prev_word = is_id_continue; + } + + for w in words { + result.entry(w.word.clone()).or_insert(Vec::new()).push(w); + } + result +} + +#[cfg(test)] +mod tests { + use super::{ + build_word_index, build_word_index_for_file_content, line_to_words, word_index_add, + word_index_subtract, Word, + }; + use lsp_types::{Location, Position, Range, Url}; + use std::collections::HashMap; + use std::path::PathBuf; + #[test] + fn test_build_word_index() { + let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let mut path = root.clone(); + path.push("src/test_data/find_refs_test/main.k"); + + let url = lsp_types::Url::from_file_path(path.clone()).unwrap(); + let path = path.to_str().unwrap(); + let expect: HashMap> = vec![ + ( + "a".to_string(), + vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 1), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 4), + end: Position::new(1, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(2, 4), + end: Position::new(2, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 14), + end: Position::new(12, 15), + }, + }, + ], + ), + ( + "c".to_string(), + vec![Location { + uri: url.clone(), + range: Range { + start: Position::new(2, 0), + end: Position::new(2, 1), + }, + }], + ), + ( + "b".to_string(), + vec![Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 0), + end: Position::new(1, 1), + }, + }], + ), + ( + "n".to_string(), + vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(8, 4), + end: Position::new(8, 5), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(11, 4), + end: Position::new(11, 5), + }, + }, + ], + ), + ( + "b".to_string(), + vec![Location { + uri: url.clone(), + range: Range { + start: Position::new(1, 0), + end: Position::new(1, 1), + }, + }], + ), + ( + "Name".to_string(), + vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(4, 7), + end: Position::new(4, 11), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(8, 7), + end: Position::new(8, 11), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(11, 7), + end: Position::new(11, 11), + }, + }, + ], + ), + ( + "name".to_string(), + vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(5, 4), + end: Position::new(5, 8), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(12, 8), + end: Position::new(12, 12), + }, + }, + ], + ), + ( + "demo".to_string(), + vec![Location { + uri: url.clone(), + range: Range { + start: Position::new(0, 5), + end: Position::new(0, 9), + }, + }], + ), + ( + "Person".to_string(), + vec![ + Location { + uri: url.clone(), + range: Range { + start: Position::new(7, 7), + end: Position::new(7, 13), + }, + }, + Location { + uri: url.clone(), + range: Range { + start: Position::new(10, 5), + end: Position::new(10, 11), + }, + }, + ], + ), + ( + "p2".to_string(), + vec![Location { + uri: url.clone(), + range: Range { + start: Position::new(10, 0), + end: Position::new(10, 2), + }, + }], + ), + ] + .into_iter() + .collect(); + match build_word_index(path.to_string(), true) { + Ok(actual) => { + assert_eq!(expect, actual) + } + Err(_) => assert!(false, "build word index failed. expect: {:?}", expect), + } + } + + #[test] + fn test_word_index_add() { + let loc1 = Location { + uri: Url::parse("file:///path/to/file.k").unwrap(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 4), + }, + }; + let loc2 = Location { + uri: Url::parse("file:///path/to/file.k").unwrap(), + range: Range { + start: Position::new(1, 0), + end: Position::new(1, 4), + }, + }; + let mut from = HashMap::from([("name".to_string(), vec![loc1.clone()])]); + let add = HashMap::from([("name".to_string(), vec![loc2.clone()])]); + word_index_add(&mut from, add); + assert_eq!( + from, + HashMap::from([("name".to_string(), vec![loc1.clone(), loc2.clone()],)]) + ); + } + + #[test] + fn test_word_index_subtract() { + let loc1 = Location { + uri: Url::parse("file:///path/to/file.k").unwrap(), + range: Range { + start: Position::new(0, 0), + end: Position::new(0, 4), + }, + }; + let loc2 = Location { + uri: Url::parse("file:///path/to/file.k").unwrap(), + range: Range { + start: Position::new(1, 0), + end: Position::new(1, 4), + }, + }; + let mut from = HashMap::from([("name".to_string(), vec![loc1.clone(), loc2.clone()])]); + let remove = HashMap::from([("name".to_string(), vec![loc2.clone()])]); + word_index_subtract(&mut from, remove); + assert_eq!( + from, + HashMap::from([("name".to_string(), vec![loc1.clone()],)]) + ); + } + + #[test] + fn test_line_to_words() { + let lines = [ + "schema Person:", + "name. name again", + "some_word word !word", + "# this line is a single-line comment", + "name # end of line comment", + ]; + + let expects: Vec>> = vec![ + vec![( + "Person".to_string(), + vec![Word { + start_col: 7, + end_col: 13, + word: "Person".to_string(), + }], + )] + .into_iter() + .collect(), + vec![ + ( + "name".to_string(), + vec![ + Word { + start_col: 0, + end_col: 4, + word: "name".to_string(), + }, + Word { + start_col: 6, + end_col: 10, + word: "name".to_string(), + }, + ], + ), + ( + "again".to_string(), + vec![Word { + start_col: 11, + end_col: 16, + word: "again".to_string(), + }], + ), + ] + .into_iter() + .collect(), + vec![ + ( + "some_word".to_string(), + vec![Word { + start_col: 0, + end_col: 9, + word: "some_word".to_string(), + }], + ), + ( + "word".to_string(), + vec![ + Word { + start_col: 10, + end_col: 14, + word: "word".to_string(), + }, + Word { + start_col: 16, + end_col: 20, + word: "word".to_string(), + }, + ], + ), + ] + .into_iter() + .collect(), + HashMap::new(), + vec![( + "name".to_string(), + vec![Word { + start_col: 0, + end_col: 4, + word: "name".to_string(), + }], + )] + .into_iter() + .collect(), + ]; + for i in 0..lines.len() { + let got = line_to_words(lines[i].to_string(), true); + assert_eq!(expects[i], got) + } + } + + #[test] + fn test_build_word_index_for_file_content() { + let content = r#"schema Person: + """ + This is a docstring. + Person is a schema which defines a person's name and age. + """ + name: str # name must not be empty + # age is a positive integer + age: int +"#; + let mock_url = Url::parse("file:///path/to/file.k").unwrap(); + let expects: HashMap> = vec![ + ( + "Person".to_string(), + vec![Location { + uri: mock_url.clone(), + range: Range { + start: Position::new(0, 7), + end: Position::new(0, 13), + }, + }], + ), + ( + "name".to_string(), + vec![Location { + uri: mock_url.clone(), + range: Range { + start: Position::new(5, 4), + end: Position::new(5, 8), + }, + }], + ), + ( + "age".to_string(), + vec![Location { + uri: mock_url.clone(), + range: Range { + start: Position::new(7, 4), + end: Position::new(7, 7), + }, + }], + ), + ] + .into_iter() + .collect(); + + let got = build_word_index_for_file_content(content.to_string(), &mock_url.clone(), true); + assert_eq!(expects, got) + } +} diff --git a/kclvm/tools/src/fix/LICENSE b/kclvm/tools/src/fix/LICENSE new file mode 100644 index 000000000..989e2c59e --- /dev/null +++ b/kclvm/tools/src/fix/LICENSE @@ -0,0 +1,201 @@ +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. \ No newline at end of file diff --git a/kclvm/tools/src/fix/mod.rs b/kclvm/tools/src/fix/mod.rs new file mode 100644 index 000000000..8d9b8abef --- /dev/null +++ b/kclvm/tools/src/fix/mod.rs @@ -0,0 +1,171 @@ +mod replace; +#[cfg(test)] +mod tests; +use anyhow::{ensure, Error}; +use kclvm_error::{diagnostic::Range as KCLRange, Diagnostic}; +use std::collections::HashMap; +use std::fs; +use std::ops::Range; + +/// A structure for handling code fixes. +pub struct CodeFix { + data: replace::Data, +} + +impl CodeFix { + pub fn new(s: &str) -> CodeFix { + CodeFix { + data: replace::Data::new(s.as_bytes()), + } + } + + pub fn apply(&mut self, suggestion: &Suggestion) -> Result<(), Error> { + let snippet = &suggestion.replacement.snippet; + self.data.replace_range( + snippet.range.start, + snippet.range.end.saturating_sub(1), + suggestion.replacement.replacement.as_bytes(), + )?; + Ok(()) + } + + pub fn finish(&self) -> Result { + Ok(String::from_utf8(self.data.to_vec())?) + } +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +/// An error/warning and possible solutions for fixing it +pub struct Suggestion { + pub message: String, + pub replacement: Replacement, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct Replacement { + pub snippet: Snippet, + pub replacement: String, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct Snippet { + pub file_name: String, + pub range: Range, +} + +pub fn diag_to_suggestion( + diag: Diagnostic, + files: &mut HashMap, +) -> anyhow::Result> { + let mut suggestions = vec![]; + + for msg in &diag.messages { + let replacements = msg + .suggested_replacement + .clone() + .unwrap_or_else(|| vec!["".to_string()]); + let replacement_str = replacements.first().cloned().unwrap_or_default(); + + let file_name = msg.range.0.filename.clone(); + let src = match files.get(&file_name) { + Some(src) => src.clone(), + None => { + let src = fs::read_to_string(&file_name).expect("Unable to read file"); + files.insert(file_name.clone(), src.clone()); + src + } + }; + + suggestions.push(Suggestion { + message: msg.message.clone(), + replacement: Replacement { + snippet: Snippet { + file_name, + range: text_range(src.as_str(), &msg.range)?, + }, + replacement: replacement_str, + }, + }); + } + Ok(suggestions) +} + +fn is_newline_at_index(s: &str, index: usize) -> bool { + let length = s.len(); + + if index >= length { + return false; + } + + let bytes = s.as_bytes(); + + if bytes[index] == b'\n' { + return true; + } + #[cfg(target_os = "windows")] + if bytes[index] == b'\r' && index + 1 < length && bytes[index + 1] == b'\n' { + return true; + } + + false +} + +pub(crate) fn text_range(text: &str, range: &KCLRange) -> anyhow::Result, Error> { + let mut lines_length = vec![]; + let lines_text: Vec<&str> = text.split('\n').collect(); + let mut pre_total_length = 0; + + for line in &lines_text { + lines_length.push(pre_total_length); + pre_total_length += line.len() + "\n".len(); + } + + ensure!( + (range.0.line as usize) <= lines_length.len() + && (range.1.line as usize) <= lines_length.len() + ); + + // The KCL diagnostic line is 1-based and the column is 0-based. + let start = + lines_length.get(range.0.line as usize - 1).unwrap() + range.0.column.unwrap_or(0) as usize; + let mut end = + lines_length.get(range.1.line as usize - 1).unwrap() + range.1.column.unwrap_or(0) as usize; + + if is_newline_at_index(text, end) { + if cfg!(windows) { + end += "\r\n".len() + } else { + end += "\n".len() + } + } + + Ok(Range { start, end }) +} + +pub fn fix(diags: Vec) -> Result<(), Error> { + let mut suggestions = vec![]; + let mut source_code = HashMap::new(); + for diag in diags { + suggestions.extend(diag_to_suggestion(diag, &mut source_code)?) + } + + let mut files = HashMap::new(); + for suggestion in suggestions { + let file = suggestion.replacement.snippet.file_name.clone(); + files.entry(file).or_insert_with(Vec::new).push(suggestion); + } + + for (source_file, suggestions) in &files { + println!("fix file: {:?}", source_file); + let source = fs::read_to_string(source_file)?; + let mut fix = CodeFix::new(&source); + for suggestion in suggestions.iter() { + if let Err(e) = fix.apply(suggestion) { + eprintln!("Failed to apply suggestion to {}: {}", source_file, e); + } + } + let fixes = fix.finish()?; + fs::write(source_file, fixes)?; + } + Ok(()) +} diff --git a/kclvm/tools/src/fix/replace.rs b/kclvm/tools/src/fix/replace.rs new file mode 100644 index 000000000..4bc4d5c31 --- /dev/null +++ b/kclvm/tools/src/fix/replace.rs @@ -0,0 +1,274 @@ +//! The following code and tests are copied and modified from +//! [rust-lang/rustfix](https://github.com/rust-lang/rustfix/blob/master/src/replace.rs) +//! +//! A small module giving you a simple container that allows easy and cheap +//! replacement of parts of its content, with the ability to prevent changing +//! the same parts multiple times. + +use anyhow::{anyhow, ensure, Error}; +use std::rc::Rc; + +#[derive(Debug, Clone, PartialEq, Eq)] +enum State { + Initial, + Replaced(Rc<[u8]>), + Inserted(Rc<[u8]>), +} + +impl State { + fn is_inserted(&self) -> bool { + matches!(*self, State::Inserted(..)) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Span { + /// Start of this span in parent data + start: usize, + /// up to end including + end: usize, + data: State, +} + +/// A container that allows easily replacing chunks of its data +#[derive(Debug, Clone, Default)] +pub struct Data { + original: Vec, + parts: Vec, +} + +impl Data { + /// Create a new data container from a slice of bytes + pub fn new(data: &[u8]) -> Self { + Data { + original: data.into(), + parts: vec![Span { + data: State::Initial, + start: 0, + end: data.len().saturating_sub(1), + }], + } + } + + /// Render this data as a vector of bytes + pub fn to_vec(&self) -> Vec { + if self.original.is_empty() { + return Vec::new(); + } + + self.parts.iter().fold(Vec::new(), |mut acc, d| { + match d.data { + State::Initial => acc.extend_from_slice(&self.original[d.start..=d.end]), + State::Replaced(ref d) | State::Inserted(ref d) => acc.extend_from_slice(d), + }; + acc + }) + } + + /// Replace a chunk of data with the given slice, erroring when this part + /// was already changed previously. + pub fn replace_range( + &mut self, + from: usize, + up_to_and_including: usize, + data: &[u8], + ) -> Result<(), Error> { + let exclusive_end = up_to_and_including + 1; + + ensure!( + from <= exclusive_end, + "Invalid range {}...{}, start is larger than end", + from, + up_to_and_including + ); + + ensure!( + up_to_and_including <= self.original.len(), + "Invalid range {}...{} given, original data is only {} byte long", + from, + up_to_and_including, + self.original.len() + ); + + let insert_only = from == exclusive_end; + + // Since we error out when replacing an already replaced chunk of data, + // we can take some shortcuts here. For example, there can be no + // overlapping replacements -- we _always_ split a chunk of 'initial' + // data into three[^empty] parts, and there can't ever be two 'initial' + // parts touching. + // + // [^empty]: Leading and trailing ones might be empty if we replace + // the whole chunk. As an optimization and without loss of generality we + // don't add empty parts. + let new_parts = { + let index_of_part_to_split = self + .parts + .iter() + .position(|p| { + !p.data.is_inserted() && p.start <= from && p.end >= up_to_and_including + }) + .ok_or_else(|| { + anyhow!( + "Could not replace range {}...{} in file \ + -- maybe parts of it were already replaced?", + from, + up_to_and_including + ) + })?; + + let part_to_split = &self.parts[index_of_part_to_split]; + + // If this replacement matches exactly the part that we would + // otherwise split then we ignore this for now. This means that you + // can replace the exact same range with the exact same content + // multiple times and we'll process and allow it. + if part_to_split.start == from && part_to_split.end == up_to_and_including { + if let State::Replaced(ref replacement) = part_to_split.data { + if &**replacement == data { + return Ok(()); + } + } + } + + ensure!( + part_to_split.data == State::Initial, + "Cannot replace slice of data that was already replaced" + ); + + let mut new_parts = Vec::with_capacity(self.parts.len() + 2); + + // Previous parts + if let Some(ps) = self.parts.get(..index_of_part_to_split) { + new_parts.extend_from_slice(ps); + } + + // Keep initial data on left side of part + if from > part_to_split.start { + new_parts.push(Span { + start: part_to_split.start, + end: from.saturating_sub(1), + data: State::Initial, + }); + } + + // New part + new_parts.push(Span { + start: from, + end: up_to_and_including, + data: if insert_only { + State::Inserted(data.into()) + } else { + State::Replaced(data.into()) + }, + }); + + // Keep initial data on right side of part + if up_to_and_including < part_to_split.end { + new_parts.push(Span { + start: up_to_and_including + 1, + end: part_to_split.end, + data: State::Initial, + }); + } + + // Following parts + if let Some(ps) = self.parts.get(index_of_part_to_split + 1..) { + new_parts.extend_from_slice(ps); + } + + new_parts + }; + + self.parts = new_parts; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + fn str(i: &[u8]) -> &str { + ::std::str::from_utf8(i).unwrap() + } + + #[test] + fn replace_some_stuff() { + let mut d = Data::new(b"foo bar baz"); + d.replace_range(4, 6, b"lol").unwrap(); + assert_eq!("foo lol baz", str(&d.to_vec())); + } + + #[test] + fn replace_a_single_char() { + let mut d = Data::new(b"let y = true;"); + d.replace_range(4, 4, b"mut y").unwrap(); + assert_eq!("let mut y = true;", str(&d.to_vec())); + } + + #[test] + fn replace_multiple_lines() { + let mut d = Data::new(b"lorem\nipsum\ndolor"); + + d.replace_range(6, 10, b"lol").unwrap(); + assert_eq!("lorem\nlol\ndolor", str(&d.to_vec())); + + d.replace_range(12, 16, b"lol").unwrap(); + assert_eq!("lorem\nlol\nlol", str(&d.to_vec())); + } + + #[test] + fn replace_multiple_lines_with_insert_only() { + let mut d = Data::new(b"foo!"); + + d.replace_range(3, 2, b"bar").unwrap(); + assert_eq!("foobar!", str(&d.to_vec())); + + d.replace_range(0, 2, b"baz").unwrap(); + assert_eq!("bazbar!", str(&d.to_vec())); + + d.replace_range(3, 3, b"?").unwrap(); + assert_eq!("bazbar?", str(&d.to_vec())); + } + + #[test] + fn replace_invalid_range() { + let mut d = Data::new(b"foo!"); + + assert!(d.replace_range(2, 0, b"bar").is_err()); + assert!(d.replace_range(0, 2, b"bar").is_ok()); + } + + #[test] + fn empty_to_vec_roundtrip() { + let s = ""; + assert_eq!(s.as_bytes(), Data::new(s.as_bytes()).to_vec().as_slice()); + } + + #[test] + #[should_panic(expected = "Cannot replace slice of data that was already replaced")] + fn replace_overlapping_stuff_errs() { + let mut d = Data::new(b"foo bar baz"); + + d.replace_range(4, 6, b"lol").unwrap(); + assert_eq!("foo lol baz", str(&d.to_vec())); + + d.replace_range(4, 6, b"lol2").unwrap(); + } + + #[test] + #[should_panic(expected = "original data is only 3 byte long")] + fn broken_replacements() { + let mut d = Data::new(b"foo"); + d.replace_range(4, 7, b"lol").unwrap(); + } + + #[test] + fn replace_same_twice() { + let mut d = Data::new(b"foo"); + d.replace_range(0, 0, b"b").unwrap(); + d.replace_range(0, 0, b"b").unwrap(); + assert_eq!("boo", str(&d.to_vec())); + } +} diff --git a/kclvm/tools/src/fix/test_data/fix_import.k b/kclvm/tools/src/fix/test_data/fix_import.k new file mode 100644 index 000000000..4632b86c3 --- /dev/null +++ b/kclvm/tools/src/fix/test_data/fix_import.k @@ -0,0 +1,5 @@ +import regex +import math +import regex + +a = math.pow(1, 1) \ No newline at end of file diff --git a/kclvm/tools/src/fix/test_data/unused_import.k b/kclvm/tools/src/fix/test_data/unused_import.k new file mode 100644 index 000000000..02202730e --- /dev/null +++ b/kclvm/tools/src/fix/test_data/unused_import.k @@ -0,0 +1 @@ +import math \ No newline at end of file diff --git a/kclvm/tools/src/fix/tests.rs b/kclvm/tools/src/fix/tests.rs new file mode 100644 index 000000000..a76afbe8a --- /dev/null +++ b/kclvm/tools/src/fix/tests.rs @@ -0,0 +1,42 @@ +use std::fs; + +use crate::lint::lint_files; + +use super::fix; + +#[test] +fn test_lint() { + let (errors, warnings) = lint_files( + &[ + "./src/fix/test_data/fix_import.k", + "./src/fix/test_data/unused_import.k", + ], + None, + ); + assert_eq!(errors.len(), 0); + let mut diags = vec![]; + diags.extend(warnings); + + match fix(diags) { + Ok(_) => { + let src = fs::read_to_string("./src/fix/test_data/fix_import.k").unwrap(); + #[cfg(target_os = "windows")] + assert_eq!(src, "import math\r\n\r\na = math.pow(1, 1)".to_string()); + #[cfg(not(target_os = "windows"))] + assert_eq!(src, "import math\n\na = math.pow(1, 1)".to_string()); + fs::write( + "./src/fix/test_data/fix_import.k", + r#"import regex +import math +import regex + +a = math.pow(1, 1)"#, + ) + .unwrap(); + let src = fs::read_to_string("./src/fix/test_data/unused_import.k").unwrap(); + assert_eq!(src, "".to_string()); + fs::write("./src/fix/test_data/unused_import.k", r#"import math"#).unwrap(); + } + Err(e) => panic!("fix failed: {:?}", e), + } +} diff --git a/kclvm/tools/src/format/mod.rs b/kclvm/tools/src/format/mod.rs index a7f382ff7..9d81901e9 100644 --- a/kclvm/tools/src/format/mod.rs +++ b/kclvm/tools/src/format/mod.rs @@ -5,12 +5,12 @@ //! The basic principle is to call the [kclvm_parser::parse_file] function to parse the //! AST Module, and then use the AST printer [kclvm_tools::printer::print_ast_module] //! to print it as source code string. -use anyhow::{anyhow, Result}; +use anyhow::Result; use kclvm_ast_pretty::print_ast_module; use kclvm_driver::get_kcl_files; use std::path::Path; -use kclvm_parser::parse_file; +use kclvm_parser::{parse_file, parse_file_force_errors}; #[cfg(test)] mod tests; @@ -18,10 +18,12 @@ mod tests; /// FormatOptions contains two options: /// - is_stdout: whether to output the formatted result to stdout. /// - recursively: whether to recursively traverse a folder and format all KCL files in it. +/// - omit_errors: whether to omit the parse errors when format the KCL code. #[derive(Debug, Default)] pub struct FormatOptions { pub is_stdout: bool, pub recursively: bool, + pub omit_errors: bool, } /// Formats kcl file or directory path contains kcl files and @@ -69,7 +71,7 @@ pub fn format>(path: P, opts: &FormatOptions) -> Result Result { let src = std::fs::read_to_string(file)?; - let (source, is_formatted) = format_source(&src)?; + let (source, is_formatted) = format_source(file, &src, opts)?; if opts.is_stdout { println!("{}", source); } else { @@ -80,10 +82,11 @@ pub fn format_file(file: &str, opts: &FormatOptions) -> Result { /// Formats a code source and returns the formatted source and /// whether the source is changed. -pub fn format_source(src: &str) -> Result<(String, bool)> { - let module = match parse_file("", Some(src.to_string())) { - Ok(module) => module, - Err(err) => return Err(anyhow!("{}", err)), +pub fn format_source(file: &str, src: &str, opts: &FormatOptions) -> Result<(String, bool)> { + let module = if opts.omit_errors { + parse_file(file, Some(src.to_string()))?.module + } else { + parse_file_force_errors(file, Some(src.to_string()))? }; let formatted_src = print_ast_module(&module); let is_formatted = src != formatted_src; diff --git a/kclvm/tools/src/format/test_data/format_data/breakline.golden b/kclvm/tools/src/format/test_data/format_data/breakline.golden index eb95f0d96..6b23475a3 100644 --- a/kclvm/tools/src/format/test_data/format_data/breakline.golden +++ b/kclvm/tools/src/format/test_data/format_data/breakline.golden @@ -1,4 +1,5 @@ import math + schema Base: name: str diff --git a/kclvm/tools/src/format/test_data/format_data/codelayout.golden b/kclvm/tools/src/format/test_data/format_data/codelayout.golden index ca0a5210f..2e5db3977 100644 --- a/kclvm/tools/src/format/test_data/format_data/codelayout.golden +++ b/kclvm/tools/src/format/test_data/format_data/codelayout.golden @@ -1,4 +1,5 @@ import math as alias_math + schema Person(Base): # inline comment name: str diff --git a/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.golden b/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.golden new file mode 100644 index 000000000..fea668c1a --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.golden @@ -0,0 +1,7 @@ +import a + +schema A: + name: str = a.name + +A {} +# Break one blank line between different statements e.g., import, schema and expression statements. diff --git a/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.input b/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.input new file mode 100644 index 000000000..60d9818b9 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/different_stmts_line_breaks.input @@ -0,0 +1,5 @@ +import a +schema A: + name: str = a.name +A{} +# Break one blank line between different statements e.g., import, schema and expression statements. diff --git a/kclvm/tools/src/format/test_data/format_data/import.golden b/kclvm/tools/src/format/test_data/format_data/import.golden index 3b4302338..5a9a8ae8d 100644 --- a/kclvm/tools/src/format/test_data/format_data/import.golden +++ b/kclvm/tools/src/format/test_data/format_data/import.golden @@ -3,4 +3,5 @@ import b import c import d import e as e + a = 1 diff --git a/kclvm/tools/src/format/test_data/format_data/import_only.golden b/kclvm/tools/src/format/test_data/format_data/import_only.golden new file mode 100644 index 000000000..c2d4d9515 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/import_only.golden @@ -0,0 +1,2 @@ +import math +import abc diff --git a/kclvm/tools/src/format/test_data/format_data/import_only.input b/kclvm/tools/src/format/test_data/format_data/import_only.input new file mode 100644 index 000000000..598699503 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/import_only.input @@ -0,0 +1,2 @@ +import math +import abc \ No newline at end of file diff --git a/kclvm/tools/src/format/test_data/format_data/lambda.golden b/kclvm/tools/src/format/test_data/format_data/lambda.golden index b63f99de6..cb5410afe 100644 --- a/kclvm/tools/src/format/test_data/format_data/lambda.golden +++ b/kclvm/tools/src/format/test_data/format_data/lambda.golden @@ -1,18 +1,13 @@ f0 = lambda { 1 + 1 - } f1 = lambda x: int, y: int -> int { x + y - } f2 = lambda { lambda x { lambda y { y + 1 - } - } - } diff --git a/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.golden b/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.golden new file mode 100644 index 000000000..792e3ac36 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.golden @@ -0,0 +1,6 @@ +import a.b.c +import d + +schema A: + name: str + diff --git a/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.input b/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.input new file mode 100644 index 000000000..7d3da4d41 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/layout_import_stmt.input @@ -0,0 +1,4 @@ +import a.b.c +import d +schema A: + name: str \ No newline at end of file diff --git a/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.golden b/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.golden new file mode 100644 index 000000000..a71205411 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.golden @@ -0,0 +1,20 @@ +dict = { + "key": "value" +} + +dict2 = {"key": "value"} + +list = [ + first + second +] + +list2 = [first, second] + +expr = Person { + name: "Alice" +} + +expr2 = Person {name: "Alice"} + +# It's both acceptable to write each entry in the list/dict/schema expr without line breaks, or separate each entry with one line break. diff --git a/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.input b/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.input new file mode 100644 index 000000000..a71205411 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/list_dict_schema_expr.input @@ -0,0 +1,20 @@ +dict = { + "key": "value" +} + +dict2 = {"key": "value"} + +list = [ + first + second +] + +list2 = [first, second] + +expr = Person { + name: "Alice" +} + +expr2 = Person {name: "Alice"} + +# It's both acceptable to write each entry in the list/dict/schema expr without line breaks, or separate each entry with one line break. diff --git a/kclvm/tools/src/format/test_data/format_data/schema.golden b/kclvm/tools/src/format/test_data/format_data/schema.golden index 901994fb1..b28d44bcd 100644 --- a/kclvm/tools/src/format/test_data/format_data/schema.golden +++ b/kclvm/tools/src/format/test_data/format_data/schema.golden @@ -1,4 +1,5 @@ import math + mixin XXMixin: nameVar: str diff --git a/kclvm/tools/src/format/test_data/format_data/type_alias.golden b/kclvm/tools/src/format/test_data/format_data/type_alias.golden index 7bc0ef6b1..87616fb37 100644 --- a/kclvm/tools/src/format/test_data/format_data/type_alias.golden +++ b/kclvm/tools/src/format/test_data/format_data/type_alias.golden @@ -4,4 +4,4 @@ schema Person: type PersonOther = Person type Int = int -type UnionType = int|float|str +type UnionType = int | float | str diff --git a/kclvm/tools/src/format/test_data/format_data/union_types.golden b/kclvm/tools/src/format/test_data/format_data/union_types.golden new file mode 100644 index 000000000..b4f853579 --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/union_types.golden @@ -0,0 +1,11 @@ +workloadType: "Deployment" | "StatefulSet" = "Deployment" +ServiceType: "LoadBalance" | "ClusterIP" = "LoadBalance" +abc: A | B | C = A {} + +schema Server: + [name: str | int]: str | int + workloadType: "Deployment" | "StatefulSet" + dict: {str:str | int} + +type some_alias = "abc" | "def" | {str | int:} +# In union types, there should be one and only one whitespace both before and after the union operator | diff --git a/kclvm/tools/src/format/test_data/format_data/union_types.input b/kclvm/tools/src/format/test_data/format_data/union_types.input new file mode 100644 index 000000000..03d8b64fd --- /dev/null +++ b/kclvm/tools/src/format/test_data/format_data/union_types.input @@ -0,0 +1,11 @@ +workloadType: "Deployment"|"StatefulSet" = "Deployment" +ServiceType: "LoadBalance" |"ClusterIP" = "LoadBalance" +abc: A|B|C = A{} + +schema Server: + [name: str|int]: str|int + workloadType: "Deployment"| "StatefulSet" + dict: {str: str|int} + +type some_alias = "abc"|"def"|{str|int:} +# In union types, there should be one and only one whitespace both before and after the union operator | diff --git a/kclvm/tools/src/format/tests.rs b/kclvm/tools/src/format/tests.rs index bf224a071..a76abc70f 100644 --- a/kclvm/tools/src/format/tests.rs +++ b/kclvm/tools/src/format/tests.rs @@ -1,11 +1,11 @@ use super::*; -use kclvm_parser::parse_file; +use kclvm_parser::parse_file_force_errors; use pretty_assertions::assert_eq; use walkdir::WalkDir; const FILE_INPUT_SUFFIX: &str = ".input"; const FILE_OUTPUT_SUFFIX: &str = ".golden"; -const TEST_CASES: &[&str; 18] = &[ +const TEST_CASES: &[&str; 22] = &[ "assert", "check", "blankline", @@ -16,6 +16,7 @@ const TEST_CASES: &[&str; 18] = &[ "comp_for", "empty", "import", + "import_only", "indent", "inline_comment", "lambda", @@ -24,18 +25,22 @@ const TEST_CASES: &[&str; 18] = &[ "string", "type_alias", "unary", + "union_types", + "layout_import_stmt", + "different_stmts_line_breaks", + // "list_dict_schema_expr", ]; fn read_data(data_name: &str) -> (String, String) { - let src = std::fs::read_to_string(&format!( + let src = std::fs::read_to_string(format!( "./src/format/test_data/format_data/{}{}", data_name, FILE_INPUT_SUFFIX )) .unwrap(); ( - format_source(&src).unwrap().0, - std::fs::read_to_string(&format!( + format_source("", &src, &Default::default()).unwrap().0, + std::fs::read_to_string(format!( "./src/format/test_data/format_data/{}{}", data_name, FILE_OUTPUT_SUFFIX )) @@ -76,6 +81,7 @@ fn test_format_with_stdout_option() { let opts = FormatOptions { is_stdout: true, recursively: false, + omit_errors: false, }; let changed_files = format("./src/format/test_data/format_path_data/if.k", &opts).unwrap(); assert_eq!(changed_files.len(), 1); @@ -84,11 +90,89 @@ fn test_format_with_stdout_option() { let opts = FormatOptions { is_stdout: true, recursively: true, + omit_errors: false, }; let changed_files = format("./src/format/test_data/format_path_data/", &opts).unwrap(); assert_eq!(changed_files.len(), 2); } +#[test] +fn test_format_with_omit_error_option() { + let opts = FormatOptions { + is_stdout: false, + recursively: false, + omit_errors: true, + }; + let cases = [ + ( + r#"x = { +a: { +b: 1 +c: 2 +} +d: 3 +} +"#, + r#"x = { + a: { + b: 1 + c: 2 + } + d: 3 +} +"#, + ), + ( + r#"x = { +a: { + b: 1 + c: 2 +} +} +"#, + r#"x = { + a: { + b: 1 + c: 2 + } +} +"#, + ), + ( + r#"x = { + a: 1 + b: 2 + c: 3 +} +"#, + r#"x = { + a: 1 + b: 2 + c: 3 +} +"#, + ), + ( + r#"x = { + a: 1 + b: 2 + c: 3 +} +"#, + r#"x = { + a: 1 + b: 2 + c: 3 +} +"#, + ), + ]; + for (code, expected_code) in cases { + let (actual_code, _) = format_source("error_indent.k", code, &opts).unwrap(); + assert_eq!(actual_code, expected_code); + } +} + #[test] fn test_format_integration_konfig() -> Result<()> { let konfig_path = Path::new(".") @@ -98,21 +182,22 @@ fn test_format_integration_konfig() -> Result<()> { .parent() .unwrap() .join("test") + .join("integration") .join("konfig"); let files = get_files(konfig_path, true, true, ".k"); for file in &files { // Skip test and hidden files. - if file.ends_with("_test.k") || file.starts_with("_") { + if file.ends_with("_test.k") || file.starts_with('_') { continue; } assert!( - parse_file(file, None).is_ok(), + parse_file_force_errors(file, None).is_ok(), "file {} test format failed", file ); let src = std::fs::read_to_string(file)?; - let (formatted_src, _) = format_source(&src)?; - let parse_result = parse_file("test.k", Some(formatted_src.clone() + "\n")); + let (formatted_src, _) = format_source("", &src, &Default::default())?; + let parse_result = parse_file_force_errors("test.k", Some(formatted_src.clone() + "\n")); assert!( parse_result.is_ok(), "file {} test format failed, the formatted source is\n{}\n the parse error is\n{}", diff --git a/kclvm/tools/src/lib.rs b/kclvm/tools/src/lib.rs index 6ec98222f..703c3b406 100644 --- a/kclvm/tools/src/lib.rs +++ b/kclvm/tools/src/lib.rs @@ -1,4 +1,6 @@ +pub mod fix; pub mod format; pub mod lint; +pub mod testing; pub mod util; pub mod vet; diff --git a/kclvm/tools/src/lint/mod.rs b/kclvm/tools/src/lint/mod.rs index 7f885e442..4a0b66fb5 100644 --- a/kclvm/tools/src/lint/mod.rs +++ b/kclvm/tools/src/lint/mod.rs @@ -4,7 +4,7 @@ use indexmap::IndexSet; use kclvm_error::{Diagnostic, Handler}; use kclvm_parser::{load_program, LoadProgramOptions, ParseSession}; use kclvm_runtime::PanicInfo; -use kclvm_sema::resolver::resolve_program; +use kclvm_sema::resolver::resolve_program_with_opts; #[cfg(test)] mod tests; @@ -45,11 +45,18 @@ mod tests; /// Diagnostic { /// level: Warning /// messages: [Message { -/// pos: Position { -/// filename: test.k, -/// line: 1, -/// column: None, -/// }, +/// range: ( +/// Position { +/// filename: test.k, +/// line: 1, +/// column: None, +/// }, +/// Position { +/// filename: test.k, +/// line: 1, +/// column: None, +/// }, +/// ), /// style: Style::Line, /// message: "Module 'math' imported but unused", /// note: Some("Consider removing this statement".to_string()), @@ -64,14 +71,27 @@ pub fn lint_files( ) -> (IndexSet, IndexSet) { // Parse AST program. let sess = Arc::new(ParseSession::default()); - let mut program = match load_program(sess.clone(), files, opts) { - Ok(p) => p, + let mut opts = opts.unwrap_or_default(); + opts.load_plugins = true; + let mut program = match load_program(sess.clone(), files, Some(opts), None) { + Ok(p) => p.program, Err(err_str) => { return Handler::default() - .add_panic_info(&PanicInfo::from(err_str)) + .add_panic_info(&PanicInfo::from(err_str.to_string())) .classification(); } }; - sess.append_diagnostic(resolve_program(&mut program).handler.diagnostics) - .classification() + sess.append_diagnostic( + resolve_program_with_opts( + &mut program, + kclvm_sema::resolver::Options { + merge_program: false, + ..Default::default() + }, + None, + ) + .handler + .diagnostics, + ) + .classification() } diff --git a/kclvm/tools/src/lint/test_data/lint.k b/kclvm/tools/src/lint/test_data/lint.k index 41436a31a..9e2fc7327 100644 --- a/kclvm/tools/src/lint/test_data/lint.k +++ b/kclvm/tools/src/lint/test_data/lint.k @@ -2,6 +2,7 @@ import import_test.a # UnusedImport import import_test.a # ReImport import abc + schema Person: name: str age: int diff --git a/kclvm/tools/src/lint/test_data/unused_check_for_each_file/a.k b/kclvm/tools/src/lint/test_data/unused_check_for_each_file/a.k new file mode 100644 index 000000000..02202730e --- /dev/null +++ b/kclvm/tools/src/lint/test_data/unused_check_for_each_file/a.k @@ -0,0 +1 @@ +import math \ No newline at end of file diff --git a/kclvm/tools/src/lint/test_data/unused_check_for_each_file/b.k b/kclvm/tools/src/lint/test_data/unused_check_for_each_file/b.k new file mode 100644 index 000000000..b59d572e1 --- /dev/null +++ b/kclvm/tools/src/lint/test_data/unused_check_for_each_file/b.k @@ -0,0 +1,2 @@ +import math +a = math.pow(1, 1) \ No newline at end of file diff --git a/kclvm/tools/src/lint/tests.rs b/kclvm/tools/src/lint/tests.rs index 883e58bc7..767f2fecb 100644 --- a/kclvm/tools/src/lint/tests.rs +++ b/kclvm/tools/src/lint/tests.rs @@ -8,6 +8,7 @@ fn test_lint() { "Importstmt should be placed at the top of the module", "Module 'a' is reimported multiple times", "Module 'import_test.a' imported but unused", + "Module 'import_test.a' imported but unused", "Module 'abc' imported but unused", ]; assert_eq!(warnings.len(), msgs.len()); @@ -23,10 +24,47 @@ fn test_lint() { let msgs = [ "pkgpath abc not found in the program", + "try 'kcl mod add abc' to download the package not found", + "find more package on 'https://artifacthub.io'", &format!("Cannot find the module abc from {}", path.to_str().unwrap()), ]; - assert_eq!(errors.len(), msgs.len()); + assert_eq!( + errors.len(), + msgs.len(), + "{:?}", + errors + .iter() + .map(|e| e.messages[0].message.clone()) + .collect::>() + ); for (diag, m) in errors.iter().zip(msgs.iter()) { assert_eq!(diag.messages[0].message, m.to_string()); } } + +#[test] +fn test_unused_check_for_each_file() { + let (errs, warnings) = lint_files( + &[ + "./src/lint/test_data/unused_check_for_each_file/a.k", + "./src/lint/test_data/unused_check_for_each_file/b.k", + ], + None, + ); + assert_eq!(errs.len(), 0); + assert_eq!(warnings.len(), 1); + assert_eq!( + warnings[0].messages[0].message, + "Module 'math' imported but unused".to_string() + ); + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("src"); + path.push("lint"); + path.push("test_data"); + path.push("unused_check_for_each_file"); + path.push("a.k"); + assert_eq!( + warnings[0].messages[0].range.0.filename, + path.to_str().unwrap().to_string() + ); +} diff --git a/kclvm/tools/src/testing/mod.rs b/kclvm/tools/src/testing/mod.rs new file mode 100644 index 000000000..88aa328fa --- /dev/null +++ b/kclvm/tools/src/testing/mod.rs @@ -0,0 +1,58 @@ +//! [kclvm_tools::testing] module mainly contains some functions of language testing tool. +//! +//! The basic principle of the testing tool is to search for test files in the KCL package +//! that have the suffix "_test.k" and do not start with "_". These test files will be regard +//! as test suites. Within these files, any lambda literals starting with "test_" will be +//! considered as test cases, but these lambda functions should not have any parameters. +//! To perform the testing, the tool compiles the test suite file and its dependencies into an +//! [kclvm_runner::Artifact], which is regard as a new compilation entry point. Then, +//! it executes each test case separately and collects information about the test cases, +//! such as the execution time and whether the test passes or fails. +pub use crate::testing::suite::{load_test_suites, TestSuite}; +use anyhow::{Error, Result}; +use indexmap::IndexMap; +use kclvm_runner::ExecProgramArgs; +use std::time::Duration; + +mod suite; + +#[cfg(test)] +mod tests; + +/// Trait for running tests. +pub trait TestRun { + type Options; + type Result; + + /// Run the test with the given options and return the result. + fn run(&self, opts: &Self::Options) -> Result; +} + +/// Represents the result of a test. +#[derive(Debug, Default)] +pub struct TestResult { + /// This field stores test case information in an [IndexMap], where the key is a [String] and the value is a [TestCaseInfo] struct. + pub info: IndexMap, +} + +/// Represents information about a test case. +#[derive(Debug, Default)] +pub struct TestCaseInfo { + /// This field stores the log message of the test. + pub log_message: String, + /// This field stores the error associated with the test case, if any. + pub error: Option, + /// This field stores the duration of the test case. + pub duration: Duration, +} + +/// Represents options for running tests. +#[derive(Debug, Default, Clone)] +pub struct TestOptions { + /// This field stores the execution program arguments. + pub exec_args: ExecProgramArgs, + /// This field stores a regular expression for filtering tests to run. + pub run_regexp: String, + /// This field determines whether the test run should stop on the first failure. + pub fail_fast: bool, +} diff --git a/kclvm/tools/src/testing/suite.rs b/kclvm/tools/src/testing/suite.rs new file mode 100644 index 000000000..c03058ff6 --- /dev/null +++ b/kclvm/tools/src/testing/suite.rs @@ -0,0 +1,194 @@ +use std::{fs::remove_file, path::Path}; + +use crate::testing::{TestCaseInfo, TestOptions, TestResult, TestRun}; +use anyhow::{anyhow, Result}; +use indexmap::IndexMap; +use kclvm_ast::ast; +use kclvm_driver::{get_kcl_files, get_pkg_list}; +use kclvm_parser::{parse_file_force_errors, ParseSession}; +use kclvm_runner::runner::ProgramRunner; +use kclvm_runner::{build_program, ExecProgramArgs}; +use std::sync::Arc; +use std::time::Instant; + +/// File suffix for test files. +pub const TEST_FILE_SUFFIX: &str = "_test.k"; +/// Prefix for test suite names. +pub const TEST_SUITE_PREFIX: &str = "test_"; + +const TEST_MAIN_FILE: &str = "_kcl_test.k"; +const TEST_CASE_RUN_OPTION: &str = "_kcl_test_case_run"; +const TEST_MAIN_FILE_PREFIX: &str = r#" +# Auto generated by the kcl test tool; DO NOT EDIT! + +_kcl_test_case_run = option("_kcl_test_case_run", type="str", default="") + +"#; + +pub struct TestSuite { + /// Package path of the test suite. e.g. ./path/to/pkg + pub pkg: String, + /// List of normal files in the package. + pub normal_files: Vec, + /// List of normal files without the `_test.k` suffix in the package. + pub test_files: Vec, + // Map of test cases in the test suite. + pub cases: IndexMap, + // Flag indicating whether the test suite should be skipped. + pub skip: bool, +} + +impl TestRun for TestSuite { + type Options = TestOptions; + type Result = TestResult; + + /// Run the test suite with the given options and return the result. + fn run(&self, opts: &Self::Options) -> Result { + let mut result = TestResult::default(); + // Skip test suite if marked as skipped or if there are no test cases. + if self.skip || self.cases.is_empty() { + return Ok(result); + } + // Generate the test main entry file. + let main_file = self.gen_test_main_file()?; + // Set up execution arguments. + let mut args = ExecProgramArgs { + k_filename_list: self.get_input_files(&main_file), + overrides: vec![], + disable_yaml_result: true, + ..opts.exec_args.clone() + }; + // Build the program. + let artifact = build_program::(Arc::new(ParseSession::default()), &args, None)?; + // Test every case in the suite. + for (name, _) in &self.cases { + args.args = vec![ast::CmdArgSpec { + name: TEST_CASE_RUN_OPTION.into(), + value: format!("{:?}", name), + }]; + let start = Instant::now(); + let exec_result = artifact.run(&args)?; + // Check if there was an error. + let error = if exec_result.err_message.is_empty() { + None + } else { + Some(anyhow!("{}", exec_result.err_message)) + }; + // Check if the fail_fast option is enabled and there was an error. + let fail_fast = error.is_some() && opts.fail_fast; + // Add test case information to the result. + result.info.insert( + name.clone(), + TestCaseInfo { + log_message: exec_result.log_message.clone(), + duration: Instant::now() - start, + error, + }, + ); + if fail_fast { + break; + } + } + // Remove the temp test main file + if opts.exec_args.debug == 0 { + remove_file(main_file)?; + } + Ok(result) + } +} + +impl TestSuite { + fn gen_test_main_file(&self) -> Result { + let test_codes = self + .cases + .keys() + .map(|c| format!("if {} == '{}': {}()", TEST_CASE_RUN_OPTION, c, c)) + .collect::>(); + let code = format!("{}{}", TEST_MAIN_FILE_PREFIX, test_codes.join("\n")); + let path = Path::new(&self.pkg).join(TEST_MAIN_FILE); + let test_main_file = path + .to_str() + .ok_or(anyhow!("{} is not found", TEST_MAIN_FILE))?; + std::fs::write(test_main_file, code)?; + Ok(test_main_file.into()) + } + + fn get_input_files(&self, main_file: &str) -> Vec { + // Construct test package files. + let mut files = vec![]; + let mut normal_files = self.normal_files.clone(); + let mut test_files = self.test_files.clone(); + files.append(&mut normal_files); + files.append(&mut test_files); + files.push(main_file.into()); + files + } +} + +pub struct TestCase; + +/// Load test suite from path +pub fn load_test_suites>(path: P, opts: &TestOptions) -> Result> { + let pkg_list = get_pkg_list(path.as_ref())?; + let mut suites = vec![]; + for pkg in &pkg_list { + let (normal_files, test_files) = get_test_files(pkg)?; + let mut cases = IndexMap::new(); + for file in &test_files { + let module = parse_file_force_errors(file, None)?; + for stmt in &module.body { + if let ast::Stmt::Assign(assign_stmt) = &stmt.node { + if let ast::Expr::Lambda(_lambda_expr) = &assign_stmt.value.node { + for target in &assign_stmt.targets { + let func_name = target.node.get_name(); + if is_test_suite(&func_name) && should_run(&opts.run_regexp, &func_name) + { + cases.insert(func_name.clone(), TestCase {}); + } + } + } + } + } + } + suites.push(TestSuite { + pkg: pkg.clone(), + cases, + normal_files, + test_files, + skip: false, + }); + } + Ok(suites) +} + +#[inline] +fn get_test_files>(pkg: P) -> Result<(Vec, Vec)> { + let files = get_kcl_files(pkg, false)?; + let normal_files = files + .iter() + .filter(|x| !x.starts_with('_') && !x.ends_with(TEST_FILE_SUFFIX)) + .cloned() + .collect::>(); + let test_files = files + .iter() + .filter(|x| !x.starts_with('_') && x.ends_with(TEST_FILE_SUFFIX)) + .cloned() + .collect::>(); + Ok((normal_files, test_files)) +} + +#[inline] +fn is_test_suite(name: &str) -> bool { + name.starts_with(TEST_SUITE_PREFIX) +} + +#[inline] +fn should_run(run_regexp: &str, name: &str) -> bool { + if !run_regexp.is_empty() { + regex::Regex::new(run_regexp) + .map(|re| re.is_match(name)) + .unwrap_or_default() + } else { + true + } +} diff --git a/kclvm/tools/src/testing/test_data/module/kcl.mod b/kclvm/tools/src/testing/test_data/module/kcl.mod new file mode 100644 index 000000000..35d888aa7 --- /dev/null +++ b/kclvm/tools/src/testing/test_data/module/kcl.mod @@ -0,0 +1,3 @@ +[package] +name = "test_data" + diff --git a/kclvm/tools/src/testing/test_data/module/pkg/func.k b/kclvm/tools/src/testing/test_data/module/pkg/func.k new file mode 100644 index 000000000..26df9cf5a --- /dev/null +++ b/kclvm/tools/src/testing/test_data/module/pkg/func.k @@ -0,0 +1,3 @@ +func = lambda x { + x +} diff --git a/kclvm/tools/src/testing/test_data/module/pkg/func_test.k b/kclvm/tools/src/testing/test_data/module/pkg/func_test.k new file mode 100644 index 000000000..2aadb5a3f --- /dev/null +++ b/kclvm/tools/src/testing/test_data/module/pkg/func_test.k @@ -0,0 +1,7 @@ +test_func_0 = lambda { + assert func("a") == "a" +} + +test_func_1 = lambda { + assert func("a") == "d" +} diff --git a/kclvm/tools/src/testing/tests.rs b/kclvm/tools/src/testing/tests.rs new file mode 100644 index 000000000..54d545c4b --- /dev/null +++ b/kclvm/tools/src/testing/tests.rs @@ -0,0 +1,32 @@ +use crate::testing::TestRun; + +use super::{load_test_suites, TestOptions}; +use std::path::Path; + +#[test] +fn test_load_test_suites_and_run() { + let opts = TestOptions::default(); + let suites = load_test_suites( + Path::new(".") + .join("src") + .join("testing") + .join("test_data") + .join("module") + .join("pkg") + .to_str() + .unwrap(), + &opts, + ) + .unwrap(); + assert_eq!(suites.len(), 1); + assert_eq!(suites[0].cases.len(), 2); + let test_result = suites[0].run(&opts).unwrap(); + assert_eq!(test_result.info.len(), 2); + assert!(test_result.info[0].error.is_none()); + assert!(test_result.info[1] + .error + .as_ref() + .unwrap() + .to_string() + .contains("Error"),); +} diff --git a/kclvm/tools/src/util/loader.rs b/kclvm/tools/src/util/loader.rs index 3e929ae3d..ab3b026d1 100644 --- a/kclvm/tools/src/util/loader.rs +++ b/kclvm/tools/src/util/loader.rs @@ -1,6 +1,10 @@ -use std::fs; +use std::{fs, path::PathBuf}; use anyhow::{bail, Context, Result}; +use compiler_base_span::{span::new_byte_pos, BytePos, FilePathMapping, SourceMap}; +use json_spanned_value::{self as jsv, spanned}; +use kclvm_ast::ast::PosTuple; +use located_yaml::YamlLoader; pub(crate) trait Loader { fn load(&self) -> Result; @@ -20,6 +24,8 @@ pub enum LoaderKind { pub(crate) struct DataLoader { kind: LoaderKind, content: String, + // SourceMap is used to find the position of the error in the file + sm: SourceMap, } impl DataLoader { @@ -27,19 +33,24 @@ impl DataLoader { pub(crate) fn new_with_file_path(loader_kind: LoaderKind, file_path: &str) -> Result { let content = fs::read_to_string(file_path) .with_context(|| format!("Failed to Load '{}'", file_path))?; - + let sm = SourceMap::new(FilePathMapping::empty()); + sm.new_source_file(PathBuf::from(file_path).into(), content.clone()); Ok(Self { kind: loader_kind, content, + sm, }) } /// If `DataLoader` is constructed using a Json/Yaml string, then `content` is the string #[allow(dead_code)] pub(crate) fn new_with_str(loader_kind: LoaderKind, content: &str) -> Result { + let sm = SourceMap::new(FilePathMapping::empty()); + sm.new_source_file(PathBuf::from("").into(), content.to_string()); Ok(Self { kind: loader_kind, content: content.to_string(), + sm, }) } @@ -50,6 +61,29 @@ impl DataLoader { pub(crate) fn get_kind(&self) -> &LoaderKind { &self.kind } + + /// Convert the position in the source map to the position in the source file + pub fn byte_pos_to_pos_in_sourcemap(&self, lo: BytePos, hi: BytePos) -> PosTuple { + let lo = self.sm.lookup_char_pos(lo); + let hi = self.sm.lookup_char_pos(hi); + let filename: String = format!("{}", lo.file.name.prefer_remapped()); + ( + filename, + lo.line as u64, + lo.col.0 as u64, + hi.line as u64, + hi.col.0 as u64, + ) + } + + pub fn file_name(&self) -> String { + self.sm + .lookup_char_pos(new_byte_pos(0)) + .file + .name + .prefer_remapped() + .to_string() + } } impl Loader for DataLoader { @@ -67,6 +101,38 @@ impl Loader for DataLoader { } } +/// Load data into Json value with span. +impl Loader for DataLoader { + fn load(&self) -> Result { + let v = match self.kind { + LoaderKind::JSON => jsv::from_str(self.get_data()) + .with_context(|| format!("Failed to String '{}' to Json", self.get_data()))?, + _ => { + bail!("Failed to String to Json Value") + } + }; + + Ok(v) + } +} + +/// Load data into Json value with span. +impl Loader for DataLoader { + fn load(&self) -> Result { + let v = match self.kind { + LoaderKind::YAML => YamlLoader::load_from_str(self.get_data()) + .with_context(|| format!("Failed to String '{}' to Yaml", self.get_data()))?, + _ => { + bail!("Failed to String to Yaml Value") + } + }; + + v.docs + .get(0) + .map_or_else(|| bail!("Failed to Load YAML"), |res| Ok(res.clone())) + } +} + impl Loader for DataLoader { /// Load data into Yaml value. fn load(&self) -> Result { diff --git a/kclvm/tools/src/vet/expr_builder.rs b/kclvm/tools/src/vet/expr_builder.rs index 36b5bb654..db34a1d76 100644 --- a/kclvm/tools/src/vet/expr_builder.rs +++ b/kclvm/tools/src/vet/expr_builder.rs @@ -1,3 +1,4 @@ +use compiler_base_span::span::new_byte_pos; use kclvm_ast::{ ast::{ ConfigEntry, ConfigEntryOperation, ConfigExpr, Expr, ExprContext, Identifier, ListExpr, @@ -6,6 +7,7 @@ use kclvm_ast::{ }, node_ref, }; +use serde_json::json; use crate::util::loader::{DataLoader, Loader, LoaderKind}; use anyhow::{bail, Context, Result}; @@ -43,14 +45,16 @@ impl ExprBuilder { pub(crate) fn build(&self, schema_name: Option) -> Result> { match self.loader.get_kind() { LoaderKind::JSON => { - let value = >::load(&self.loader) - .with_context(|| "Failed to Load JSON".to_string())?; + let value = , + >>::load(&self.loader) + .with_context(|| "Failed to Load JSON".to_string())?; Ok(self .generate(&value, &schema_name) .with_context(|| "Failed to Load JSON".to_string())?) } LoaderKind::YAML => { - let value = >::load(&self.loader) + let value = >::load(&self.loader) .with_context(|| "Failed to Load YAML".to_string())?; Ok(self .generate(&value, &schema_name) @@ -161,7 +165,7 @@ impl ExprGenerator for ExprBuilder { match schema_name { Some(s_name) => { let iden = node_ref!(Identifier { - names: vec![s_name.to_string()], + names: vec![Node::dummy_node(s_name.to_string())], pkgpath: String::new(), ctx: ExprContext::Load }); @@ -185,6 +189,327 @@ impl ExprGenerator for ExprBuilder { } } +impl ExprGenerator for ExprBuilder { + fn generate( + &self, + value: &located_yaml::Yaml, + schema_name: &Option, + ) -> Result> { + let loc = ( + self.loader.file_name(), + value.marker.line as u64, + value.marker.col as u64, + 0, + 0, + ); + match &value.yaml { + located_yaml::YamlElt::Null => Ok(node_ref!( + Expr::NameConstantLit(NameConstantLit { + value: NameConstant::None, + }), + loc + )), + located_yaml::YamlElt::Boolean(j_bool) => { + let name_const = match NameConstant::try_from(*j_bool) { + Ok(nc) => nc, + Err(err) => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, {err}") + } + }; + + Ok(node_ref!( + Expr::NameConstantLit(NameConstantLit { value: name_const }), + loc + )) + } + located_yaml::YamlElt::Integer(j_int) => { + if json!(j_int).is_i64() { + Ok(node_ref!( + Expr::NumberLit(NumberLit { + binary_suffix: None, + value: NumberLitValue::Int(*j_int) + }), + loc + )) + } else { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, Unsupported Number Type"); + } + } + located_yaml::YamlElt::Real(j_float) => { + if let Ok(number_lit) = j_float.parse::() { + if format!("{}", number_lit) != *j_float { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, Unsupported Number Type",) + } + Ok(node_ref!( + Expr::NumberLit(NumberLit { + binary_suffix: None, + value: NumberLitValue::Float(number_lit) + }), + loc + )) + } else { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, Unsupported Number Type",) + } + } + located_yaml::YamlElt::String(j_string) => { + let str_lit = match StringLit::try_from(j_string.to_string()) { + Ok(s) => s, + Err(_) => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}") + } + }; + Ok(node_ref!(Expr::StringLit(str_lit), loc)) + } + located_yaml::YamlElt::Array(j_arr) => { + let mut j_arr_ast_nodes: Vec> = Vec::new(); + for j_arr_item in j_arr { + j_arr_ast_nodes.push( + self.generate(j_arr_item, schema_name) + .with_context(|| FAIL_LOAD_VALIDATED_ERR_MSG)?, + ); + } + Ok(node_ref!( + Expr::List(ListExpr { + ctx: ExprContext::Load, + elts: j_arr_ast_nodes + }), + loc + )) + } + located_yaml::YamlElt::Hash(j_map) => { + let mut config_entries: Vec> = Vec::new(); + + for (k, v) in j_map.iter() { + // The configuration builder already in the schema no longer needs a schema name + let k = self + .generate(k, &None) + .with_context(|| FAIL_LOAD_VALIDATED_ERR_MSG)?; + let v = self + .generate(v, &None) + .with_context(|| FAIL_LOAD_VALIDATED_ERR_MSG)?; + + let config_entry = node_ref!( + ConfigEntry { + key: Some(k), + value: v, + operation: ConfigEntryOperation::Union, + insert_index: -1 + }, + loc.clone() + ); + config_entries.push(config_entry); + } + + let config_expr = node_ref!( + Expr::Config(ConfigExpr { + items: config_entries + }), + loc.clone() + ); + + match schema_name { + Some(s_name) => { + let iden = node_ref!( + Identifier { + names: vec![Node::new( + s_name.to_string(), + loc.0.clone(), + loc.1, + loc.2, + loc.3, + loc.4 + )], + pkgpath: String::new(), + ctx: ExprContext::Load + }, + loc.clone() + ); + Ok(node_ref!( + Expr::Schema(SchemaExpr { + name: iden, + config: config_expr, + args: vec![], + kwargs: vec![] + }), + loc.clone() + )) + } + None => Ok(config_expr), + } + } + _ => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, Unsupported Yaml Element",) + } + } + } +} + +/// `ExprBuilder` will generate ast expr from Json with span. +impl ExprGenerator> for ExprBuilder { + fn generate( + &self, + value: &json_spanned_value::Spanned, + schema_name: &Option, + ) -> Result> { + let loc = self.loader.byte_pos_to_pos_in_sourcemap( + new_byte_pos(value.span().0 as u32), + new_byte_pos(value.span().1 as u32), + ); + match value.get_ref() { + json_spanned_value::Value::Null => Ok(node_ref!( + Expr::NameConstantLit(NameConstantLit { + value: NameConstant::None, + }), + loc + )), + json_spanned_value::Value::Bool(j_bool) => { + let name_const = match NameConstant::try_from(*j_bool) { + Ok(nc) => nc, + Err(err) => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, {err}") + } + }; + + Ok(node_ref!( + Expr::NameConstantLit(NameConstantLit { value: name_const }), + loc + )) + } + json_spanned_value::Value::Number(j_num) => { + if j_num.is_f64() { + let number_lit = match j_num.as_f64() { + Some(num_f64) => num_f64, + None => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}") + } + }; + + Ok(node_ref!( + Expr::NumberLit(NumberLit { + binary_suffix: None, + value: NumberLitValue::Float(number_lit) + }), + loc + )) + } else if j_num.is_i64() { + let number_lit = match j_num.as_i64() { + Some(j_num) => j_num, + None => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}") + } + }; + + Ok(node_ref!( + Expr::NumberLit(NumberLit { + binary_suffix: None, + value: NumberLitValue::Int(number_lit) + }), + loc + )) + } else { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, Unsupported Unsigned 64"); + } + } + json_spanned_value::Value::String(j_string) => { + let str_lit = match StringLit::try_from(j_string.to_string()) { + Ok(s) => s, + Err(_) => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}") + } + }; + + Ok(node_ref!(Expr::StringLit(str_lit), loc)) + } + json_spanned_value::Value::Array(j_arr) => { + let mut j_arr_ast_nodes: Vec> = Vec::new(); + for j_arr_item in j_arr { + j_arr_ast_nodes.push( + self.generate(j_arr_item, schema_name) + .with_context(|| FAIL_LOAD_VALIDATED_ERR_MSG)?, + ); + } + Ok(node_ref!( + Expr::List(ListExpr { + ctx: ExprContext::Load, + elts: j_arr_ast_nodes + }), + loc + )) + } + json_spanned_value::Value::Object(j_map) => { + let mut config_entries: Vec> = Vec::new(); + + for (k, v) in j_map.iter() { + let k_span = k.span(); + let k = match StringLit::try_from(k.to_string()) { + Ok(s) => s, + Err(err) => { + bail!("{FAIL_LOAD_VALIDATED_ERR_MSG}, {err}") + } + }; + let v = self + .generate(v, &None) + .with_context(|| FAIL_LOAD_VALIDATED_ERR_MSG)?; + + let config_entry = node_ref!( + ConfigEntry { + key: Some(node_ref!( + Expr::StringLit(k), + self.loader.byte_pos_to_pos_in_sourcemap( + new_byte_pos(k_span.0 as u32), + new_byte_pos(k_span.1 as u32) + ) + )), + value: v, + operation: ConfigEntryOperation::Union, + insert_index: -1 + }, + loc.clone() + ); + config_entries.push(config_entry); + } + + let config_expr = node_ref!( + Expr::Config(ConfigExpr { + items: config_entries + }), + loc.clone() + ); + + match schema_name { + Some(s_name) => { + let iden = node_ref!( + Identifier { + names: vec![Node::new( + s_name.to_string(), + loc.0.clone(), + loc.1, + loc.2, + loc.3, + loc.4 + )], + pkgpath: String::new(), + ctx: ExprContext::Load + }, + loc.clone() + ); + Ok(node_ref!( + Expr::Schema(SchemaExpr { + name: iden, + config: config_expr, + args: vec![], + kwargs: vec![] + }), + loc + )) + } + None => Ok(config_expr), + } + } + } + } +} + impl ExprGenerator for ExprBuilder { fn generate( &self, @@ -289,7 +614,7 @@ impl ExprGenerator for ExprBuilder { match schema_name { Some(s_name) => { let iden = node_ref!(Identifier { - names: vec![s_name.to_string()], + names: vec![Node::dummy_node(s_name.to_string())], pkgpath: String::new(), ctx: ExprContext::Load }); diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-2.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-2.snap new file mode 100644 index 000000000..6c792a219 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-2.snap @@ -0,0 +1,162 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": "simple" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-3.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-3.snap new file mode 100644 index 000000000..19165aa64 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-3.snap @@ -0,0 +1,19 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "/plain_value.k.json", + "line": 1, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-4.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-4.snap new file mode 100644 index 000000000..71c682689 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-4.snap @@ -0,0 +1,175 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "/list.k.json", + "line": 1, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "args": [], + "config": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "items": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": "list" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } + } + ], + "type": "List" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-5.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-5.snap new file mode 100644 index 000000000..eae68d196 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-5.snap @@ -0,0 +1,429 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "/complex.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"data\"", + "type": "StringLit", + "value": "data" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "items": [ + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"id\"", + "type": "StringLit", + "value": "id" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + } + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + }, + "operation": "Union", + "value": { + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value1\"", + "type": "StringLit", + "value": "value1" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "is_long_string": false, + "raw_value": "\"hc\"", + "type": "StringLit", + "value": "hc" + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 2 + } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 3 + } + } + } + ], + "type": "List" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "/complex.k.json", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"labels\"", + "type": "StringLit", + "value": "labels" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"key\"", + "type": "StringLit", + "value": "key" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": "complex" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-6.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-6.snap new file mode 100644 index 000000000..0ac707bcd --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-6.snap @@ -0,0 +1,84 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "type": "StringLit", + "value": "null_value" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "None" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": "only_with_null" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-7.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-7.snap new file mode 100644 index 000000000..1dbe63aa9 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-7.snap @@ -0,0 +1,84 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"flag\"", + "type": "StringLit", + "value": "flag" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "True" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": "only_with_bool" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-8.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-8.snap new file mode 100644 index 000000000..e508aac19 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath-8.snap @@ -0,0 +1,88 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "type": "StringLit", + "value": "float_value" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Float", + "value": 0.33 + } + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": "only_with_float" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath.snap new file mode 100644 index 000000000..376279697 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_filepath.snap @@ -0,0 +1,298 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/test.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"address\"", + "type": "StringLit", + "value": "address" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "items": [ + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"city\"", + "type": "StringLit", + "value": "city" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"London\"", + "type": "StringLit", + "value": "London" + } + } + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"street\"", + "type": "StringLit", + "value": "street" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "type": "StringLit", + "value": "10 Downing Street" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 43 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "type": "StringLit", + "value": "John Doe" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "/test.k.json", + "line": 8, + "node": { + "is_long_string": false, + "raw_value": "\"phones\"", + "type": "StringLit", + "value": "phones" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/test.k.json", + "line": 8, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "/test.k.json", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "type": "StringLit", + "value": "+44 1234567" + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "/test.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "type": "StringLit", + "value": "+44 2345678" + } + } + ], + "type": "List" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": "test" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-2.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-2.snap new file mode 100644 index 000000000..9d6105035 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-2.snap @@ -0,0 +1,162 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": "simple" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-3.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-3.snap new file mode 100644 index 000000000..1d2ef3c01 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-3.snap @@ -0,0 +1,19 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "", + "line": 1, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-4.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-4.snap new file mode 100644 index 000000000..a5b616a7e --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-4.snap @@ -0,0 +1,175 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "args": [], + "config": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "items": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": "list" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } + } + ], + "type": "List" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-5.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-5.snap new file mode 100644 index 000000000..f63d815f3 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-5.snap @@ -0,0 +1,429 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"data\"", + "type": "StringLit", + "value": "data" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "items": [ + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"id\"", + "type": "StringLit", + "value": "id" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + } + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + }, + "operation": "Union", + "value": { + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value1\"", + "type": "StringLit", + "value": "value1" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "is_long_string": false, + "raw_value": "\"hc\"", + "type": "StringLit", + "value": "hc" + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 2 + } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 3 + } + } + } + ], + "type": "List" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"labels\"", + "type": "StringLit", + "value": "labels" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 9, + "node": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 9, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"key\"", + "type": "StringLit", + "value": "key" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": "complex" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-6.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-6.snap new file mode 100644 index 000000000..3b8d839c6 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-6.snap @@ -0,0 +1,84 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "type": "StringLit", + "value": "null_value" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "None" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_null" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-7.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-7.snap new file mode 100644 index 000000000..5d6e0bda7 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-7.snap @@ -0,0 +1,84 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"flag\"", + "type": "StringLit", + "value": "flag" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "True" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_bool" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-8.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-8.snap new file mode 100644 index 000000000..5f14d9e73 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str-8.snap @@ -0,0 +1,88 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "type": "StringLit", + "value": "float_value" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Float", + "value": 0.33 + } + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_float" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str.snap new file mode 100644 index 000000000..cebe71cae --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_json_with_str.snap @@ -0,0 +1,298 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"address\"", + "type": "StringLit", + "value": "address" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "items": [ + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"city\"", + "type": "StringLit", + "value": "city" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"London\"", + "type": "StringLit", + "value": "London" + } + } + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"street\"", + "type": "StringLit", + "value": "street" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "type": "StringLit", + "value": "10 Downing Street" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 43 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "type": "StringLit", + "value": "John Doe" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "", + "line": 8, + "node": { + "is_long_string": false, + "raw_value": "\"phones\"", + "type": "StringLit", + "value": "phones" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 8, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "type": "StringLit", + "value": "+44 1234567" + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "type": "StringLit", + "value": "+44 2345678" + } + } + ], + "type": "List" + } + } + } + } + ], + "type": "Config" + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": "test" + } + ], + "pkgpath": "" + } + }, + "type": "Schema" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-2.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-2.snap new file mode 100644 index 000000000..2cf71ad87 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-2.snap @@ -0,0 +1,129 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-3.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-3.snap new file mode 100644 index 000000000..19165aa64 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-3.snap @@ -0,0 +1,19 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "/plain_value.k.json", + "line": 1, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-4.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-4.snap new file mode 100644 index 000000000..22cb63f75 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-4.snap @@ -0,0 +1,142 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "/list.k.json", + "line": 1, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "items": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } + } + ], + "type": "List" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-5.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-5.snap new file mode 100644 index 000000000..389d673e8 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-5.snap @@ -0,0 +1,396 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 18 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "/complex.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"data\"", + "type": "StringLit", + "value": "data" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "items": [ + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"id\"", + "type": "StringLit", + "value": "id" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + } + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + }, + "operation": "Union", + "value": { + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "is_long_string": false, + "raw_value": "\"value1\"", + "type": "StringLit", + "value": "value1" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "is_long_string": false, + "raw_value": "\"hc\"", + "type": "StringLit", + "value": "hc" + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 1 + } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 2 + } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 3 + } + } + } + ], + "type": "List" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "/complex.k.json", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"labels\"", + "type": "StringLit", + "value": "labels" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"key\"", + "type": "StringLit", + "value": "key" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"value\"", + "type": "StringLit", + "value": "value" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"message\"", + "type": "StringLit", + "value": "message" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "type": "StringLit", + "value": "This is Alice" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "type": "StringLit", + "value": "Alice" + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-6.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-6.snap new file mode 100644 index 000000000..d3f3bb3dc --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-6.snap @@ -0,0 +1,51 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "type": "StringLit", + "value": "null_value" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "None" + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-7.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-7.snap new file mode 100644 index 000000000..5ae411ae0 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-7.snap @@ -0,0 +1,51 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"flag\"", + "type": "StringLit", + "value": "flag" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "type": "NameConstantLit", + "value": "True" + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-8.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-8.snap new file mode 100644 index 000000000..2861cabd0 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name-8.snap @@ -0,0 +1,55 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "type": "StringLit", + "value": "float_value" + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Float", + "value": 0.33 + } + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name.snap new file mode 100644 index 000000000..686a9c5b8 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_json_no_schema_name.snap @@ -0,0 +1,265 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_json_str +--- +{ + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/test.k.json", + "line": 4, + "node": { + "is_long_string": false, + "raw_value": "\"address\"", + "type": "StringLit", + "value": "address" + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "items": [ + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"city\"", + "type": "StringLit", + "value": "city" + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "is_long_string": false, + "raw_value": "\"London\"", + "type": "StringLit", + "value": "London" + } + } + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"street\"", + "type": "StringLit", + "value": "street" + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "type": "StringLit", + "value": "10 Downing Street" + } + } + } + } + ], + "type": "Config" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "is_long_string": false, + "raw_value": "\"age\"", + "type": "StringLit", + "value": "age" + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "binary_suffix": null, + "type": "NumberLit", + "value": { + "type": "Int", + "value": 43 + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"name\"", + "type": "StringLit", + "value": "name" + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "type": "StringLit", + "value": "John Doe" + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "/test.k.json", + "line": 8, + "node": { + "is_long_string": false, + "raw_value": "\"phones\"", + "type": "StringLit", + "value": "phones" + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/test.k.json", + "line": 8, + "node": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "/test.k.json", + "line": 9, + "node": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "type": "StringLit", + "value": "+44 1234567" + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "/test.k.json", + "line": 10, + "node": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "type": "StringLit", + "value": "+44 2345678" + } + } + ], + "type": "List" + } + } + } + } + ], + "type": "Config" + } +} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-2.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-2.snap new file mode 100644 index 000000000..884b88940 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-2.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/simple.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice,\"","value":"Alice,"},"filename":"/simple.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/simple.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"18,\"","value":"18,"},"filename":"/simple.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/simple.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/simple.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-3.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-3.snap new file mode 100644 index 000000000..0a462296b --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-3.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/plain_value.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-4.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-4.snap new file mode 100644 index 000000000..4abc726e5 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-4.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"List","elts":[{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/list.k.yaml","line":1,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"},"filename":"/list.k.yaml","line":1,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/list.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":18}},"filename":"/list.k.yaml","line":2,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/list.k.yaml","line":3,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/list.k.yaml","line":3,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}]},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/list.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-5.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-5.snap new file mode 100644 index 000000000..8828b7ea7 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-5.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/complex.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"},"filename":"/complex.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/complex.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":18}},"filename":"/complex.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/complex.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/complex.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"data\"","value":"data"},"filename":"/complex.k.yaml","line":4,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"id\"","value":"id"},"filename":"/complex.k.yaml","line":5,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/complex.k.yaml","line":5,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value\"","value":"value"},"filename":"/complex.k.yaml","line":6,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value1\"","value":"value1"},"filename":"/complex.k.yaml","line":6,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"labels\"","value":"labels"},"filename":"/complex.k.yaml","line":7,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"key\"","value":"key"},"filename":"/complex.k.yaml","line":8,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value\"","value":"value"},"filename":"/complex.k.yaml","line":8,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"hc\"","value":"hc"},"filename":"/complex.k.yaml","line":9,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"List","elts":[{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/complex.k.yaml","line":10,"column":6,"end_line":0,"end_column":0},{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":2}},"filename":"/complex.k.yaml","line":11,"column":6,"end_line":0,"end_column":0},{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":3}},"filename":"/complex.k.yaml","line":12,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/complex.k.yaml","line":10,"column":4,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-6.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-6.snap new file mode 100644 index 000000000..a56aff609 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-6.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"null_val\"","value":"null_val"},"filename":"/only_with_null.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NameConstantLit","value":"None"},"filename":"/only_with_null.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}]},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-7.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-7.snap new file mode 100644 index 000000000..048edc552 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-7.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"bool_val\"","value":"bool_val"},"filename":"/only_with_bool.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NameConstantLit","value":"True"},"filename":"/only_with_bool.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}]},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-8.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-8.snap new file mode 100644 index 000000000..cbde2526e --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name-8.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"float_val\"","value":"float_val"},"filename":"/only_with_float.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Float","value":0.33}},"filename":"/only_with_float.yaml","line":1,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}]},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name.snap new file mode 100644 index 000000000..bc42c7584 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_with_yaml_no_schema_name.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"languages\"","value":"languages"},"filename":"/test.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"List","elts":[{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"},"filename":"/test.k.yaml","line":2,"column":4,"end_line":0,"end_column":0},{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"},"filename":"/test.k.yaml","line":3,"column":4,"end_line":0,"end_column":0},{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Python\"","value":"Python"},"filename":"/test.k.yaml","line":4,"column":4,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/test.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"websites\"","value":"websites"},"filename":"/test.k.yaml","line":5,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"YAML\"","value":"YAML"},"filename":"/test.k.yaml","line":6,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"yaml.org\"","value":"yaml.org"},"filename":"/test.k.yaml","line":6,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"},"filename":"/test.k.yaml","line":7,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"ruby-lang.org\"","value":"ruby-lang.org"},"filename":"/test.k.yaml","line":7,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Python\"","value":"Python"},"filename":"/test.k.yaml","line":8,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"python.org\"","value":"python.org"},"filename":"/test.k.yaml","line":8,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"},"filename":"/test.k.yaml","line":9,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"use.perl.org\"","value":"use.perl.org"},"filename":"/test.k.yaml","line":9,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0}]},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}]},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-2.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-2.snap new file mode 100644 index 000000000..ef00d15f9 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-2.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"simple","filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/simple.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice,\"","value":"Alice,"},"filename":"/simple.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/simple.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"18,\"","value":"18,"},"filename":"/simple.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/simple.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/simple.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-3.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-3.snap new file mode 100644 index 000000000..0a462296b --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-3.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/plain_value.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-4.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-4.snap new file mode 100644 index 000000000..7cbe04455 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-4.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"List","elts":[{"node":{"type":"Schema","name":{"node":{"names":[{"node":"list","filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/list.k.yaml","line":1,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"},"filename":"/list.k.yaml","line":1,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/list.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":18}},"filename":"/list.k.yaml","line":2,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/list.k.yaml","line":3,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/list.k.yaml","line":3,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}]},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/list.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-5.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-5.snap new file mode 100644 index 000000000..29c6875fa --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-5.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"complex","filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"name\"","value":"name"},"filename":"/complex.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"},"filename":"/complex.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"age\"","value":"age"},"filename":"/complex.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":18}},"filename":"/complex.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"message\"","value":"message"},"filename":"/complex.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"},"filename":"/complex.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"data\"","value":"data"},"filename":"/complex.k.yaml","line":4,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"id\"","value":"id"},"filename":"/complex.k.yaml","line":5,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/complex.k.yaml","line":5,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value\"","value":"value"},"filename":"/complex.k.yaml","line":6,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value1\"","value":"value1"},"filename":"/complex.k.yaml","line":6,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"labels\"","value":"labels"},"filename":"/complex.k.yaml","line":7,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"key\"","value":"key"},"filename":"/complex.k.yaml","line":8,"column":4,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"value\"","value":"value"},"filename":"/complex.k.yaml","line":8,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"hc\"","value":"hc"},"filename":"/complex.k.yaml","line":9,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"List","elts":[{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":1}},"filename":"/complex.k.yaml","line":10,"column":6,"end_line":0,"end_column":0},{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":2}},"filename":"/complex.k.yaml","line":11,"column":6,"end_line":0,"end_column":0},{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Int","value":3}},"filename":"/complex.k.yaml","line":12,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/complex.k.yaml","line":10,"column":4,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-6.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-6.snap new file mode 100644 index 000000000..251847505 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-6.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"only_with_null","filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"null_val\"","value":"null_val"},"filename":"/only_with_null.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NameConstantLit","value":"None"},"filename":"/only_with_null.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}]},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-7.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-7.snap new file mode 100644 index 000000000..baed11e7c --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-7.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"only_with_bool","filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"bool_val\"","value":"bool_val"},"filename":"/only_with_bool.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NameConstantLit","value":"True"},"filename":"/only_with_bool.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}]},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-8.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-8.snap new file mode 100644 index 000000000..cf92614c0 --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml-8.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"only_with_float","filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"float_val\"","value":"float_val"},"filename":"/only_with_float.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"NumberLit","binary_suffix":null,"value":{"type":"Float","value":0.33}},"filename":"/only_with_float.yaml","line":1,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}]},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml.snap b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml.snap new file mode 100644 index 000000000..41dea12dd --- /dev/null +++ b/kclvm/tools/src/vet/snapshots/kclvm_tools__vet__tests__test_expr_builder__build_yaml.snap @@ -0,0 +1,5 @@ +--- +source: tools/src/vet/tests.rs +expression: got_ast_yaml_str +--- +{"node":{"type":"Schema","name":{"node":{"names":[{"node":"test","filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"languages\"","value":"languages"},"filename":"/test.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"List","elts":[{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"},"filename":"/test.k.yaml","line":2,"column":4,"end_line":0,"end_column":0},{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"},"filename":"/test.k.yaml","line":3,"column":4,"end_line":0,"end_column":0},{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Python\"","value":"Python"},"filename":"/test.k.yaml","line":4,"column":4,"end_line":0,"end_column":0}],"ctx":"Load"},"filename":"/test.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"websites\"","value":"websites"},"filename":"/test.k.yaml","line":5,"column":0,"end_line":0,"end_column":0},"value":{"node":{"type":"Config","items":[{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"YAML\"","value":"YAML"},"filename":"/test.k.yaml","line":6,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"yaml.org\"","value":"yaml.org"},"filename":"/test.k.yaml","line":6,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"},"filename":"/test.k.yaml","line":7,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"ruby-lang.org\"","value":"ruby-lang.org"},"filename":"/test.k.yaml","line":7,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Python\"","value":"Python"},"filename":"/test.k.yaml","line":8,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"python.org\"","value":"python.org"},"filename":"/test.k.yaml","line":8,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"},"filename":"/test.k.yaml","line":9,"column":2,"end_line":0,"end_column":0},"value":{"node":{"type":"StringLit","is_long_string":false,"raw_value":"\"use.perl.org\"","value":"use.perl.org"},"filename":"/test.k.yaml","line":9,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0}]},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}]},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0} diff --git a/kclvm/tools/src/vet/test_datas/invalid/unsupported/yaml_with_tag.yaml b/kclvm/tools/src/vet/test_datas/invalid/unsupported/yaml_with_tag.yaml deleted file mode 100644 index 19ca468cc..000000000 --- a/kclvm/tools/src/vet/test_datas/invalid/unsupported/yaml_with_tag.yaml +++ /dev/null @@ -1,4 +0,0 @@ -!mytag -a: 1 -b: 2 -c: 2022-05-01 \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k new file mode 100644 index 000000000..09c880103 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k @@ -0,0 +1,11 @@ +schema User: + name: str + age: int + message?: str + data: Data + labels: {str:} + hc: [int] + +schema Data: + id: int + value: str diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k.json new file mode 100644 index 000000000..00890e982 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/complex.k.json @@ -0,0 +1,10 @@ +{ + "name": "Alice", + "age": 18, + "message": "This is Alice", + "data": 10, + "labels": { + "key": "value" + }, + "hc": [1, 2, 3] +} diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k new file mode 100644 index 000000000..ef6d67aed --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k @@ -0,0 +1,9 @@ +schema User: + name: str + age: int + message?: str + +assert typeof(value) == "list" +assert all v in value { + typeof(v) == "User" +} diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k.json new file mode 100644 index 000000000..4e4da006d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/list.k.json @@ -0,0 +1,7 @@ +[ + { + "name": 10, + "age": 18, + "message": "This is Alice" + } +] diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k new file mode 100644 index 000000000..820fab7ce --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k @@ -0,0 +1,2 @@ +assert typeof(value) == "int" +assert value >= 1 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k.json new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/plain_value.k.json @@ -0,0 +1 @@ +0 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k new file mode 100644 index 000000000..7a78b3aac --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k @@ -0,0 +1,4 @@ +schema User: + name: str + age: int + message?: str diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k.json new file mode 100644 index 000000000..558a22e13 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/simple.k.json @@ -0,0 +1,5 @@ +{ + "name": 10, + "age": 18, + "message": "This is Alice" +} diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k new file mode 100644 index 000000000..39d538064 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k @@ -0,0 +1,9 @@ +schema User: + name: str + age: int + message?: str + + check: + name == "Alice" + age > 10 + diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k.json new file mode 100644 index 000000000..8b12f2738 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_json/test.k.json @@ -0,0 +1,5 @@ +{ + "name": "Tom", + "age": 18, + "message": "This is Alice" +} diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k new file mode 100644 index 000000000..09c880103 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k @@ -0,0 +1,11 @@ +schema User: + name: str + age: int + message?: str + data: Data + labels: {str:} + hc: [int] + +schema Data: + id: int + value: str diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.stderr.json new file mode 100644 index 000000000..9bfb4e464 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.stderr.json @@ -0,0 +1,18 @@ +{ + "__kcl_PanicInfo__": true, + "rust_file": "", + "rust_line": 0, + "rust_col": 0, + "kcl_pkgpath": "", + "kcl_file": "", + "kcl_line": 1, + "kcl_col": 1, + "kcl_arg_msg": "", + "kcl_config_meta_file": "", + "kcl_config_meta_line": 0, + "kcl_config_meta_col": 0, + "kcl_config_meta_arg_msg": "", + "message": "expect Data, got int(10)", + "err_type_code": 5, + "is_warning": false +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.yaml new file mode 100644 index 000000000..17dbf2761 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/complex.k.yaml @@ -0,0 +1,10 @@ +name: Alice +age: 18 +message: This is Alice +data: 10 +labels: + key: value +hc: + - 1 + - 2 + - 3 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k new file mode 100644 index 000000000..ef6d67aed --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k @@ -0,0 +1,9 @@ +schema User: + name: str + age: int + message?: str + +assert typeof(value) == "list" +assert all v in value { + typeof(v) == "User" +} diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.stderr.json new file mode 100644 index 000000000..9030cae6c --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.stderr.json @@ -0,0 +1,18 @@ +{ + "__kcl_PanicInfo__": true, + "rust_file": "", + "rust_line": 0, + "rust_col": 0, + "kcl_pkgpath": "", + "kcl_file": "", + "kcl_line": 1, + "kcl_col": 1, + "kcl_arg_msg": "", + "kcl_config_meta_file": "", + "kcl_config_meta_line": 0, + "kcl_config_meta_col": 0, + "kcl_config_meta_arg_msg": "", + "message": "expect str, got int(10)", + "err_type_code": 5, + "is_warning": false +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.yaml new file mode 100644 index 000000000..2a038e8b5 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/list.k.yaml @@ -0,0 +1,4 @@ +- name: 10 + age: 18 + message: This is Alice + \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k new file mode 100644 index 000000000..820fab7ce --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k @@ -0,0 +1,2 @@ +assert typeof(value) == "int" +assert value >= 1 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.stderr.json new file mode 100644 index 000000000..b1e3dd64c --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.stderr.json @@ -0,0 +1,18 @@ +{ + "__kcl_PanicInfo__": true, + "rust_file": "runtime/src/stdlib/assert_api.rs", + "rust_line": 19, + "rust_col": 9, + "kcl_pkgpath": "", + "kcl_file": "validationTempKCLCode.k", + "kcl_line": 2, + "kcl_col": 0, + "kcl_arg_msg": "", + "kcl_config_meta_file": "", + "kcl_config_meta_line": 0, + "kcl_config_meta_col": 0, + "kcl_config_meta_arg_msg": "", + "message": "", + "err_type_code": 29, + "is_warning": false +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.yaml new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/plain_value.k.yaml @@ -0,0 +1 @@ +0 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k new file mode 100644 index 000000000..7a78b3aac --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k @@ -0,0 +1,4 @@ +schema User: + name: str + age: int + message?: str diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.stderr.json new file mode 100644 index 000000000..9030cae6c --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.stderr.json @@ -0,0 +1,18 @@ +{ + "__kcl_PanicInfo__": true, + "rust_file": "", + "rust_line": 0, + "rust_col": 0, + "kcl_pkgpath": "", + "kcl_file": "", + "kcl_line": 1, + "kcl_col": 1, + "kcl_arg_msg": "", + "kcl_config_meta_file": "", + "kcl_config_meta_line": 0, + "kcl_config_meta_col": 0, + "kcl_config_meta_arg_msg": "", + "message": "expect str, got int(10)", + "err_type_code": 5, + "is_warning": false +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.yaml new file mode 100644 index 000000000..0acfbba39 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/simple.k.yaml @@ -0,0 +1,3 @@ +name: 10 +age: 18 +message: This is Alice diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k new file mode 100644 index 000000000..4c5653da4 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k @@ -0,0 +1,8 @@ +schema User: + name: str + age: int + message?: str + + check: + name == "Alice" + age > 10 diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.stderr.json b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.stderr.json new file mode 100644 index 000000000..eedceca94 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.stderr.json @@ -0,0 +1,18 @@ +{ + "__kcl_PanicInfo__": true, + "rust_file": "runtime/src/value/api.rs", + "rust_line": 2204, + "rust_col": 9, + "kcl_pkgpath": "__main__", + "kcl_file": "validationTempKCLCode.k", + "kcl_line": 7, + "kcl_col": 0, + "kcl_arg_msg": "Check failed on the condition", + "kcl_config_meta_file": "", + "kcl_config_meta_line": 1, + "kcl_config_meta_col": 1, + "kcl_config_meta_arg_msg": "Instance check failed", + "message": "", + "err_type_code": 17, + "is_warning": false +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.yaml b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.yaml new file mode 100644 index 000000000..26beecf48 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/invalid_vet_cases_yaml/test.k.yaml @@ -0,0 +1,3 @@ +name: Tom +age: 18 +message: This is Alice diff --git a/kclvm/tools/src/vet/test_datas/json/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json/complex.k.ast.json index 0ee30c15f..6c33f2d9d 100644 --- a/kclvm/tools/src/vet/test_datas/json/complex.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/complex.k.ast.json @@ -1,436 +1,443 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 13, + "filename": "/complex.k.json", "line": 1, "node": { - "Config": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "/complex.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "Config": { "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"data\"", - "value": "data" - } - } - }, - "operation": "Union", + "NumberLit": { + "binary_suffix": null, "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"id\"", - "value": "id" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value\"", - "value": "value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value1\"", - "value": "value1" - } - } - } - } - } - ] - } - } + "Int": 1 } + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + } + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"hc\"", - "value": "hc" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 2 - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 3 - } - } - } - } - ] - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + }, + "operation": "Union", + "value": { + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"labels\"", - "value": "labels" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"key\"", - "value": "key" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value\"", - "value": "value" - } - } - } - } - } - ] - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "/complex.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "Config": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } } + } } + } ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } } + } } - }, - "kwargs": [], - "name": { - "column": 1, + }, + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 13, + "filename": "/complex.k.json", "line": 1, "node": { - "ctx": "Load", - "names": [ - "complex" - ], - "pkgpath": "" + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": "complex" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json/list.k.ast.json index 1cc7c1d70..21f95eb77 100644 --- a/kclvm/tools/src/vet/test_datas/json/list.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/list.k.ast.json @@ -1,172 +1,179 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } - } - } - } - } - ] - } - } - }, - "kwargs": [], - "name": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "ctx": "Load", - "names": [ - "list" - ], - "pkgpath": "" + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "/list.k.json", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "Schema": { + "args": [], + "config": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "Config": { + "items": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 } + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } } + } } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": "list" } + ], + "pkgpath": "" } - ] + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/complex.k.ast.json index 365b17e6d..94c9fcbab 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/complex.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/complex.k.ast.json @@ -1,409 +1,409 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "/complex.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { + "Config": { + "items": [ + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { "insert_index": -1, "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" } + } }, "operation": "Union", "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "/complex.k.json", + "line": 6, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } } + } } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 5, + "node": { "insert_index": -1, "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"data\"", - "value": "data" - } + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" } + } }, "operation": "Union", "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"id\"", - "value": "id" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value\"", - "value": "value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value1\"", - "value": "value1" - } - } - } - } - } - ] - } + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" } + } } + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"hc\"", - "value": "hc" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 2 - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 3 - } - } - } - } - ] - } - } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"labels\"", - "value": "labels" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"key\"", - "value": "key" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"value\"", - "value": "value" - } - } - } - } - } - ] - } - } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 + } } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } } + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "/complex.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { + "Config": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/complex.k.json", + "line": 9, + "node": { "insert_index": -1, "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" } + } }, "operation": "Union", "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" } + } } + } } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" } - ] + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/list.k.ast.json index cf5857ef0..5328534c9 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/list.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/list.k.ast.json @@ -1,145 +1,145 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "/list.k.json", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "Config": { + "items": [ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } - } - } - } - } - ] + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } } + } } - ] + ] + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_bool.ast.json index 891d15cbb..31ebdf6f2 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_bool.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_bool.ast.json @@ -1,50 +1,50 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"flag\"", - "value": "flag" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NameConstantLit": { - "value": "True" - } - } - } - } + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" } - ] + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_float.ast.json index f3edc9d91..2f3a0968a 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_float.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_float.ast.json @@ -1,53 +1,53 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"float_value\"", - "value": "float_value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Float": 0.33 - } - } - } - } - } + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" } - ] + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_null.ast.json index 635309d32..f4723b7ff 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_null.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/only_with_null.ast.json @@ -1,50 +1,50 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"null_value\"", - "value": "null_value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NameConstantLit": { - "value": "None" - } - } - } - } + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" } - ] + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/plain_value.k.ast.json index 6d5cb0433..3110dbc86 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/plain_value.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/plain_value.k.ast.json @@ -1,15 +1,15 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "/plain_value.k.json", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/simple.k.ast.json index 6ca1ac023..76b85ff1a 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/simple.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/simple.k.ast.json @@ -1,131 +1,131 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } - } - } - } + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" } - ] + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/no_schema_name/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json/no_schema_name/test.k.ast.json index 86bf8b3e5..e683f9346 100644 --- a/kclvm/tools/src/vet/test_datas/json/no_schema_name/test.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/no_schema_name/test.k.ast.json @@ -1,275 +1,275 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/test.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "Config": { + "items": [ + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { "insert_index": -1, "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"address\"", - "value": "address" - } + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" } + } }, "operation": "Union", "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"city\"", - "value": "city" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"London\"", - "value": "London" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"street\"", - "value": "street" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"10 Downing Street\"", - "value": "10 Downing Street" - } - } - } - } - } - ] - } + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" } + } } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { "insert_index": -1, "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" } + } }, "operation": "Union", "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 43 - } - } + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" } + } } + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"John Doe\"", - "value": "John Doe" - } - } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "/test.k.json", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/test.k.json", + "line": 8, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "/test.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"phones\"", - "value": "phones" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"+44 1234567\"", - "value": "+44 1234567" - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"+44 2345678\"", - "value": "+44 2345678" - } - } - } - ] - } - } + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "/test.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" } + } } + ] } - ] + } + } + } } + ] } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json/only_with_bool.ast.json index de8499450..0913c16c2 100644 --- a/kclvm/tools/src/vet/test_datas/json/only_with_bool.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/only_with_bool.ast.json @@ -1,77 +1,84 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 3, + "filename": "/only_with_bool.json", "line": 1, "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"flag\"", - "value": "flag" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NameConstantLit": { - "value": "True" - } - } - } - } - } - ] + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" + } } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } } - }, - "kwargs": [], - "name": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "ctx": "Load", - "names": [ - "only_with_bool" - ], - "pkgpath": "" - } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": "only_with_bool" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json/only_with_float.ast.json index 9726b82d5..e897394ba 100644 --- a/kclvm/tools/src/vet/test_datas/json/only_with_float.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/only_with_float.ast.json @@ -1,80 +1,87 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 3, + "filename": "/only_with_float.json", "line": 1, "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"float_value\"", - "value": "float_value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Float": 0.33 - } - } - } - } - } - } - ] + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" + } } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } } - }, - "kwargs": [], - "name": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "ctx": "Load", - "names": [ - "only_with_float" - ], - "pkgpath": "" - } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": "only_with_float" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json/only_with_null.ast.json index e1f07e137..afde4b451 100644 --- a/kclvm/tools/src/vet/test_datas/json/only_with_null.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/only_with_null.ast.json @@ -1,77 +1,84 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 3, + "filename": "/only_with_null.json", "line": 1, "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"null_value\"", - "value": "null_value" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NameConstantLit": { - "value": "None" - } - } - } - } - } - ] + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" + } } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } } - }, - "kwargs": [], - "name": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "ctx": "Load", - "names": [ - "only_with_null" - ], - "pkgpath": "" - } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": "only_with_null" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json/plain_value.k.ast.json index 6d5cb0433..3110dbc86 100644 --- a/kclvm/tools/src/vet/test_datas/json/plain_value.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/plain_value.k.ast.json @@ -1,15 +1,15 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 1 - } - } + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "/plain_value.k.json", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json/simple.k.ast.json index 5c2864b12..45841497c 100644 --- a/kclvm/tools/src/vet/test_datas/json/simple.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/simple.k.ast.json @@ -1,158 +1,165 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 5, + "filename": "/simple.k.json", "line": 1, "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 18 - } - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"message\"", - "value": "message" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"This is Alice\"", - "value": "This is Alice" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"Alice\"", - "value": "Alice" - } - } - } - } - } - ] + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } } - }, - "kwargs": [], - "name": { - "column": 1, + }, + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 5, + "filename": "/simple.k.json", "line": 1, "node": { - "ctx": "Load", - "names": [ - "simple" - ], - "pkgpath": "" + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": "simple" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json/test.k.ast.json index 954c074cc..2669ed139 100644 --- a/kclvm/tools/src/vet/test_datas/json/test.k.ast.json +++ b/kclvm/tools/src/vet/test_datas/json/test.k.ast.json @@ -1,302 +1,309 @@ { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Schema": { - "args": [], - "config": { - "column": 1, + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 12, + "filename": "/test.k.json", "line": 1, "node": { - "Config": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "/test.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "Config": { "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"address\"", - "value": "address" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "Config": { - "items": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"city\"", - "value": "city" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"London\"", - "value": "London" - } - } - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"street\"", - "value": "street" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"10 Downing Street\"", - "value": "10 Downing Street" - } - } - } - } - } - ] - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"age\"", - "value": "age" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "NumberLit": { - "binary_suffix": null, - "value": { - "Int": 43 - } - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + } + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "/test.k.json", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"name\"", - "value": "name" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"John Doe\"", - "value": "John Doe" - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" + } } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, "node": { - "insert_index": -1, - "key": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"phones\"", - "value": "phones" - } - } - }, - "operation": "Union", - "value": { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "List": { - "ctx": "Load", - "elts": [ - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"+44 1234567\"", - "value": "+44 1234567" - } - } - }, - { - "column": 1, - "end_column": 1, - "end_line": 1, - "filename": "", - "line": 1, - "node": { - "StringLit": { - "is_long_string": false, - "raw_value": "\"+44 2345678\"", - "value": "+44 2345678" - } - } - } - ] - } - } - } + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" + } } + } } + } ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } } - }, - "kwargs": [], - "name": { - "column": 1, + }, + { + "column": 0, "end_column": 1, - "end_line": 1, - "filename": "", + "end_line": 12, + "filename": "/test.k.json", "line": 1, "node": { - "ctx": "Load", - "names": [ - "test" - ], - "pkgpath": "" + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "/test.k.json", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "/test.k.json", + "line": 8, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "/test.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" + } + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "/test.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" + } + } + } + ] + } + } + } } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": "test" } + ], + "pkgpath": "" } + } } + } } \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str/complex.k.ast.json new file mode 100644 index 000000000..77bb882b7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/complex.k.ast.json @@ -0,0 +1,443 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "Config": { + "items": [ + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 12, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 15, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + } + } + }, + { + "column": 12, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 15, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + }, + "operation": "Union", + "value": { + "column": 17, + "end_column": 25, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 8, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 10, + "end_column": 19, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 11, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + }, + { + "column": 14, + "end_column": 15, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 + } + } + } + }, + { + "column": 17, + "end_column": 18, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 9, + "filename": "", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 9, + "node": { + "Config": { + "items": [ + { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 9, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 22, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 13, + "filename": "", + "line": 1, + "node": "complex" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/complex.k.json b/kclvm/tools/src/vet/test_datas/json_str/complex.k.json new file mode 100644 index 000000000..d3e9b575d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/complex.k.json @@ -0,0 +1,13 @@ +{ + "name": "Alice", + "age": 18, + "message": "This is Alice", + "data": { + "id": 1, + "value": "value1" + }, + "labels": { + "key": "value" + }, + "hc": [1, 2, 3] +} diff --git a/kclvm/tools/src/vet/test_datas/json_str/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str/list.k.ast.json new file mode 100644 index 000000000..8167b9857 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/list.k.ast.json @@ -0,0 +1,179 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 7, + "filename": "", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "Schema": { + "args": [], + "config": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "Config": { + "items": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 17, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 17, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 34, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 23, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 4, + "end_column": 5, + "end_line": 6, + "filename": "", + "line": 2, + "node": "list" + } + ], + "pkgpath": "" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/list.k.json b/kclvm/tools/src/vet/test_datas/json_str/list.k.json new file mode 100644 index 000000000..b6f772ebe --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/list.k.json @@ -0,0 +1,7 @@ +[ + { + "name": "Alice", + "age": 18, + "message": "This is Alice" + } +] diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.ast.json new file mode 100644 index 000000000..78a504fc7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 16, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_bool" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.json new file mode 100644 index 000000000..ca087fd5f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_bool.json @@ -0,0 +1,3 @@ +{ + "flag": true +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_float.ast.json new file mode 100644 index 000000000..d98c1a8ab --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_float.ast.json @@ -0,0 +1,87 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 17, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 23, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_float" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_float.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_float.json new file mode 100644 index 000000000..8f6133170 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_float.json @@ -0,0 +1,3 @@ +{ + "float_value": 0.33 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_null.ast.json new file mode 100644 index 000000000..04e2a4540 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_null.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 16, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 22, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_null" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/only_with_null.json b/kclvm/tools/src/vet/test_datas/json_str/only_with_null.json new file mode 100644 index 000000000..0578d4d6e --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/only_with_null.json @@ -0,0 +1,3 @@ +{ + "null_value": null +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.ast.json new file mode 100644 index 000000000..3d322f34f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.ast.json @@ -0,0 +1,15 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.json b/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.json new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/plain_value.k.json @@ -0,0 +1 @@ +1 diff --git a/kclvm/tools/src/vet/test_datas/json_str/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str/simple.k.ast.json new file mode 100644 index 000000000..373b8a71b --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/simple.k.ast.json @@ -0,0 +1,165 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 30, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 19, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 1, + "node": "simple" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/simple.k.json b/kclvm/tools/src/vet/test_datas/json_str/simple.k.json new file mode 100644 index 000000000..02fd725d1 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/simple.k.json @@ -0,0 +1,5 @@ +{ + "name": "Alice", + "age": 18, + "message": "This is Alice" +} diff --git a/kclvm/tools/src/vet/test_datas/json_str/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str/test.k.ast.json new file mode 100644 index 000000000..46dfd3472 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/test.k.ast.json @@ -0,0 +1,309 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 13, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "Config": { + "items": [ + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 14, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" + } + } + }, + "operation": "Union", + "value": { + "column": 16, + "end_column": 24, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" + } + } + } + } + }, + { + "column": 15, + "end_column": 5, + "end_line": 7, + "filename": "", + "line": 4, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 16, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 37, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 9, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 11, + "end_column": 13, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 10, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 12, + "end_column": 22, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } + } + }, + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 4, + "end_column": 12, + "end_line": 8, + "filename": "", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 14, + "end_column": 5, + "end_line": 11, + "filename": "", + "line": 8, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 8, + "end_column": 21, + "end_line": 9, + "filename": "", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" + } + } + }, + { + "column": 8, + "end_column": 21, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" + } + } + } + ] + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 1, + "node": "test" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str/test.k.json b/kclvm/tools/src/vet/test_datas/json_str/test.k.json new file mode 100644 index 000000000..e02809804 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str/test.k.json @@ -0,0 +1,12 @@ +{ + "name": "John Doe", + "age": 43, + "address": { + "street": "10 Downing Street", + "city": "London" + }, + "phones": [ + "+44 1234567", + "+44 2345678" + ] +} diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.ast.json new file mode 100644 index 000000000..8da01354f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.ast.json @@ -0,0 +1,443 @@ +{ + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 0, + "end_line": 6, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "", + "line": 6, + "node": { + "Config": { + "items": [ + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 0, + "end_line": 7, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 3, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + } + } + }, + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 14, + "end_column": 21, + "end_line": 7, + "filename": "", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 5, + "end_line": 8, + "filename": "", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 15, + "end_column": 19, + "end_line": 12, + "filename": "", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 10, + "end_line": 13, + "filename": "", + "line": 13, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 2, + "end_column": 3, + "end_line": 13, + "filename": "", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + }, + { + "column": 5, + "end_column": 6, + "end_line": 13, + "filename": "", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 + } + } + } + }, + { + "column": 8, + "end_column": 9, + "end_line": 13, + "filename": "", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 4, + "end_line": 10, + "filename": "", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "", + "line": 10, + "node": { + "Config": { + "items": [ + { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "", + "line": 10, + "node": { + "insert_index": -1, + "key": { + "column": 17, + "end_column": 22, + "end_line": 10, + "filename": "", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 1, + "end_line": 12, + "filename": "", + "line": 11, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "", + "line": 1, + "node": "complex" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.json b/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.json new file mode 100644 index 000000000..d3e9b575d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/complex.k.json @@ -0,0 +1,13 @@ +{ + "name": "Alice", + "age": 18, + "message": "This is Alice", + "data": { + "id": 1, + "value": "value1" + }, + "labels": { + "key": "value" + }, + "hc": [1, 2, 3] +} diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/list.k.ast.json new file mode 100644 index 000000000..17925c434 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/list.k.ast.json @@ -0,0 +1,179 @@ +{ + "column": 0, + "end_column": 7, + "end_line": 7, + "filename": "", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "Schema": { + "args": [], + "config": { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "Config": { + "items": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 16, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 21, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 3, + "end_line": 6, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 10, + "end_column": 16, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 0, + "end_line": 4, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 2, + "node": "list" + } + ], + "pkgpath": "" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/list.k.json b/kclvm/tools/src/vet/test_datas/json_str_win/list.k.json new file mode 100644 index 000000000..b6f772ebe --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/list.k.json @@ -0,0 +1,7 @@ +[ + { + "name": "Alice", + "age": 18, + "message": "This is Alice" + } +] diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.ast.json new file mode 100644 index 000000000..4794707cf --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 3, + "filename": "", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_bool" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.json new file mode 100644 index 000000000..ca087fd5f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_bool.json @@ -0,0 +1,3 @@ +{ + "flag": true +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.ast.json new file mode 100644 index 000000000..4efc9d4e1 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.ast.json @@ -0,0 +1,87 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 18, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" + } + } + }, + "operation": "Union", + "value": { + "column": 20, + "end_column": 0, + "end_line": 3, + "filename": "", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_float" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.json new file mode 100644 index 000000000..8f6133170 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_float.json @@ -0,0 +1,3 @@ +{ + "float_value": 0.33 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.ast.json new file mode 100644 index 000000000..e7d0f16df --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 17, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 0, + "end_line": 3, + "filename": "", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "", + "line": 1, + "node": "only_with_null" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.json b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.json new file mode 100644 index 000000000..0578d4d6e --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/only_with_null.json @@ -0,0 +1,3 @@ +{ + "null_value": null +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.ast.json new file mode 100644 index 000000000..3d322f34f --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.ast.json @@ -0,0 +1,15 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.json b/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.json new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/plain_value.k.json @@ -0,0 +1 @@ +1 diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.ast.json new file mode 100644 index 000000000..bf2c6061d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.ast.json @@ -0,0 +1,165 @@ +{ + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 2, + "end_line": 5, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "", + "line": 1, + "node": "simple" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.json b/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.json new file mode 100644 index 000000000..02fd725d1 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/simple.k.json @@ -0,0 +1,5 @@ +{ + "name": "Alice", + "age": 18, + "message": "This is Alice" +} diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json_str_win/test.k.ast.json new file mode 100644 index 000000000..94fbde486 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/test.k.ast.json @@ -0,0 +1,309 @@ +{ + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "Config": { + "items": [ + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 19, + "end_line": 6, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" + } + } + }, + "operation": "Union", + "value": { + "column": 21, + "end_column": 4, + "end_line": 7, + "filename": "", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" + } + } + } + } + }, + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 20, + "end_line": 5, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" + } + } + }, + "operation": "Union", + "value": { + "column": 22, + "end_column": 2, + "end_line": 6, + "filename": "", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 23, + "end_line": 2, + "filename": "", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 3, + "end_line": 9, + "filename": "", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 5, + "end_column": 9, + "end_line": 12, + "filename": "", + "line": 9, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 16, + "end_column": 6, + "end_line": 10, + "filename": "", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" + } + } + }, + { + "column": 17, + "end_column": 2, + "end_line": 12, + "filename": "", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" + } + } + } + ] + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "", + "line": 1, + "node": "test" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_str_win/test.k.json b/kclvm/tools/src/vet/test_datas/json_str_win/test.k.json new file mode 100644 index 000000000..e02809804 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_str_win/test.k.json @@ -0,0 +1,12 @@ +{ + "name": "John Doe", + "age": 43, + "address": { + "street": "10 Downing Street", + "city": "London" + }, + "phones": [ + "+44 1234567", + "+44 2345678" + ] +} diff --git a/kclvm/tools/src/vet/test_datas/json_win/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/complex.k.ast.json new file mode 100644 index 000000000..ecce3da6a --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/complex.k.ast.json @@ -0,0 +1,443 @@ +{ + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "/complex.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "/complex.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 0, + "end_line": 6, + "filename": "/complex.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "/complex.k.json", + "line": 6, + "node": { + "Config": { + "items": [ + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "/complex.k.json", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 0, + "end_line": 7, + "filename": "/complex.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 3, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + } + } + }, + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "/complex.k.json", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 14, + "end_column": 21, + "end_line": 7, + "filename": "/complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 5, + "end_line": 8, + "filename": "/complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 15, + "end_column": 19, + "end_line": 12, + "filename": "/complex.k.json", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 10, + "end_line": 13, + "filename": "/complex.k.json", + "line": 13, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 2, + "end_column": 3, + "end_line": 13, + "filename": "/complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + }, + { + "column": 5, + "end_column": 6, + "end_line": 13, + "filename": "/complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 + } + } + } + }, + { + "column": 8, + "end_column": 9, + "end_line": 13, + "filename": "/complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 4, + "end_line": 10, + "filename": "/complex.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 10, + "node": { + "Config": { + "items": [ + { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "/complex.k.json", + "line": 10, + "node": { + "insert_index": -1, + "key": { + "column": 17, + "end_column": 22, + "end_line": 10, + "filename": "/complex.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 1, + "end_line": 12, + "filename": "/complex.k.json", + "line": 11, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "/complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "/complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "/complex.k.json", + "line": 1, + "node": "complex" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/list.k.ast.json new file mode 100644 index 000000000..b8c212c40 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/list.k.ast.json @@ -0,0 +1,179 @@ +{ + "column": 0, + "end_column": 7, + "end_line": 7, + "filename": "/list.k.json", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "Schema": { + "args": [], + "config": { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "Config": { + "items": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 16, + "end_line": 4, + "filename": "/list.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "/list.k.json", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 21, + "end_line": 5, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 3, + "end_line": 6, + "filename": "/list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 10, + "end_column": 16, + "end_line": 3, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 0, + "end_line": 4, + "filename": "/list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": { + "ctx": "Load", + "names": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "/list.k.json", + "line": 2, + "node": "list" + } + ], + "pkgpath": "" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/complex.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/complex.k.ast.json new file mode 100644 index 000000000..5f74bd0af --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/complex.k.ast.json @@ -0,0 +1,409 @@ +{ + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "\\complex.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "\\complex.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 8, + "end_column": 0, + "end_line": 6, + "filename": "\\complex.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "\\complex.k.json", + "line": 6, + "node": { + "Config": { + "items": [ + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "\\complex.k.json", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 0, + "end_line": 7, + "filename": "\\complex.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + } + }, + "operation": "Union", + "value": { + "column": 2, + "end_column": 3, + "end_line": 7, + "filename": "\\complex.k.json", + "line": 7, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + } + } + }, + { + "column": 2, + "end_column": 5, + "end_line": 9, + "filename": "\\complex.k.json", + "line": 6, + "node": { + "insert_index": -1, + "key": { + "column": 14, + "end_column": 21, + "end_line": 7, + "filename": "\\complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 5, + "end_line": 8, + "filename": "\\complex.k.json", + "line": 7, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 15, + "end_column": 19, + "end_line": 12, + "filename": "\\complex.k.json", + "line": 12, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 10, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 13, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 2, + "end_column": 3, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } + }, + { + "column": 5, + "end_column": 6, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 2 + } + } + } + }, + { + "column": 8, + "end_column": 9, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 13, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 3 + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 4, + "end_line": 10, + "filename": "\\complex.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + } + }, + "operation": "Union", + "value": { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "\\complex.k.json", + "line": 10, + "node": { + "Config": { + "items": [ + { + "column": 6, + "end_column": 8, + "end_line": 12, + "filename": "\\complex.k.json", + "line": 10, + "node": { + "insert_index": -1, + "key": { + "column": 17, + "end_column": 22, + "end_line": 10, + "filename": "\\complex.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 1, + "end_line": 12, + "filename": "\\complex.k.json", + "line": 11, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "\\complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "\\complex.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 13, + "end_line": 13, + "filename": "\\complex.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "\\complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "\\complex.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/list.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/list.k.ast.json new file mode 100644 index 000000000..ad7f66fc7 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/list.k.ast.json @@ -0,0 +1,145 @@ +{ + "column": 0, + "end_column": 7, + "end_line": 7, + "filename": "\\list.k.json", + "line": 1, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "\\list.k.json", + "line": 2, + "node": { + "Config": { + "items": [ + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "\\list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 16, + "end_line": 4, + "filename": "\\list.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 1, + "end_line": 5, + "filename": "\\list.k.json", + "line": 4, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "\\list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 21, + "end_line": 5, + "filename": "\\list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 23, + "end_column": 3, + "end_line": 6, + "filename": "\\list.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 5, + "end_column": 4, + "end_line": 7, + "filename": "\\list.k.json", + "line": 2, + "node": { + "insert_index": -1, + "key": { + "column": 10, + "end_column": 16, + "end_line": 3, + "filename": "\\list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 0, + "end_line": 4, + "filename": "\\list.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_bool.ast.json new file mode 100644 index 000000000..f55ee7c62 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_bool.ast.json @@ -0,0 +1,50 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_bool.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_bool.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "\\only_with_bool.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 3, + "filename": "\\only_with_bool.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_float.ast.json new file mode 100644 index 000000000..608d85f9e --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_float.ast.json @@ -0,0 +1,53 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_float.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_float.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 18, + "end_line": 2, + "filename": "\\only_with_float.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" + } + } + }, + "operation": "Union", + "value": { + "column": 20, + "end_column": 0, + "end_line": 3, + "filename": "\\only_with_float.json", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_null.ast.json new file mode 100644 index 000000000..2d3731770 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/only_with_null.ast.json @@ -0,0 +1,50 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_null.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "\\only_with_null.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 17, + "end_line": 2, + "filename": "\\only_with_null.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 0, + "end_line": 3, + "filename": "\\only_with_null.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/plain_value.k.ast.json new file mode 100644 index 000000000..02f360fd3 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/plain_value.k.ast.json @@ -0,0 +1,15 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "\\plain_value.k.json", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/simple.k.ast.json new file mode 100644 index 000000000..4b5360af4 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/simple.k.ast.json @@ -0,0 +1,131 @@ +{ + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "\\simple.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "\\simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "\\simple.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "\\simple.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "\\simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "\\simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 2, + "end_line": 5, + "filename": "\\simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "\\simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "\\simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "\\simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/test.k.ast.json new file mode 100644 index 000000000..b11b921ce --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/no_schema_name/test.k.ast.json @@ -0,0 +1,275 @@ +{ + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "\\test.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "\\test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "\\test.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "\\test.k.json", + "line": 5, + "node": { + "Config": { + "items": [ + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "\\test.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 19, + "end_line": 6, + "filename": "\\test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" + } + } + }, + "operation": "Union", + "value": { + "column": 21, + "end_column": 4, + "end_line": 7, + "filename": "\\test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" + } + } + } + } + }, + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "\\test.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 20, + "end_line": 5, + "filename": "\\test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" + } + } + }, + "operation": "Union", + "value": { + "column": 22, + "end_column": 2, + "end_line": 6, + "filename": "\\test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "\\test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "\\test.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "\\test.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "\\test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "\\test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 23, + "end_line": 2, + "filename": "\\test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "\\test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 3, + "end_line": 9, + "filename": "\\test.k.json", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 5, + "end_column": 9, + "end_line": 12, + "filename": "\\test.k.json", + "line": 9, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 16, + "end_column": 6, + "end_line": 10, + "filename": "\\test.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" + } + } + }, + { + "column": 17, + "end_column": 2, + "end_line": 12, + "filename": "\\test.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" + } + } + } + ] + } + } + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/only_with_bool.ast.json b/kclvm/tools/src/vet/test_datas/json_win/only_with_bool.ast.json new file mode 100644 index 000000000..ce2204d12 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/only_with_bool.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"flag\"", + "value": "flag" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "True" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_bool.json", + "line": 1, + "node": "only_with_bool" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/only_with_float.ast.json b/kclvm/tools/src/vet/test_datas/json_win/only_with_float.ast.json new file mode 100644 index 000000000..d399bb08d --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/only_with_float.ast.json @@ -0,0 +1,87 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 18, + "end_line": 2, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"float_value\"", + "value": "float_value" + } + } + }, + "operation": "Union", + "value": { + "column": 20, + "end_column": 0, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 2, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Float": 0.33 + } + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_float.json", + "line": 1, + "node": "only_with_float" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/only_with_null.ast.json b/kclvm/tools/src/vet/test_datas/json_win/only_with_null.ast.json new file mode 100644 index 000000000..efa3c5353 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/only_with_null.ast.json @@ -0,0 +1,84 @@ +{ + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 17, + "end_line": 2, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"null_value\"", + "value": "null_value" + } + } + }, + "operation": "Union", + "value": { + "column": 19, + "end_column": 0, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 2, + "node": { + "NameConstantLit": { + "value": "None" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 3, + "end_line": 3, + "filename": "/only_with_null.json", + "line": 1, + "node": "only_with_null" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/plain_value.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/plain_value.k.ast.json new file mode 100644 index 000000000..3110dbc86 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/plain_value.k.ast.json @@ -0,0 +1,15 @@ +{ + "column": 0, + "end_column": 1, + "end_line": 1, + "filename": "/plain_value.k.json", + "line": 1, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 1 + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/simple.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/simple.k.ast.json new file mode 100644 index 000000000..af431e2bf --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/simple.k.ast.json @@ -0,0 +1,165 @@ +{ + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "/simple.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "/simple.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 18 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + } + }, + "operation": "Union", + "value": { + "column": 18, + "end_column": 2, + "end_line": 5, + "filename": "/simple.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + } + } + } + }, + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 20, + "end_line": 2, + "filename": "/simple.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 5, + "end_line": 5, + "filename": "/simple.k.json", + "line": 1, + "node": "simple" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/json_win/test.k.ast.json b/kclvm/tools/src/vet/test_datas/json_win/test.k.ast.json new file mode 100644 index 000000000..3d1fb6680 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/json_win/test.k.ast.json @@ -0,0 +1,309 @@ +{ + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "Schema": { + "args": [], + "config": { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "Config": { + "items": [ + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 7, + "end_column": 16, + "end_line": 4, + "filename": "/test.k.json", + "line": 4, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"address\"", + "value": "address" + } + } + }, + "operation": "Union", + "value": { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "/test.k.json", + "line": 5, + "node": { + "Config": { + "items": [ + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "/test.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 13, + "end_column": 19, + "end_line": 6, + "filename": "/test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"city\"", + "value": "city" + } + } + }, + "operation": "Union", + "value": { + "column": 21, + "end_column": 4, + "end_line": 7, + "filename": "/test.k.json", + "line": 6, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"London\"", + "value": "London" + } + } + } + } + }, + { + "column": 1, + "end_column": 4, + "end_line": 8, + "filename": "/test.k.json", + "line": 5, + "node": { + "insert_index": -1, + "key": { + "column": 12, + "end_column": 20, + "end_line": 5, + "filename": "/test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"street\"", + "value": "street" + } + } + }, + "operation": "Union", + "value": { + "column": 22, + "end_column": 2, + "end_line": 6, + "filename": "/test.k.json", + "line": 5, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"10 Downing Street\"", + "value": "10 Downing Street" + } + } + } + } + } + ] + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 6, + "end_column": 11, + "end_line": 3, + "filename": "/test.k.json", + "line": 3, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 0, + "end_line": 4, + "filename": "/test.k.json", + "line": 3, + "node": { + "NumberLit": { + "binary_suffix": null, + "value": { + "Int": 43 + } + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 5, + "end_column": 11, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + } + }, + "operation": "Union", + "value": { + "column": 13, + "end_column": 23, + "end_line": 2, + "filename": "/test.k.json", + "line": 2, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"John Doe\"", + "value": "John Doe" + } + } + } + } + }, + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "insert_index": -1, + "key": { + "column": 11, + "end_column": 3, + "end_line": 9, + "filename": "/test.k.json", + "line": 8, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"phones\"", + "value": "phones" + } + } + }, + "operation": "Union", + "value": { + "column": 5, + "end_column": 9, + "end_line": 12, + "filename": "/test.k.json", + "line": 9, + "node": { + "List": { + "ctx": "Load", + "elts": [ + { + "column": 16, + "end_column": 6, + "end_line": 10, + "filename": "/test.k.json", + "line": 9, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 1234567\"", + "value": "+44 1234567" + } + } + }, + { + "column": 17, + "end_column": 2, + "end_line": 12, + "filename": "/test.k.json", + "line": 10, + "node": { + "StringLit": { + "is_long_string": false, + "raw_value": "\"+44 2345678\"", + "value": "+44 2345678" + } + } + } + ] + } + } + } + } + } + ] + } + } + }, + "kwargs": [], + "name": { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": { + "ctx": "Load", + "names": [ + { + "column": 0, + "end_column": 12, + "end_line": 12, + "filename": "/test.k.json", + "line": 1, + "node": "test" + } + ], + "pkgpath": "" + } + } + } + } +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/complex.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/complex.k.ast.yaml index 0d7c301a6..994e9dd8e 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/complex.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/complex.k.ast.yaml @@ -1,296 +1,443 @@ -node: !Schema - name: - node: - names: - - complex - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice"' - value: Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 18 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"data"' - value: data - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"id"' - value: id - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"value"' - value: value - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"value1"' - value: value1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"labels"' - value: labels - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"key"' - value: key - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"value"' - value: value - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"hc"' - value: hc - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !List - elts: - - node: !NumberLit - binary_suffix: null - value: !Int 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !NumberLit - binary_suffix: null - value: !Int 2 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !NumberLit - binary_suffix: null - value: !Int 3 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "complex", + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/complex.k.yaml", + "line": 2, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 18 + } + } + }, + "filename": "/complex.k.yaml", + "line": 2, + "column": 5, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/complex.k.yaml", + "line": 3, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/complex.k.yaml", + "line": 3, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + }, + "filename": "/complex.k.yaml", + "line": 4, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + }, + "filename": "/complex.k.yaml", + "line": 6, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + }, + "filename": "/complex.k.yaml", + "line": 6, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + }, + "filename": "/complex.k.yaml", + "line": 7, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 7, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 7, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + }, + "filename": "/complex.k.yaml", + "line": 9, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!List": { + "elts": [ + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/complex.k.yaml", + "line": 10, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 2 + } + } + }, + "filename": "/complex.k.yaml", + "line": 11, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 3 + } + } + }, + "filename": "/complex.k.yaml", + "line": 12, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/complex.k.yaml", + "line": 10, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/list.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/list.k.ast.yaml index 91d0580bd..dbd19b9af 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/list.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/list.k.ast.yaml @@ -1,118 +1,179 @@ -node: !List - elts: - - node: !Schema - name: - node: - names: - - list - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice"' - value: Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 18 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!List": { + "elts": [ + { + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "list", + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/list.k.yaml", + "line": 2, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 18 + } + } + }, + "filename": "/list.k.yaml", + "line": 2, + "column": 7, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/list.k.yaml", + "line": 3, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/list.k.yaml", + "line": 3, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/complex.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/complex.k.ast.yaml index baa3ef6c6..45d0b3902 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/complex.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/complex.k.ast.yaml @@ -1,276 +1,409 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice"' - value: Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 18 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"data"' - value: data - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"id"' - value: id - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"value"' - value: value - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"value1"' - value: value1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"labels"' - value: labels - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"key"' - value: key - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"value"' - value: value - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"hc"' - value: hc - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !List - elts: - - node: !NumberLit - binary_suffix: null - value: !Int 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !NumberLit - binary_suffix: null - value: !Int 2 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !NumberLit - binary_suffix: null - value: !Int 3 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/complex.k.yaml", + "line": 2, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 18 + } + } + }, + "filename": "/complex.k.yaml", + "line": 2, + "column": 5, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/complex.k.yaml", + "line": 3, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/complex.k.yaml", + "line": 3, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"data\"", + "value": "data" + } + }, + "filename": "/complex.k.yaml", + "line": 4, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"id\"", + "value": "id" + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + }, + "filename": "/complex.k.yaml", + "line": 6, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value1\"", + "value": "value1" + } + }, + "filename": "/complex.k.yaml", + "line": 6, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 5, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"labels\"", + "value": "labels" + } + }, + "filename": "/complex.k.yaml", + "line": 7, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"key\"", + "value": "key" + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"value\"", + "value": "value" + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 7, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 8, + "column": 7, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"hc\"", + "value": "hc" + } + }, + "filename": "/complex.k.yaml", + "line": 9, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!List": { + "elts": [ + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/complex.k.yaml", + "line": 10, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 2 + } + } + }, + "filename": "/complex.k.yaml", + "line": 11, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 3 + } + } + }, + "filename": "/complex.k.yaml", + "line": 12, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/complex.k.yaml", + "line": 10, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/complex.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/list.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/list.k.ast.yaml index 93c2f07f0..e79438795 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/list.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/list.k.ast.yaml @@ -1,98 +1,145 @@ -node: !List - elts: - - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice"' - value: Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Int 18 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!List": { + "elts": [ + { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice\"", + "value": "Alice" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/list.k.yaml", + "line": 2, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 18 + } + } + }, + "filename": "/list.k.yaml", + "line": 2, + "column": 7, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/list.k.yaml", + "line": 3, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/list.k.yaml", + "line": 3, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/list.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_bool.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_bool.ast.yaml index 827ddedf7..fe0d8abda 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_bool.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_bool.ast.yaml @@ -1,33 +1,50 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"bool_val"' - value: bool_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NameConstantLit - value: 'True' - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"bool_val\"", + "value": "bool_val" + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NameConstantLit": { + "value": "True" + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_float.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_float.ast.yaml index d8bb37a03..931b4e4ed 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_float.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_float.ast.yaml @@ -1,34 +1,53 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"float_val"' - value: float_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Float 0.33 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"float_val\"", + "value": "float_val" + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Float": 0.33 + } + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_null.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_null.ast.yaml index ff036c9f4..9ddf82fb5 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_null.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/only_with_null.ast.yaml @@ -1,33 +1,50 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"null_val"' - value: null_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NameConstantLit - value: None - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"null_val\"", + "value": "null_val" + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NameConstantLit": { + "value": "None" + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/plain_value.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/plain_value.k.ast.yaml index 757c6399f..e94a58580 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/plain_value.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/plain_value.k.ast.yaml @@ -1,8 +1,15 @@ -node: !NumberLit - binary_suffix: null - value: !Int 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/plain_value.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/simple.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/simple.k.ast.yaml index 2dae0c79a..4a83ae487 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/simple.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/simple.k.ast.yaml @@ -1,91 +1,130 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice,"' - value: Alice, - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"18,"' - value: 18, - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice,\"", + "value": "Alice," + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/simple.k.yaml", + "line": 2, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"18,\"", + "value": "18," + } + }, + "filename": "/simple.k.yaml", + "line": 2, + "column": 5, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/simple.k.yaml", + "line": 3, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/simple.k.yaml", + "line": 3, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/test.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/test.k.ast.yaml index 2289b0e6c..dab696bad 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/test.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/no_schema_name/test.k.ast.yaml @@ -1,199 +1,288 @@ -node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"languages"' - value: languages - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !List - elts: - - node: !StringLit - is_long_string: false - raw_value: '"Ruby"' - value: Ruby - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !StringLit - is_long_string: false - raw_value: '"Perl"' - value: Perl - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !StringLit - is_long_string: false - raw_value: '"Python"' - value: Python - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"websites"' - value: websites - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"YAML"' - value: YAML - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"yaml.org"' - value: yaml.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Ruby"' - value: Ruby - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"ruby-lang.org"' - value: ruby-lang.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Python"' - value: Python - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"python.org"' - value: python.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Perl"' - value: Perl - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"use.perl.org"' - value: use.perl.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"languages\"", + "value": "languages" + } + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!List": { + "elts": [ + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Ruby\"", + "value": "Ruby" + } + }, + "filename": "/test.k.yaml", + "line": 2, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Perl\"", + "value": "Perl" + } + }, + "filename": "/test.k.yaml", + "line": 3, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Python\"", + "value": "Python" + } + }, + "filename": "/test.k.yaml", + "line": 4, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/test.k.yaml", + "line": 2, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"websites\"", + "value": "websites" + } + }, + "filename": "/test.k.yaml", + "line": 5, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"YAML\"", + "value": "YAML" + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"yaml.org\"", + "value": "yaml.org" + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Ruby\"", + "value": "Ruby" + } + }, + "filename": "/test.k.yaml", + "line": 7, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"ruby-lang.org\"", + "value": "ruby-lang.org" + } + }, + "filename": "/test.k.yaml", + "line": 7, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Python\"", + "value": "Python" + } + }, + "filename": "/test.k.yaml", + "line": 8, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"python.org\"", + "value": "python.org" + } + }, + "filename": "/test.k.yaml", + "line": 8, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Perl\"", + "value": "Perl" + } + }, + "filename": "/test.k.yaml", + "line": 9, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"use.perl.org\"", + "value": "use.perl.org" + } + }, + "filename": "/test.k.yaml", + "line": 9, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/only_with_bool.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/only_with_bool.ast.yaml index 642349be9..d0defd343 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/only_with_bool.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/only_with_bool.ast.yaml @@ -1,53 +1,84 @@ -node: !Schema - name: - node: - names: - - only_with_bool - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"bool_val"' - value: bool_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NameConstantLit - value: 'True' - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "only_with_bool", + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"bool_val\"", + "value": "bool_val" + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NameConstantLit": { + "value": "True" + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/only_with_bool.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/only_with_float.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/only_with_float.ast.yaml index a38f830d8..97e725388 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/only_with_float.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/only_with_float.ast.yaml @@ -1,54 +1,87 @@ -node: !Schema - name: - node: - names: - - only_with_float - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"float_val"' - value: float_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NumberLit - binary_suffix: null - value: !Float 0.33 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "only_with_float", + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"float_val\"", + "value": "float_val" + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Float": 0.33 + } + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 11, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/only_with_float.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/only_with_null.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/only_with_null.ast.yaml index babebbc5a..22ab167c1 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/only_with_null.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/only_with_null.ast.yaml @@ -1,53 +1,84 @@ -node: !Schema - name: - node: - names: - - only_with_null - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"null_val"' - value: null_val - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !NameConstantLit - value: None - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "only_with_null", + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"null_val\"", + "value": "null_val" + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!NameConstantLit": { + "value": "None" + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/only_with_null.yaml", + "line": 1, + "column": 8, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/plain_value.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/plain_value.k.ast.yaml index 757c6399f..e94a58580 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/plain_value.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/plain_value.k.ast.yaml @@ -1,8 +1,15 @@ -node: !NumberLit - binary_suffix: null - value: !Int 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!NumberLit": { + "binary_suffix": null, + "value": { + "!Int": 1 + } + } + }, + "filename": "/plain_value.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/simple.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/simple.k.ast.yaml index 765e71e61..e2898cb74 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/simple.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/simple.k.ast.yaml @@ -1,111 +1,164 @@ -node: !Schema - name: - node: - names: - - simple - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"name"' - value: name - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"Alice,"' - value: Alice, - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"age"' - value: age - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"18,"' - value: 18, - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"message"' - value: message - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"This is Alice"' - value: This is Alice - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "simple", + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"name\"", + "value": "name" + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Alice,\"", + "value": "Alice," + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"age\"", + "value": "age" + } + }, + "filename": "/simple.k.yaml", + "line": 2, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"18,\"", + "value": "18," + } + }, + "filename": "/simple.k.yaml", + "line": 2, + "column": 5, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"message\"", + "value": "message" + } + }, + "filename": "/simple.k.yaml", + "line": 3, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"This is Alice\"", + "value": "This is Alice" + } + }, + "filename": "/simple.k.yaml", + "line": 3, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/simple.k.yaml", + "line": 1, + "column": 4, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml/test.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml/test.k.ast.yaml index cf7887e1b..e65e74bed 100644 --- a/kclvm/tools/src/vet/test_datas/yaml/test.k.ast.yaml +++ b/kclvm/tools/src/vet/test_datas/yaml/test.k.ast.yaml @@ -1,219 +1,322 @@ -node: !Schema - name: - node: - names: - - test - pkgpath: '' - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - args: [] - kwargs: [] - config: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"languages"' - value: languages - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !List - elts: - - node: !StringLit - is_long_string: false - raw_value: '"Ruby"' - value: Ruby - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !StringLit - is_long_string: false - raw_value: '"Perl"' - value: Perl - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: !StringLit - is_long_string: false - raw_value: '"Python"' - value: Python - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - ctx: Load - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"websites"' - value: websites - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !Config - items: - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"YAML"' - value: YAML - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"yaml.org"' - value: yaml.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Ruby"' - value: Ruby - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"ruby-lang.org"' - value: ruby-lang.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Python"' - value: Python - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"python.org"' - value: python.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - - node: - key: - node: !StringLit - is_long_string: false - raw_value: '"Perl"' - value: Perl - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - value: - node: !StringLit - is_long_string: false - raw_value: '"use.perl.org"' - value: use.perl.org - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - operation: Union - insert_index: -1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 - filename: '' - line: 1 - column: 1 - end_line: 1 - end_column: 1 -filename: '' -line: 1 -column: 1 -end_line: 1 -end_column: 1 \ No newline at end of file +{ + "node": { + "!Schema": { + "name": { + "node": { + "names": [ + { + "node": "test", + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ], + "pkgpath": "", + "ctx": "Load" + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + "args": [], + "kwargs": [], + "config": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"languages\"", + "value": "languages" + } + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!List": { + "elts": [ + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Ruby\"", + "value": "Ruby" + } + }, + "filename": "/test.k.yaml", + "line": 2, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Perl\"", + "value": "Perl" + } + }, + "filename": "/test.k.yaml", + "line": 3, + "column": 4, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Python\"", + "value": "Python" + } + }, + "filename": "/test.k.yaml", + "line": 4, + "column": 4, + "end_line": 0, + "end_column": 0 + } + ], + "ctx": "Load" + } + }, + "filename": "/test.k.yaml", + "line": 2, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"websites\"", + "value": "websites" + } + }, + "filename": "/test.k.yaml", + "line": 5, + "column": 0, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!Config": { + "items": [ + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"YAML\"", + "value": "YAML" + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"yaml.org\"", + "value": "yaml.org" + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Ruby\"", + "value": "Ruby" + } + }, + "filename": "/test.k.yaml", + "line": 7, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"ruby-lang.org\"", + "value": "ruby-lang.org" + } + }, + "filename": "/test.k.yaml", + "line": 7, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Python\"", + "value": "Python" + } + }, + "filename": "/test.k.yaml", + "line": 8, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"python.org\"", + "value": "python.org" + } + }, + "filename": "/test.k.yaml", + "line": 8, + "column": 10, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + { + "node": { + "key": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"Perl\"", + "value": "Perl" + } + }, + "filename": "/test.k.yaml", + "line": 9, + "column": 2, + "end_line": 0, + "end_column": 0 + }, + "value": { + "node": { + "!StringLit": { + "is_long_string": false, + "raw_value": "\"use.perl.org\"", + "value": "use.perl.org" + } + }, + "filename": "/test.k.yaml", + "line": 9, + "column": 8, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/test.k.yaml", + "line": 6, + "column": 6, + "end_line": 0, + "end_column": 0 + }, + "operation": "Union", + "insert_index": -1 + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + ] + } + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 + } + } + }, + "filename": "/test.k.yaml", + "line": 1, + "column": 9, + "end_line": 0, + "end_column": 0 +} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/complex.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/complex.k.ast.yaml new file mode 100644 index 000000000..5047ccbaf --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/complex.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"complex","filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/complex.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"}},"filename":"/complex.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/complex.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":18}}},"filename":"/complex.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/complex.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/complex.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"data\"","value":"data"}},"filename":"/complex.k.yaml","line":4,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"id\"","value":"id"}},"filename":"/complex.k.yaml","line":5,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/complex.k.yaml","line":5,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value\"","value":"value"}},"filename":"/complex.k.yaml","line":6,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value1\"","value":"value1"}},"filename":"/complex.k.yaml","line":6,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"labels\"","value":"labels"}},"filename":"/complex.k.yaml","line":7,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"key\"","value":"key"}},"filename":"/complex.k.yaml","line":8,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value\"","value":"value"}},"filename":"/complex.k.yaml","line":8,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"hc\"","value":"hc"}},"filename":"/complex.k.yaml","line":9,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!List":{"elts":[{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/complex.k.yaml","line":10,"column":6,"end_line":0,"end_column":0},{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":2}}},"filename":"/complex.k.yaml","line":11,"column":6,"end_line":0,"end_column":0},{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":3}}},"filename":"/complex.k.yaml","line":12,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/complex.k.yaml","line":10,"column":4,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}}},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/list.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/list.k.ast.yaml new file mode 100644 index 000000000..0049e35fa --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/list.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!List":{"elts":[{"node":{"!Schema":{"name":{"node":{"names":[{"node":"list","filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/list.k.yaml","line":1,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"}},"filename":"/list.k.yaml","line":1,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/list.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":18}}},"filename":"/list.k.yaml","line":2,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/list.k.yaml","line":3,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/list.k.yaml","line":3,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}]}},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}}},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/list.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/complex.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/complex.k.ast.yaml new file mode 100644 index 000000000..9c87a26d4 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/complex.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/complex.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"}},"filename":"/complex.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/complex.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":18}}},"filename":"/complex.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/complex.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/complex.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"data\"","value":"data"}},"filename":"/complex.k.yaml","line":4,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"id\"","value":"id"}},"filename":"/complex.k.yaml","line":5,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/complex.k.yaml","line":5,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value\"","value":"value"}},"filename":"/complex.k.yaml","line":6,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value1\"","value":"value1"}},"filename":"/complex.k.yaml","line":6,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":5,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"labels\"","value":"labels"}},"filename":"/complex.k.yaml","line":7,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"key\"","value":"key"}},"filename":"/complex.k.yaml","line":8,"column":4,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"value\"","value":"value"}},"filename":"/complex.k.yaml","line":8,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":8,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"hc\"","value":"hc"}},"filename":"/complex.k.yaml","line":9,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!List":{"elts":[{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/complex.k.yaml","line":10,"column":6,"end_line":0,"end_column":0},{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":2}}},"filename":"/complex.k.yaml","line":11,"column":6,"end_line":0,"end_column":0},{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":3}}},"filename":"/complex.k.yaml","line":12,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/complex.k.yaml","line":10,"column":4,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]}},"filename":"/complex.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/list.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/list.k.ast.yaml new file mode 100644 index 000000000..4f1ba042b --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/list.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!List":{"elts":[{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/list.k.yaml","line":1,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice\"","value":"Alice"}},"filename":"/list.k.yaml","line":1,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/list.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":18}}},"filename":"/list.k.yaml","line":2,"column":7,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/list.k.yaml","line":3,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/list.k.yaml","line":3,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}]}},"filename":"/list.k.yaml","line":1,"column":6,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/list.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_bool.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_bool.ast.yaml new file mode 100644 index 000000000..15f8b70f0 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_bool.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"bool_val\"","value":"bool_val"}},"filename":"/only_with_bool.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NameConstantLit":{"value":"True"}},"filename":"/only_with_bool.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}]}},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_float.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_float.ast.yaml new file mode 100644 index 000000000..74b3498fc --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_float.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"float_val\"","value":"float_val"}},"filename":"/only_with_float.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Float":0.33}}},"filename":"/only_with_float.yaml","line":1,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}]}},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_null.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_null.ast.yaml new file mode 100644 index 000000000..d488b40f9 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/only_with_null.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"null_val\"","value":"null_val"}},"filename":"/only_with_null.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NameConstantLit":{"value":"None"}},"filename":"/only_with_null.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}]}},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/plain_value.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/plain_value.k.ast.yaml new file mode 100644 index 000000000..77ee8b2ff --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/plain_value.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/plain_value.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/simple.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/simple.k.ast.yaml new file mode 100644 index 000000000..d43c49020 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/simple.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/simple.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice,\"","value":"Alice,"}},"filename":"/simple.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/simple.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"18,\"","value":"18,"}},"filename":"/simple.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/simple.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/simple.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]}},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/test.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/test.k.ast.yaml new file mode 100644 index 000000000..e6ab4d182 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/no_schema_name/test.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"languages\"","value":"languages"}},"filename":"/test.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!List":{"elts":[{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"}},"filename":"/test.k.yaml","line":2,"column":4,"end_line":0,"end_column":0},{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"}},"filename":"/test.k.yaml","line":3,"column":4,"end_line":0,"end_column":0},{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Python\"","value":"Python"}},"filename":"/test.k.yaml","line":4,"column":4,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/test.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"websites\"","value":"websites"}},"filename":"/test.k.yaml","line":5,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"YAML\"","value":"YAML"}},"filename":"/test.k.yaml","line":6,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"yaml.org\"","value":"yaml.org"}},"filename":"/test.k.yaml","line":6,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"}},"filename":"/test.k.yaml","line":7,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"ruby-lang.org\"","value":"ruby-lang.org"}},"filename":"/test.k.yaml","line":7,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Python\"","value":"Python"}},"filename":"/test.k.yaml","line":8,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"python.org\"","value":"python.org"}},"filename":"/test.k.yaml","line":8,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"}},"filename":"/test.k.yaml","line":9,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"use.perl.org\"","value":"use.perl.org"}},"filename":"/test.k.yaml","line":9,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0}]}},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}]}},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/only_with_bool.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_bool.ast.yaml new file mode 100644 index 000000000..497ce691e --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_bool.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"only_with_bool","filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"bool_val\"","value":"bool_val"}},"filename":"/only_with_bool.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NameConstantLit":{"value":"True"}},"filename":"/only_with_bool.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}]}},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0}}},"filename":"/only_with_bool.yaml","line":1,"column":8,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/only_with_float.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_float.ast.yaml new file mode 100644 index 000000000..ca5c407b6 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_float.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"only_with_float","filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"float_val\"","value":"float_val"}},"filename":"/only_with_float.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Float":0.33}}},"filename":"/only_with_float.yaml","line":1,"column":11,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}]}},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0}}},"filename":"/only_with_float.yaml","line":1,"column":9,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/only_with_null.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_null.ast.yaml new file mode 100644 index 000000000..4435356de --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/only_with_null.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"only_with_null","filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"null_val\"","value":"null_val"}},"filename":"/only_with_null.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!NameConstantLit":{"value":"None"}},"filename":"/only_with_null.yaml","line":1,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}]}},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0}}},"filename":"/only_with_null.yaml","line":1,"column":8,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/plain_value.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/plain_value.k.ast.yaml new file mode 100644 index 000000000..77ee8b2ff --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/plain_value.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!NumberLit":{"binary_suffix":null,"value":{"!Int":1}}},"filename":"/plain_value.k.yaml","line":1,"column":0,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/simple.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/simple.k.ast.yaml new file mode 100644 index 000000000..578b80342 --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/simple.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"simple","filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"name\"","value":"name"}},"filename":"/simple.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Alice,\"","value":"Alice,"}},"filename":"/simple.k.yaml","line":1,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"age\"","value":"age"}},"filename":"/simple.k.yaml","line":2,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"18,\"","value":"18,"}},"filename":"/simple.k.yaml","line":2,"column":5,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"message\"","value":"message"}},"filename":"/simple.k.yaml","line":3,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"This is Alice\"","value":"This is Alice"}},"filename":"/simple.k.yaml","line":3,"column":9,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}]}},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0}}},"filename":"/simple.k.yaml","line":1,"column":4,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/test_datas/yaml_win/test.k.ast.yaml b/kclvm/tools/src/vet/test_datas/yaml_win/test.k.ast.yaml new file mode 100644 index 000000000..5bb5163ca --- /dev/null +++ b/kclvm/tools/src/vet/test_datas/yaml_win/test.k.ast.yaml @@ -0,0 +1 @@ +{"node":{"!Schema":{"name":{"node":{"names":[{"node":"test","filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}],"pkgpath":"","ctx":"Load"},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},"args":[],"kwargs":[],"config":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"languages\"","value":"languages"}},"filename":"/test.k.yaml","line":1,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!List":{"elts":[{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"}},"filename":"/test.k.yaml","line":2,"column":4,"end_line":0,"end_column":0},{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"}},"filename":"/test.k.yaml","line":3,"column":4,"end_line":0,"end_column":0},{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Python\"","value":"Python"}},"filename":"/test.k.yaml","line":4,"column":4,"end_line":0,"end_column":0}],"ctx":"Load"}},"filename":"/test.k.yaml","line":2,"column":2,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"websites\"","value":"websites"}},"filename":"/test.k.yaml","line":5,"column":0,"end_line":0,"end_column":0},"value":{"node":{"!Config":{"items":[{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"YAML\"","value":"YAML"}},"filename":"/test.k.yaml","line":6,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"yaml.org\"","value":"yaml.org"}},"filename":"/test.k.yaml","line":6,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Ruby\"","value":"Ruby"}},"filename":"/test.k.yaml","line":7,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"ruby-lang.org\"","value":"ruby-lang.org"}},"filename":"/test.k.yaml","line":7,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Python\"","value":"Python"}},"filename":"/test.k.yaml","line":8,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"python.org\"","value":"python.org"}},"filename":"/test.k.yaml","line":8,"column":10,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},{"node":{"key":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"Perl\"","value":"Perl"}},"filename":"/test.k.yaml","line":9,"column":2,"end_line":0,"end_column":0},"value":{"node":{"!StringLit":{"is_long_string":false,"raw_value":"\"use.perl.org\"","value":"use.perl.org"}},"filename":"/test.k.yaml","line":9,"column":8,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0}]}},"filename":"/test.k.yaml","line":6,"column":6,"end_line":0,"end_column":0},"operation":"Union","insert_index":-1},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}]}},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0}}},"filename":"/test.k.yaml","line":1,"column":9,"end_line":0,"end_column":0} \ No newline at end of file diff --git a/kclvm/tools/src/vet/tests.rs b/kclvm/tools/src/vet/tests.rs index 3d89865b1..b250847fd 100644 --- a/kclvm/tools/src/vet/tests.rs +++ b/kclvm/tools/src/vet/tests.rs @@ -14,7 +14,6 @@ pub(crate) fn rel_path() -> String { .display() .to_string() } -const NO_SCHEMA_NAME_PATH: &str = "no_schema_name"; const TEST_CASES: &[&str] = &[ "test.k", @@ -44,7 +43,7 @@ const LOADER_KIND: [&LoaderKind; 2] = [&LoaderKind::JSON, &LoaderKind::YAML]; const INVALID_FILE_RESULT: &[&str] = &[ "Failed to Load JSON\n\nCaused by:\n 0: Failed to String 'languages:\n - Ruby\n ' to Json\n 1: expected value at line 1 column 1", -"Failed to Load YAML\n\nCaused by:\n 0: Failed to String '{\n \"name\": \"John Doe\",\n \"city\": \"London\"\n invalid\n \n ' to Yaml\n 1: did not find expected ',' or '}' at line 4 column 1, while parsing a flow mapping" +"Failed to Load YAML\n\nCaused by:\n 0: Failed to String '{\n \"name\": \"John Doe\",\n \"city\": \"London\"\n invalid\n \n ' to Yaml\n 1: while parsing a flow mapping, did not find expected ',' or '}' at line 4 column 1" ]; fn construct_full_path(path: &str) -> Result { @@ -73,26 +72,20 @@ mod test_expr_builder { vet::{ expr_builder::ExprBuilder, tests::{ - construct_full_path, FILE_EXTENSIONS, INVALID_FILE_RESULT, LOADER_KIND, - NO_SCHEMA_NAME_PATH, SCHEMA_NAMES, TEST_CASES, + construct_full_path, deal_windows_filepath, FILE_EXTENSIONS, INVALID_FILE_RESULT, + LOADER_KIND, SCHEMA_NAMES, TEST_CASES, }, }, }; - use std::{ - fs::{self, File}, - panic, - path::Path, - }; + use std::{fs, panic, path::Path}; #[test] + #[cfg(not(target_os = "windows"))] fn test_build_with_json_no_schema_name() { for test_name in TEST_CASES { let file_path = construct_full_path(&format!( "{}.{}", - Path::new(FILE_EXTENSIONS[0]) - .join(test_name) - .display() - .to_string(), + Path::new(FILE_EXTENSIONS[0]).join(test_name).display(), FILE_EXTENSIONS[0] )) .unwrap(); @@ -101,19 +94,16 @@ mod test_expr_builder { let expr_ast = expr_builder.build(None).unwrap(); let got_ast_json = serde_json::to_value(&expr_ast).unwrap(); - let expect_file_path = construct_full_path(&format!( - "{}.{}", - Path::new(FILE_EXTENSIONS[0]) - .join(NO_SCHEMA_NAME_PATH) - .join(test_name) - .display() - .to_string(), - FILE_EXTENSIONS[2] - )) - .unwrap(); - let f = File::open(expect_file_path.clone()).unwrap(); - let expect_ast_json: serde_json::Value = serde_json::from_reader(f).unwrap(); - assert_eq!(expect_ast_json, got_ast_json) + let got_ast_json_str = serde_json::to_string_pretty(&got_ast_json) + .unwrap() + .replace( + &deal_windows_filepath(construct_full_path("json").unwrap(), |s| { + s.replace('\\', "\\\\") + }), + "", + ); + + insta::assert_snapshot!(got_ast_json_str); } } @@ -130,21 +120,19 @@ mod test_expr_builder { let expr_ast = expr_builder.build(None).unwrap(); let got_ast_yaml = serde_yaml::to_value(&expr_ast).unwrap(); - let expect_file_path = construct_full_path(&format!( - "{}/{}/{}.{}", - FILE_EXTENSIONS[1], NO_SCHEMA_NAME_PATH, test_name, FILE_EXTENSIONS[3] - )) - .unwrap(); - let f = File::open(expect_file_path.clone()).unwrap(); - let expect_ast_yaml: serde_yaml::Value = serde_yaml::from_reader(f).unwrap(); - if expect_ast_yaml != got_ast_yaml { - serde_yaml::to_writer(std::io::stdout(), &got_ast_yaml).unwrap(); - } - assert_eq!(expect_ast_yaml, got_ast_yaml) + let got_ast_yaml_str = serde_json::to_string(&got_ast_yaml).unwrap().replace( + &deal_windows_filepath(construct_full_path("yaml").unwrap(), |s| { + s.replace('\\', "\\\\") + }), + "", + ); + + insta::assert_snapshot!(got_ast_yaml_str) } } #[test] + #[cfg(not(target_os = "windows"))] /// Test `expr_builder.build()` with input json files. fn test_build_json_with_filepath() { for i in 0..TEST_CASES.len() { @@ -157,18 +145,21 @@ mod test_expr_builder { .unwrap(); let got_ast_json = serde_json::to_value(&expr_ast).unwrap(); - let expect_file_path = construct_full_path(&format!( - "{}/{}.{}", - FILE_EXTENSIONS[0], TEST_CASES[i], FILE_EXTENSIONS[2] - )) - .unwrap(); - let f = File::open(expect_file_path.clone()).unwrap(); - let expect_ast_json: serde_json::Value = serde_json::from_reader(f).unwrap(); - assert_eq!(expect_ast_json, got_ast_json) + let got_ast_json_str = serde_json::to_string_pretty(&got_ast_json) + .unwrap() + .replace( + &deal_windows_filepath(construct_full_path("json").unwrap(), |s| { + s.replace('\\', "\\\\") + }), + "", + ); + + insta::assert_snapshot!(got_ast_json_str); } } #[test] + #[cfg(not(target_os = "windows"))] /// Test `expr_builder.build()` with input json files. fn test_build_json_with_str() { for i in 0..TEST_CASES.len() { @@ -184,14 +175,16 @@ mod test_expr_builder { .unwrap(); let got_ast_json = serde_json::to_value(&expr_ast).unwrap(); - let expect_file_path = construct_full_path(&format!( - "{}/{}.{}", - FILE_EXTENSIONS[0], TEST_CASES[i], FILE_EXTENSIONS[2] - )) - .unwrap(); - let f = File::open(expect_file_path.clone()).unwrap(); - let expect_ast_json: serde_json::Value = serde_json::from_reader(f).unwrap(); - assert_eq!(expect_ast_json, got_ast_json) + let got_ast_json_str = serde_json::to_string_pretty(&got_ast_json) + .unwrap() + .replace( + &deal_windows_filepath(construct_full_path("json").unwrap(), |s| { + s.replace('\\', "\\\\") + }), + "", + ); + + insta::assert_snapshot!(got_ast_json_str); } } @@ -208,14 +201,14 @@ mod test_expr_builder { .unwrap(); let got_ast_yaml = serde_yaml::to_value(&expr_ast).unwrap(); - let expect_file_path = construct_full_path(&format!( - "{}/{}.{}", - FILE_EXTENSIONS[1], TEST_CASES[i], FILE_EXTENSIONS[3] - )) - .unwrap(); - let f = File::open(expect_file_path.clone()).unwrap(); - let expect_ast_yaml: serde_yaml::Value = serde_yaml::from_reader(f).unwrap(); - assert_eq!(expect_ast_yaml, got_ast_yaml) + let got_ast_yaml_str = serde_json::to_string(&got_ast_yaml).unwrap().replace( + &deal_windows_filepath(construct_full_path("yaml").unwrap(), |s| { + s.replace('\\', "\\\\") + }), + "", + ); + + insta::assert_snapshot!(got_ast_yaml_str); } } @@ -318,35 +311,26 @@ mod test_expr_builder { panic!("unreachable") } Err(err) => { - assert_eq!(format!("{:?}", err), "Failed to Load YAML\n\nCaused by:\n 0: Failed to load the validated file\n 1: Failed to load the validated file, Unsupported Unsigned 64"); - } - }; - } - - #[test] - fn test_unsupported_yaml_with_tag() { - // unsupported yaml with tag - let file_path = construct_full_path("invalid/unsupported/yaml_with_tag.yaml").unwrap(); - let expr_builder = ExprBuilder::new_with_file_path(*LOADER_KIND[1], file_path).unwrap(); - match expr_builder.build(None) { - Ok(_) => { - panic!("unreachable") - } - Err(err) => { - assert_eq!(format!("{:?}", err), "Failed to Load YAML\n\nCaused by:\n Failed to load the validated file, Unsupported Yaml tag !mytag"); + assert_eq!(format!("{:?}", err), "Failed to Load YAML\n\nCaused by:\n 0: Failed to load the validated file\n 1: Failed to load the validated file, Unsupported Number Type"); } }; } } mod test_validater { - use std::{fs, panic, path::Path}; + use std::{ + fs, panic, + path::{Path, PathBuf}, + }; use regex::Regex; use crate::{ util::loader::LoaderKind, - vet::validator::{validate, ValidateOption}, + vet::{ + tests::deal_windows_filepath, + validator::{validate, ValidateOption}, + }, }; use super::{construct_full_path, LOADER_KIND}; @@ -369,6 +353,10 @@ mod test_validater { println!("test_validate_with_invalid_file_path - PASS"); test_validate_with_invalid_file_type(); println!("test_validate_with_invalid_file_type - PASS"); + test_invalid_validate_with_json_pos(); + println!("test_invalid_validate_with_json_pos - PASS"); + test_invalid_validate_with_yaml_pos(); + println!("test_invalid_validate_with_yaml_pos - PASS"); } fn test_validate() { @@ -376,7 +364,7 @@ mod test_validater { for case in KCL_TEST_CASES { let validated_file_path = construct_full_path(&format!( "{}.{}", - Path::new("validate_cases").join(case).display().to_string(), + Path::new("validate_cases").join(case).display(), file_suffix )) .unwrap(); @@ -403,15 +391,122 @@ mod test_validater { } } - fn test_invalid_validate() { - for (i, file_suffix) in VALIDATED_FILE_TYPE.iter().enumerate() { + fn test_invalid_validate_with_json_pos() { + let root_path = PathBuf::from(construct_full_path("invalid_vet_cases_json").unwrap()) + .canonicalize() + .unwrap(); + for (i, _) in VALIDATED_FILE_TYPE.iter().enumerate() { for case in KCL_TEST_CASES { let validated_file_path = construct_full_path(&format!( "{}.{}", - Path::new("invalid_validate_cases") + Path::new("invalid_vet_cases_json").join(case).display(), + "json" + )) + .unwrap(); + + let kcl_code = fs::read_to_string( + construct_full_path( + &Path::new("invalid_vet_cases_json") + .join(case) + .display() + .to_string(), + ) + .unwrap(), + ) + .expect("Something went wrong reading the file"); + + let kcl_path = construct_full_path( + &Path::new("invalid_vet_cases_json") + .join(case) + .display() + .to_string(), + ) + .unwrap(); + + let opt = ValidateOption::new( + None, + "value".to_string(), + validated_file_path.clone(), + *LOADER_KIND[i], + Some(kcl_path), + Some(kcl_code), + ); + + let result = validate(opt).unwrap_err(); + println!("{}", result); + assert!( + result.to_string().replace('\\', "").contains( + &deal_windows_filepath(root_path.join(case).display().to_string(), |s| { + s.replace('\\', "\\\\") + }) + .replace('\\', "") + ), + "{result}" + ); + } + } + } + + fn test_invalid_validate_with_yaml_pos() { + let root_path = PathBuf::from(construct_full_path("invalid_vet_cases_yaml").unwrap()) + .canonicalize() + .unwrap(); + for case in KCL_TEST_CASES { + let validated_file_path = construct_full_path(&format!( + "{}.{}", + Path::new("invalid_vet_cases_yaml").join(case).display(), + "yaml" + )) + .unwrap(); + + let kcl_code = fs::read_to_string( + construct_full_path( + &Path::new("invalid_vet_cases_yaml") .join(case) .display() .to_string(), + ) + .unwrap(), + ) + .expect("Something went wrong reading the file"); + + let kcl_path = construct_full_path( + &Path::new("invalid_vet_cases_yaml") + .join(case) + .display() + .to_string(), + ) + .unwrap(); + + let opt = ValidateOption::new( + None, + "value".to_string(), + validated_file_path.clone(), + LoaderKind::YAML, + Some(kcl_path), + Some(kcl_code), + ); + + let result = validate(opt).unwrap_err(); + println!("{}", result); + assert!( + result.to_string().replace('\\', "").contains( + &deal_windows_filepath(root_path.join(case).display().to_string(), |s| { + s.replace('\\', "\\\\") + }) + .replace('\\', "") + ), + "{result}" + ); + } + } + + fn test_invalid_validate() { + for (i, file_suffix) in VALIDATED_FILE_TYPE.iter().enumerate() { + for case in KCL_TEST_CASES { + let validated_file_path = construct_full_path(&format!( + "{}.{}", + Path::new("invalid_validate_cases").join(case).display(), file_suffix )) .unwrap(); @@ -437,7 +532,7 @@ mod test_validater { ); let result = validate(opt).unwrap_err(); - assert!(result.contains("Error"), "{result}"); + assert!(result.to_string().contains("Error"), "{result}"); } } } @@ -461,7 +556,7 @@ mod test_validater { r"^Failed to load KCL file 'validationTempKCLCode.k'. Because .*" ) .unwrap() - .is_match(&err)) + .is_match(&err.to_string())) } } } @@ -475,7 +570,7 @@ mod test_validater { let opt = ValidateOption::new( None, "value".to_string(), - "The validated file path is invalid".to_string(), + "invalid/file/path".to_string(), LoaderKind::JSON, None, Some(kcl_code), @@ -486,7 +581,7 @@ mod test_validater { panic!("unreachable") } Err(err) => { - assert_eq!(err, "Failed to load validated file.") + assert_eq!(err.to_string(), "Failed to Load 'invalid/file/path'") } } } @@ -514,8 +609,28 @@ mod test_validater { panic!("unreachable") } Err(err) => { - assert_eq!(err, "Failed to load validated file.") + assert_eq!(err.to_string(), "Failed to Load JSON") } } } } + +/// Deal with windows filepath +#[allow(unused)] +fn deal_windows_filepath(filepath: String, transform: F) -> String +where + F: FnOnce(String) -> String, +{ + #[cfg(not(target_os = "windows"))] + return filepath; + #[cfg(target_os = "windows")] + { + use kclvm_utils::path::PathPrefix; + let path = PathBuf::from(filepath) + .canonicalize() + .unwrap() + .display() + .to_string(); + return transform(Path::new(&path).adjust_canonicalization()); + } +} diff --git a/kclvm/tools/src/vet/validator.rs b/kclvm/tools/src/vet/validator.rs index 568b09a64..b7dced16f 100644 --- a/kclvm/tools/src/vet/validator.rs +++ b/kclvm/tools/src/vet/validator.rs @@ -66,11 +66,12 @@ //! ``` use super::expr_builder::ExprBuilder; pub use crate::util::loader::LoaderKind; +use anyhow::Result; use kclvm_ast::{ ast::{AssignStmt, Expr, ExprContext, Identifier, Module, Node, NodeRef, SchemaStmt, Stmt}, node_ref, }; -use kclvm_runner::execute_module; +use kclvm_runner::{execute_module, MapErrorResult}; const TMP_FILE: &str = "validationTempKCLCode.k"; @@ -170,13 +171,13 @@ const TMP_FILE: &str = "validationTempKCLCode.k"; /// "is_warning": false /// } /// ``` -pub fn validate(val_opt: ValidateOption) -> Result { +pub fn validate(val_opt: ValidateOption) -> Result { let k_path = match val_opt.kcl_path { Some(path) => path, None => TMP_FILE.to_string(), }; - let mut module = kclvm_parser::parse_file(&k_path, val_opt.kcl_code)?; + let mut module = kclvm_parser::parse_file_force_errors(&k_path, val_opt.kcl_code)?; let schemas = filter_schema_stmt(&module); let schema_name = match val_opt.schema_name { @@ -185,29 +186,25 @@ pub fn validate(val_opt: ValidateOption) -> Result { }; let expr_builder = - ExprBuilder::new_with_file_path(val_opt.validated_file_kind, val_opt.validated_file_path) - .map_err(|_| "Failed to load validated file.".to_string())?; + ExprBuilder::new_with_file_path(val_opt.validated_file_kind, val_opt.validated_file_path)?; - let validated_expr = expr_builder - .build(schema_name) - .map_err(|_| "Failed to load validated file.".to_string())?; + let validated_expr = expr_builder.build(schema_name)?; let assign_stmt = build_assign(&val_opt.attribute_name, validated_expr); module.body.insert(0, assign_stmt); - execute_module(module).map(|_| true) + execute_module(module).map_err_to_result().map(|_| true) } fn build_assign(attr_name: &str, node: NodeRef) -> NodeRef { node_ref!(Stmt::Assign(AssignStmt { targets: vec![node_ref!(Identifier { - names: vec![attr_name.to_string()], + names: vec![Node::dummy_node(attr_name.to_string())], pkgpath: String::new(), ctx: ExprContext::Store, })], value: node, - type_annotation: None, ty: None, })) } diff --git a/kclvm/utils/Cargo.toml b/kclvm/utils/Cargo.toml index adfd24006..c3563c211 100644 --- a/kclvm/utils/Cargo.toml +++ b/kclvm/utils/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "kclvm-utils" -version = "0.5.0" +version = "0.8.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1" diff --git a/kclvm/utils/src/path.rs b/kclvm/utils/src/path.rs index e1bdcf6af..683e4f73d 100644 --- a/kclvm/utils/src/path.rs +++ b/kclvm/utils/src/path.rs @@ -87,3 +87,18 @@ fn test_adjust_canonicalization1() { path.display().to_string() ); } + +#[inline] +pub fn is_dir(path: &str) -> bool { + std::path::Path::new(path).is_dir() +} + +#[inline] +pub fn is_absolute(path: &str) -> bool { + std::path::Path::new(path).is_absolute() +} + +#[inline] +pub fn path_exist(path: &str) -> bool { + std::path::Path::new(path).exists() +} diff --git a/kclvm/utils/src/pkgpath.rs b/kclvm/utils/src/pkgpath.rs index 512e8de35..ca837359e 100644 --- a/kclvm/utils/src/pkgpath.rs +++ b/kclvm/utils/src/pkgpath.rs @@ -1,5 +1,7 @@ //! This file primarily offers utils for working with kcl package paths. +use anyhow::{anyhow, Result}; + /// Remove the external package name prefix from the current import absolute path. /// /// # Note @@ -8,7 +10,7 @@ /// /// # Error /// An error is returned if an empty string is passed in. -pub fn rm_external_pkg_name(pkgpath: &str) -> Result { +pub fn rm_external_pkg_name(pkgpath: &str) -> Result { Ok(pkgpath .to_string() .trim_start_matches(parse_external_pkg_name(pkgpath)?.as_str()) @@ -23,10 +25,10 @@ pub fn rm_external_pkg_name(pkgpath: &str) -> Result { /// /// # Error /// An error is returned if an empty string is passed in. -pub fn parse_external_pkg_name(pkgpath: &str) -> Result { +pub fn parse_external_pkg_name(pkgpath: &str) -> Result { let mut names = pkgpath.splitn(2, '.'); match names.next() { Some(it) => Ok(it.to_string()), - None => Err(format!("Invalid external package name `{}`", pkgpath)), + None => Err(anyhow!("Invalid external package name `{}`", pkgpath)), } } diff --git a/kclvm/version/Cargo.toml b/kclvm/version/Cargo.toml index f58e53cc2..03c278021 100644 --- a/kclvm/version/Cargo.toml +++ b/kclvm/version/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kclvm-version" -version = "0.5.0" +version = "0.8.1" edition = "2021" [build-dependencies] diff --git a/kclvm/version/src/lib.rs b/kclvm/version/src/lib.rs index db7f10201..4f76524b1 100644 --- a/kclvm/version/src/lib.rs +++ b/kclvm/version/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 The KCL Authors. All rights reserved. +//! Copyright The KCL Authors. All rights reserved. pub const VERSION: &str = include_str!("./../../../VERSION"); pub const CHECK_SUM: &str = "20ab3eb4b9179219d6837a57f5d35286"; diff --git a/run.sh b/run.sh index 2782817d4..2c73a4dbd 100755 --- a/run.sh +++ b/run.sh @@ -13,16 +13,16 @@ topdir=$PWD help_message=$(cat <<-END Usage: run.sh -h - Print this help message + Print this help message. run.sh -a [action] - Perform an action + Perform an action. run.sh - Perform an action interactively + Perform an action interactively. Available actions: build - Package CPython and the KCLVM extension into KCLVM + Build the KCL package. release - Create a package for releasing + Create a releasing for the KCL package. END ) action= @@ -63,4 +63,4 @@ if [ "$action" == "" ]; then done fi -os=$os topdir=$topdir sslpath=$sslpath $topdir/internal/scripts/$action.sh +os=$os topdir=$topdir sslpath=$sslpath $topdir/scripts/$action.sh diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 000000000..f75459356 --- /dev/null +++ b/samples/README.md @@ -0,0 +1,3 @@ +# Examples + +More examples can be found at [here](https://github.com/kcl-lang/kcl-lang.io/tree/main/examples). diff --git a/scripts/build-rpm/kclvm.spec b/scripts/build-rpm/kclvm.spec deleted file mode 100644 index 21912d696..000000000 --- a/scripts/build-rpm/kclvm.spec +++ /dev/null @@ -1,42 +0,0 @@ -# Build kclvm rpm after building and releasing -# yum install -y rpm-build rpmdevtools -# rpmdev-setuptree -# cp ./_build/kclvm-centos-latest.tar.gz /root/rpmbuild/SOURCES/ -# rpmbuild -bb ./scripts/build-rpm/kclvm.spec -# # upload /root/rpmbuild/RPMS/x86_64/kclvm-${version}-1.el7.x86_64.rpm -Name: kclvm -Version: 0.5.0 -Release: 1%{?dist} -Summary: The KCL programming language and tools - -License: Apache-2.0 -URL: https://kcl-lang.io -Source0: kclvm-centos-latest.tar.gz - -%description - -# Turn off the brp-python-bytecompile script -%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompile[[:space:]].*$!!g') -%prep -%setup -q -c - -%build -%define debug_package %{nil} - -%install -rm -rf %{buildroot} -mkdir -p %{buildroot}/usr/local/bin -mkdir -p %{buildroot}/opt/kclvm -mkdir -p /opt/kclvm - -cp -Rp ./kclvm/* %{buildroot}/opt/kclvm -cp -Rp ./kclvm/* /opt/kclvm - -%clean -rm -rf %{buildroot} -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root,-) -%dir /opt/kclvm -/opt/kclvm/* diff --git a/scripts/build-windows/build.bat b/scripts/build-windows/build.bat deleted file mode 100644 index ecf93a12a..000000000 --- a/scripts/build-windows/build.bat +++ /dev/null @@ -1,40 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal - -cd %~dp0 - -:: install kclvm-cli -call .\\build_kclvm_dll.bat -call .\\build_kclvm_cli.bat -call .\\build_kcl_lsp_server.bat - -:: install kclvm-plugin python module -call .\\build_kclvm_plugin_py.bat - -:: Copy KCLVM C API header -call .\\build_kclvm_runtime.bat - -:: install hello.k -go run .\copy-file.go --src=..\..\samples\hello.k --dst=.\_output\kclvm-windows\hello.k - -:: install tools -go build -o .\_output\kclvm-windows\bin\kcl.exe kcl.go -go build -o .\_output\kclvm-windows\bin\kclvm.exe kclvm.go -go build -o .\_output\kclvm-windows\bin\kcl-plugin.exe kcl-plugin.go -go build -o .\_output\kclvm-windows\bin\kcl-doc.exe kcl-doc.go -go build -o .\_output\kclvm-windows\bin\kcl-test.exe kcl-test.go -go build -o .\_output\kclvm-windows\bin\kcl-lint.exe kcl-lint.go -go build -o .\_output\kclvm-windows\bin\kcl-fmt.exe kcl-fmt.go -go build -o .\_output\kclvm-windows\bin\kcl-vet.exe kcl-vet.go - -:: run hello.k -_output\kclvm-windows\bin\kcl.exe ..\..\samples\fib.k -_output\kclvm-windows\bin\kcl.exe ..\..\samples\hello.k -_output\kclvm-windows\bin\kcl.exe ..\..\samples\kubernetes.k -_output\kclvm-windows\bin\kcl.exe ..\..\samples\math.k - -_output\kclvm-windows\bin\kclvm-cli.exe run ..\..\samples\fib.k -_output\kclvm-windows\bin\kclvm-cli.exe run ..\..\samples\hello.k -_output\kclvm-windows\bin\kclvm-cli.exe run ..\..\samples\kubernetes.k -_output\kclvm-windows\bin\kclvm-cli.exe run ..\..\samples\math.k diff --git a/scripts/build-windows/build.ps1 b/scripts/build-windows/build.ps1 new file mode 100644 index 000000000..b5b6d8602 --- /dev/null +++ b/scripts/build-windows/build.ps1 @@ -0,0 +1,44 @@ +# Copyright The KCL Authors. All rights reserved. + +Set-Location $PSScriptRoot +# 1. Install kclvm_cli_cdylib.dll +Set-Location "..\..\kclvm" +cargo build --release +Set-Location $PSScriptRoot + +New-Item -ErrorAction Ignore -Path ".\_output" -ItemType "directory" +New-Item -ErrorAction Ignore -Path ".\_output\kclvm-windows" -ItemType "directory" +New-Item -ErrorAction Ignore -Path ".\_output\kclvm-windows\bin" -ItemType "directory" +New-Item -ErrorAction Ignore -Path ".\_output\kclvm-windows\include" -ItemType "directory" + +Copy-Item -Path "..\..\kclvm\target\release\kclvm_cli_cdylib.dll" -Destination ".\_output\kclvm-windows\bin\kclvm_cli_cdylib.dll" -Force +Copy-Item -Path "..\..\kclvm\target\release\kclvm_cli_cdylib.dll.lib" -Destination ".\_output\kclvm-windows\bin\kclvm_cli_cdylib.lib" -Force +Copy-Item -Path "..\..\kclvm\target\release\kclvm_cli_cdylib.dll.lib" -Destination "..\..\kclvm\target\release\kclvm_cli_cdylib.lib" -Force + +Set-Location $PSScriptRoot +# 2. Install kclvm CLI +Set-Location "..\..\cli" +cargo build --release +Set-Location $PSScriptRoot +Copy-Item -Path "..\..\cli\target\release\kclvm_cli.exe" -Destination ".\_output\kclvm-windows\bin\" -Force + +Set-Location $PSScriptRoot +# 3. Install kcl language server +Set-Location "..\..\kclvm\tools\src\LSP" +cargo build --release +Set-Location $PSScriptRoot +Copy-Item -Path "..\..\kclvm\target\release\kcl-language-server.exe" -Destination ".\_output\kclvm-windows\bin\" + +Set-Location $PSScriptRoot +# 4. Copy KCLVM C API header +Copy-Item -Path "..\..\kclvm\runtime\src\_kclvm.h" -Destination ".\_output\kclvm-windows\include\kclvm.h" -Force + +Set-Location $PSScriptRoot +# Install hello.k +Copy-Item -Path "..\..\samples\hello.k" -Destination ".\_output\kclvm-windows" -Force + +# Run KCL files +.\_output\kclvm-windows\bin\kclvm_cli.exe run ..\..\samples\fib.k +.\_output\kclvm-windows\bin\kclvm_cli.exe run ..\..\samples\hello.k +.\_output\kclvm-windows\bin\kclvm_cli.exe run ..\..\samples\kubernetes.k +.\_output\kclvm-windows\bin\kclvm_cli.exe run ..\..\samples\math.k diff --git a/scripts/build-windows/build_kcl_lsp_server.bat b/scripts/build-windows/build_kcl_lsp_server.bat deleted file mode 100644 index 0a65a1466..000000000 --- a/scripts/build-windows/build_kcl_lsp_server.bat +++ /dev/null @@ -1,11 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal -cd %~dp0 - -:: install kclvm-cli -cd ..\..\kclvm\tools\src\LSP -cargo build --release -cd %~dp0 - -go run .\copy-file.go --src=..\..\kclvm\target\release\kcl-language-server.exe --dst=.\_output\kclvm-windows\bin\kcl-language-server.exe diff --git a/scripts/build-windows/build_kclvm_cli.bat b/scripts/build-windows/build_kclvm_cli.bat deleted file mode 100644 index ec3ff6741..000000000 --- a/scripts/build-windows/build_kclvm_cli.bat +++ /dev/null @@ -1,12 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal -cd %~dp0 - -:: install kclvm-cli -cd ..\..\kclvm_cli -cargo build --release -cd %~dp0 - -go run .\copy-file.go --src=..\..\kclvm_cli\target\release\kclvm_cli.exe --dst=.\_output\kclvm-windows\bin\kclvm-cli.exe - diff --git a/scripts/build-windows/build_kclvm_dll.bat b/scripts/build-windows/build_kclvm_dll.bat deleted file mode 100644 index 822dab096..000000000 --- a/scripts/build-windows/build_kclvm_dll.bat +++ /dev/null @@ -1,17 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal -cd %~dp0 - -:: install kclvm_cli_cdylib.dll -cd ..\..\kclvm -cargo build --release -cd %~dp0 - -go run .\copy-file.go -src=..\..\kclvm\target\release\kclvm_cli_cdylib.dll -dst=.\_output\kclvm-windows\bin\kclvm_cli_cdylib.dll -go run .\copy-file.go -src=..\..\kclvm\target\release\kclvm_cli_cdylib.dll.lib -dst=.\_output\kclvm-windows\bin\kclvm_cli_cdylib.lib -go run .\copy-file.go -src=..\..\kclvm\target\release\kclvm_cli_cdylib.dll.lib -dst=..\..\kclvm\target\release\kclvm_cli_cdylib.lib - -:: install hello.k -go run .\copy-file.go --src=..\..\samples\hello.k --dst=.\_output\kclvm-windows\hello.k - diff --git a/scripts/build-windows/build_kclvm_plugin_py.bat b/scripts/build-windows/build_kclvm_plugin_py.bat deleted file mode 100644 index deff8ff91..000000000 --- a/scripts/build-windows/build_kclvm_plugin_py.bat +++ /dev/null @@ -1,13 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal -cd %~dp0 - -:: install kclvm-plugin python module -cd ..\..\kclvm\plugin -go run .\copy-file.go -src=.\kclvm_plugin.py -dst=..\..\scripts\build-windows\_output\kclvm-windows\lib\site-packages\kclvm_plugin.py -go run .\copy-file.go -src=.\kclvm_runtime.py -dst=..\..\scripts\build-windows\_output\kclvm-windows\lib\site-packages\kclvm_runtime.py - -cd %~dp0 -go run .\copy-dir.go ..\..\plugins ..\..\scripts\build-windows\_output\kclvm-windows\plugins -cd %~dp0 diff --git a/scripts/build-windows/build_kclvm_runtime.bat b/scripts/build-windows/build_kclvm_runtime.bat deleted file mode 100644 index c5046be7b..000000000 --- a/scripts/build-windows/build_kclvm_runtime.bat +++ /dev/null @@ -1,8 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal -cd %~dp0 - -:: Copy KCLVM C API header -go run .\copy-file.go --src=..\..\kclvm\runtime\src\_kclvm.h --dst=.\_output\kclvm-windows\include\_kclvm.h -cd %~dp0 diff --git a/scripts/build-windows/clean.bat b/scripts/build-windows/clean.bat deleted file mode 100644 index 898cfa442..000000000 --- a/scripts/build-windows/clean.bat +++ /dev/null @@ -1,13 +0,0 @@ -:: Copyright 2021 The KCL Authors. All rights reserved. - -setlocal - -cd %~dp0 - -rmdir _output -del /s *.obj -del /s *.exp -del /s *.lib -del /s *.dll - -del *.zip diff --git a/scripts/build-windows/clean.ps1 b/scripts/build-windows/clean.ps1 new file mode 100644 index 000000000..0088729bf --- /dev/null +++ b/scripts/build-windows/clean.ps1 @@ -0,0 +1,10 @@ +# Copyright The KCL Authors. All rights reserved. + +Set-Location $PSScriptRoot + +Remove-Item -Recurse -Force "_output" +Remove-Item -Recurse -Force "*.obj" +Remove-Item -Recurse -Force "*.exp" +Remove-Item -Recurse -Force "*.lib" +Remove-Item -Recurse -Force "*.dll" +Remove-Item -Force "*.zip" diff --git a/scripts/build-windows/copy-dir.go b/scripts/build-windows/copy-dir.go deleted file mode 100644 index 9dc4c27c4..000000000 --- a/scripts/build-windows/copy-dir.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -//go:build ingore -// +build ingore - -// Copy dir, support regexp. -// -// Example: -// -// cpdir src dst -// cpdir src dst "\.go$" -// -// Help: -// -// cpdir -h -package main - -import ( - "fmt" - "io" - "io/ioutil" - "log" - "os" - "path/filepath" - "regexp" -) - -const usage = ` -Usage: cpdir src dst [filter] - cpdir -h - -Example: - cpdir src dst - cpdir src dst "\.go$" -` - -func main() { - if len(os.Args) < 3 { - fmt.Fprintln(os.Stderr, usage[1:len(usage)-1]) - os.Exit(0) - } - filter := ".*" - if len(os.Args) > 3 { - filter = os.Args[3] - } - total := cpDir(os.Args[2], os.Args[1], filter) - fmt.Printf("total %d\n", total) -} - -func cpDir(dst, src, filter string) (total int) { - entryList, err := ioutil.ReadDir(src) - if err != nil && !os.IsExist(err) { - log.Fatal("cpDir: ", err) - } - for _, entry := range entryList { - if entry.IsDir() { - cpDir(dst+"/"+entry.Name(), src+"/"+entry.Name(), filter) - } else { - mathed, err := regexp.MatchString(filter, entry.Name()) - if err != nil { - log.Fatal("regexp.MatchString: ", err) - } - if mathed { - srcFname := filepath.Clean(src + "/" + entry.Name()) - dstFname := filepath.Clean(dst + "/" + entry.Name()) - fmt.Printf("copy %s\n", srcFname) - - cpFile(dstFname, srcFname) - total++ - } - } - } - return -} - -func cpFile(dst, src string) { - err := os.MkdirAll(filepath.Dir(dst), 0777) - if err != nil && !os.IsExist(err) { - log.Fatal("cpFile: ", err) - } - fsrc, err := os.Open(src) - if err != nil { - log.Fatal("cpFile: ", err) - } - defer fsrc.Close() - - fdst, err := os.Create(dst) - if err != nil { - log.Fatal("cpFile: ", err) - } - defer fdst.Close() - if _, err = io.Copy(fdst, fsrc); err != nil { - log.Fatal("cpFile: ", err) - } -} diff --git a/scripts/build-windows/copy-file.go b/scripts/build-windows/copy-file.go deleted file mode 100644 index a3ef4e5e5..000000000 --- a/scripts/build-windows/copy-file.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -//go:build ingore -// +build ingore - -package main - -import ( - "flag" - "io" - "log" - "os" - "path/filepath" -) - -var ( - flagDst = flag.String("dst", "", "set dst path") - flagSrc = flag.String("src", "", "set src path") -) - -func init() { - log.SetFlags(log.Lshortfile) -} - -func main() { - flag.Parse() - - if *flagDst == "" { - log.Fatal("dst path missing") - } - if *flagSrc == "" { - log.Fatal("src path missing") - } - - cpFile(*flagDst, *flagSrc) -} - -func cpFile(dst, src string) { - err := os.MkdirAll(filepath.Dir(dst), 0777) - if err != nil && !os.IsExist(err) { - log.Fatal("cpFile: ", err) - } - fsrc, err := os.Open(src) - if err != nil { - log.Fatal("cpFile: ", err) - } - defer fsrc.Close() - - fdst, err := os.Create(dst) - if err != nil { - log.Fatal("cpFile: ", err) - } - defer fdst.Close() - if _, err = io.Copy(fdst, fsrc); err != nil { - log.Fatal("cpFile: ", err) - } -} diff --git a/scripts/build-windows/kcl-doc.go b/scripts/build-windows/kcl-doc.go deleted file mode 100644 index 2852106b7..000000000 --- a/scripts/build-windows/kcl-doc.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "strconv" -) - -func main() { - // python3 -m kclvm ... - - var args []string - args = append(args, "/C", "python3", "-m", "kclvm.tools.docs") - args = append(args, os.Args[1:]...) - - os.Exit(Py_Main(args)) -} - -func Py_Main(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - Install_Kclvm() - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - Set_Env(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func Install_Kclvm() { - // Check if Python3 is installed - cmd := exec.Command("cmd", "/C", "where python3") - cmd.Stderr = os.Stderr - - err := cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "Python3 is not installed, details: ", err) - os.Exit(1) - } - - cmd = exec.Command("cmd", "/C", "python3", "-c", "\"import pkgutil;print(bool(pkgutil.find_loader('kclvm')))\"") - var out bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - fmt.Fprintln(os.Stderr, "check python3 kclvm failed: ", err) - os.Exit(1) - } - - is_installed, err := strconv.ParseBool(out.String()) - - // Check if kclvm has been installed. - if err == nil && is_installed { - return - } - - // Install kclvm module using pip - cmd = exec.Command("cmd", "/C", "python3", "-m", "pip", "install", "-U", "kclvm", "--user") - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - fmt.Fprintln(os.Stderr, "Pip install kclvm falied ", err) - os.Exit(1) - } -} - -func Set_Env(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kcl-fmt.go b/scripts/build-windows/kcl-fmt.go deleted file mode 100644 index 8fd18eeb2..000000000 --- a/scripts/build-windows/kcl-fmt.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2023 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func main() { - var args []string - args = append(args, "/C", "kclvm-cli", "fmt") - args = append(args, os.Args[1:]...) - - os.Exit(KclvmCliMain(args)) -} - -func KclvmCliMain(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - SetEnv(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func SetEnv(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kcl-lint.go b/scripts/build-windows/kcl-lint.go deleted file mode 100644 index 5c3cc2c97..000000000 --- a/scripts/build-windows/kcl-lint.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2023 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func main() { - var args []string - args = append(args, "/C", "kclvm-cli", "lint") - args = append(args, os.Args[1:]...) - - os.Exit(KclvmCliMain(args)) -} - -func KclvmCliMain(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - SetEnv(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func SetEnv(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kcl-plugin.go b/scripts/build-windows/kcl-plugin.go deleted file mode 100644 index 300710307..000000000 --- a/scripts/build-windows/kcl-plugin.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "strconv" -) - -func main() { - // python3 -m kclvm ... - - var args []string - args = append(args, "/C", "python3", "-m", "kclvm.tools.plugin") - args = append(args, os.Args[1:]...) - - os.Exit(Py_Main(args)) -} - -func Py_Main(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - Install_Kclvm() - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - Set_Env(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func Install_Kclvm() { - // Check if Python3 is installed - cmd := exec.Command("cmd", "/C", "where python3") - cmd.Stderr = os.Stderr - - err := cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "Python3 is not installed, details: ", err) - os.Exit(1) - } - - cmd = exec.Command("cmd", "/C", "python3", "-c", "\"import pkgutil;print(bool(pkgutil.find_loader('kclvm')))\"") - var out bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - fmt.Fprintln(os.Stderr, "check python3 kclvm failed: ", err) - os.Exit(1) - } - - is_installed, err := strconv.ParseBool(out.String()) - - // Check if kclvm has been installed. - if err == nil && is_installed { - return - } - - // Install kclvm module using pip - cmd = exec.Command("cmd", "/C", "python3", "-m", "pip", "install", "-U", "kclvm", "--user") - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - fmt.Fprintln(os.Stderr, "Pip install kclvm falied ", err) - os.Exit(1) - } -} - -func Set_Env(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kcl-test.go b/scripts/build-windows/kcl-test.go deleted file mode 100644 index f3acb9d53..000000000 --- a/scripts/build-windows/kcl-test.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func main() { - pwd_path, _ := os.Getwd() - kcl_go_path := filepath.Join(pwd_path, "kcl-go") - if _, err := os.Stat(kcl_go_path); os.IsNotExist(err) { - fmt.Println("kcl-go not found, please check the installation") - os.Exit(1) - } - os.Setenv("PYTHONPATH", "") - cmd := exec.Command(kcl_go_path, "test") - cmd.Args = append(cmd.Args, os.Args[1:]...) - - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Run() -} diff --git a/scripts/build-windows/kcl-vet.go b/scripts/build-windows/kcl-vet.go deleted file mode 100644 index d9f506ff1..000000000 --- a/scripts/build-windows/kcl-vet.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2023 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func main() { - var args []string - args = append(args, "/C", "kclvm-cli", "vet") - args = append(args, os.Args[1:]...) - - os.Exit(KclvmCliMain(args)) -} - -func KclvmCliMain(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - SetEnv(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func SetEnv(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kcl.go b/scripts/build-windows/kcl.go deleted file mode 100644 index 1f6faac82..000000000 --- a/scripts/build-windows/kcl.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2023 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" -) - -func main() { - var args []string - args = append(args, "/C", "kclvm-cli") - // Check version flags. Only for v0.4.x, all CLIs will be unified after v0.5.x. - if len(os.Args) >= 1 && (os.Args[1] == "-v" || os.Args[1] == "-V" || os.Args[1] == "version" || os.Args[1] == "--version") { - args = append(args, "version") - } else { - args = append(args, "run") - args = append(args, os.Args[1:]...) - } - - os.Exit(KclvmCliMain(args)) -} - -func KclvmCliMain(args []string) int { - inputPath, err := os.Executable() - if err != nil { - fmt.Fprintln(os.Stderr, "Input path does not exist") - os.Exit(1) - } - kclvm_install_dir := filepath.Dir(filepath.Dir(inputPath)) - - cmd := exec.Command("cmd", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - - SetEnv(kclvm_install_dir, cmd) - - err = cmd.Run() - if err != nil { - fmt.Fprintln(os.Stderr, "exec failed:", err) - os.Exit(1) - } - return 0 -} - -func SetEnv(kclvm_install_dir string, cmd *exec.Cmd) { - bin_path := filepath.Join(kclvm_install_dir, "bin") - site_packages_path := filepath.Join(kclvm_install_dir, "lib", "site-packages") - - os.Setenv("PATH", os.Getenv("PATH")+";"+bin_path) - cmd.Env = os.Environ() - cmd.Env = append(cmd.Env, "KCLVM_CLI_BIN_PATH="+bin_path) - cmd.Env = append(cmd.Env, "PYTHONPATH="+site_packages_path) -} diff --git a/scripts/build-windows/kclvm.go b/scripts/build-windows/kclvm.go deleted file mode 100644 index 5e309977f..000000000 --- a/scripts/build-windows/kclvm.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2021 The KCL Authors. All rights reserved. - -//go:build ingore && windows -// +build ingore,windows - -package main - -import ( - "os" - "os/exec" - "path/filepath" -) - -func main() { - - kclvm_install_dir, _ := filepath.Abs(filepath.Dir(filepath.Dir(os.Args[0]))) - - os.Setenv("KCLVM_CLI_BIN_PATH", filepath.Join(kclvm_install_dir, "bin")) - os.Setenv("PYTHONPATH", filepath.Join(kclvm_install_dir, "lib", "site-packages")) - - cmd := exec.Command("python3", os.Args[1:]...) - cmd.Env = os.Environ() - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - cmd.Stdin = os.Stdin - if err := cmd.Start(); err != nil { - os.Exit(1) - } -} diff --git a/internal/scripts/build.sh b/scripts/build.sh similarity index 54% rename from internal/scripts/build.sh rename to scripts/build.sh index d3bd566aa..b75c17a48 100755 --- a/internal/scripts/build.sh +++ b/scripts/build.sh @@ -4,6 +4,7 @@ set -e # Environment + if [ -f "/etc/os-release" ]; then source /etc/os-release os=$ID @@ -14,48 +15,18 @@ fi prepare_dirs () { install_dir="$topdir/_build/dist/$os/kclvm" mkdir -p "$install_dir/bin" - mkdir -p "$install_dir/lib/site-packages" mkdir -p "$install_dir/include" } prepare_dirs -# Perform the build process. -set -x - -# Copy kcl scripts -cp "$topdir/internal/scripts/cli/kcl" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kclvm" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-plugin" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-doc" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-test" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-lint" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-fmt" $install_dir/bin/ -cp "$topdir/internal/scripts/cli/kcl-vet" $install_dir/bin/ -chmod +x $install_dir/bin/kcl -chmod +x $install_dir/bin/kclvm -chmod +x $install_dir/bin/kcl-plugin -chmod +x $install_dir/bin/kcl-doc -chmod +x $install_dir/bin/kcl-test -chmod +x $install_dir/bin/kcl-lint -chmod +x $install_dir/bin/kcl-fmt -chmod +x $install_dir/bin/kcl-vet - -if [ -d $install_dir/lib/site-packages/kclvm ]; then - rm -rf $install_dir/lib/site-packages/kclvm -fi - -# Install plugins -cp -rf $topdir/plugins $install_dir/ - -set +x - -# build kcl +# 1. Build kcl native library cd $topdir/kclvm +export PATH=$PATH:/root/.cargo/bin:/usr/lib/llvm-12/bin cargo build --release -# Switch dll file extension according to os. +## Switch dll file extension according to os. dll_extension="so" case $os in "Default" | "default" | "centos" | "ubuntu" | "debian" | "Ubuntu" |"Debian" | "Static-Debian" | "Cood1-Debian" | "Cood1Shared-Debian") @@ -68,7 +39,12 @@ case $os in ;; esac -# Copy libkclvm_cli lib +## Copy C API header + +cd $topdir/kclvm/runtime +cp src/_kclvm.h $install_dir/include/kclvm.h + +## Copy libkclvm_cli lib to the build folder if [ -e $topdir/kclvm/target/release/libkclvm_cli_cdylib.$dll_extension ]; then touch $install_dir/bin/libkclvm_cli_cdylib.$dll_extension @@ -76,7 +52,7 @@ if [ -e $topdir/kclvm/target/release/libkclvm_cli_cdylib.$dll_extension ]; then cp $topdir/kclvm/target/release/libkclvm_cli_cdylib.$dll_extension $install_dir/bin/libkclvm_cli_cdylib.$dll_extension fi -# build kcl LSP server +## 2. Build KCL language server binary cd $topdir/kclvm/tools/src/LSP cargo build --release @@ -85,15 +61,17 @@ touch $install_dir/bin/kcl-language-server rm $install_dir/bin/kcl-language-server cp $topdir/kclvm/target/release/kcl-language-server $install_dir/bin/kcl-language-server +## 3. Build CLI -cd $topdir/kclvm_cli +cd $topdir/cli cargo build --release touch $install_dir/bin/kclvm_cli rm $install_dir/bin/kclvm_cli cp ./target/release/kclvm_cli $install_dir/bin/kclvm_cli -# Disable Mac Binary Security +## 4. Disable Mac Binary Security + case $os in "Darwin" | "darwin" | "ios" | "macos") xattr -rd com.apple.quarantine $install_dir > /dev/null 2>&1 @@ -102,16 +80,8 @@ case $os in ;; esac -# Copy kcl C API header -cd $topdir/kclvm/runtime -cp src/_kclvm.h $install_dir/include/_kclvm.h - -# build kcl plugin python module -cd $topdir/kclvm/plugin -cp ./kclvm_plugin.py $install_dir/lib/site-packages/ -cp ./kclvm_runtime.py $install_dir/lib/site-packages/ - cd $topdir + # Print the summary. echo "================ Summary ================" echo " KCLVM is updated into $install_dir" diff --git a/scripts/docker/kcl-builder-arm64/Dockerfile b/scripts/docker/kcl-builder-arm64/Dockerfile new file mode 100644 index 000000000..bf33a3a27 --- /dev/null +++ b/scripts/docker/kcl-builder-arm64/Dockerfile @@ -0,0 +1,27 @@ +# Copyright The KCL Authors. All rights reserved. +# Builder for kcllang/kcl-builder-arm64 image + +FROM arm64v8/ubuntu:20.04 + +#RUN uname -a +#RUN cat /etc/os-release + +RUN apt-get update + +RUN apt-get install -y curl make gcc git zlib1g-dev + +# rust +RUN curl https://sh.rustup.rs -sSf | bash -s -- -y +ENV CARGO_NET_GIT_FETCH_WITH_CLI=true + +RUN cargo version +RUN rustc --version + +# clang12 +RUN apt-get install -y clang-12 lld-12 +RUN ln -sf /usr/bin/clang-12 /usr/bin/clang +RUN ln -sf /usr/bin/wasm-ld-12 /usr/bin/wasm-ld + +WORKDIR /root + +CMD ["bash"] diff --git a/scripts/docker/kcl-builder-centos7/Dockerfile b/scripts/docker/kcl-builder-centos7/Dockerfile index eb46286fe..33a9729fd 100644 --- a/scripts/docker/kcl-builder-centos7/Dockerfile +++ b/scripts/docker/kcl-builder-centos7/Dockerfile @@ -32,13 +32,13 @@ RUN yum install -y zlib* # in order to use the modules that require ssl, such as pip3, twine, etc. RUN yum install -y openssl-devel -# install which +# Install which RUN yum install -y which -# install wget +# Install wget RUN yum install -y wget -# install git-2.x +# Install git-2.x # RUN yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm # RUN yum -y install git @@ -54,7 +54,7 @@ RUN rustc --version # wasm RUN rustup target add wasm32-unknown-unknown -# clang7 +# Install clang7 and llvm7 # https://www.softwarecollections.org/en/scls/rhscl/llvm-toolset-7.0/ # # 1. Install a package with repository for your system: @@ -76,6 +76,11 @@ RUN yum -y install llvm-toolset-7.0 RUN yum -y install llvm-toolset-7.0\* RUN scl enable llvm-toolset-7.0 bash +# Install gcc7 +RUN yum -y install devtoolset-7* +RUN scl enable devtoolset-7 bash +RUN gcc -v + # rpm -ql llvm-toolset-7.0-clang.x86_64 # /opt/rh/llvm-toolset-7.0/root/usr/lib64/libLLVM-7.so ENV LD_LIBRARY_PATH="/opt/rh/llvm-toolset-7.0/root/usr/lib64:${LD_LIBRARY_PATH}" diff --git a/scripts/docker/kcl-builder/Dockerfile b/scripts/docker/kcl-builder/Dockerfile index e070b45ff..4e04df6fd 100644 --- a/scripts/docker/kcl-builder/Dockerfile +++ b/scripts/docker/kcl-builder/Dockerfile @@ -43,7 +43,7 @@ RUN apt-get install -y clang-12 lld-12 RUN ln -sf /usr/bin/clang-12 /usr/bin/clang RUN ln -sf /usr/bin/wasm-ld-12 /usr/bin/wasm-ld -# golang 1.19+ +# golang 1.20+ RUN mkdir -p /root/download && cd /root/download \ && wget https://dl.google.com/go/go1.20.5.linux-amd64.tar.gz \ && tar -zxvf go1.20.5.linux-amd64.tar.gz \ diff --git a/internal/scripts/release.sh b/scripts/release.sh similarity index 100% rename from internal/scripts/release.sh rename to scripts/release.sh diff --git a/scripts/tag.sh b/scripts/tag.sh new file mode 100755 index 000000000..b9286c58e --- /dev/null +++ b/scripts/tag.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +set -e +if [ "$1" == "" ]; then + echo usage: "$0 VERSION" +fi +git tag $1 +git push origin $1 +gh release create $1 --draft --generate-notes --title "$1 Release" diff --git a/test/grammar/attr_operator/config_inside/insert/dict_2/main.k b/test/grammar/attr_operator/config_inside/insert/dict_2/main.k new file mode 100644 index 000000000..4e7150f36 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_2/main.k @@ -0,0 +1,12 @@ +config = { + main: { + env: [ + {name: "ENV_1", value: "1"} + ] + } + main: { + env += [ + {name: "ENV_2", value: "2"} + ] + } +} diff --git a/test/grammar/attr_operator/config_inside/insert/dict_2/stdout.golden b/test/grammar/attr_operator/config_inside/insert/dict_2/stdout.golden new file mode 100644 index 000000000..853930d54 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_2/stdout.golden @@ -0,0 +1,7 @@ +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' diff --git a/test/grammar/attr_operator/config_inside/insert/dict_3/main.k b/test/grammar/attr_operator/config_inside/insert/dict_3/main.k new file mode 100644 index 000000000..c5e4cd98b --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_3/main.k @@ -0,0 +1,12 @@ +config = { + main: { + env: [ + {name: "ENV_1", value: "1"} + ] + } + main: { + env += [ + {name: "ENV_2", value: "2"} + ] + } +} diff --git a/test/grammar/attr_operator/config_inside/insert/dict_3/stdout.golden b/test/grammar/attr_operator/config_inside/insert/dict_3/stdout.golden new file mode 100644 index 000000000..853930d54 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_3/stdout.golden @@ -0,0 +1,7 @@ +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' diff --git a/test/grammar/attr_operator/config_inside/insert/dict_4/main.k b/test/grammar/attr_operator/config_inside/insert/dict_4/main.k new file mode 100644 index 000000000..2e4e44524 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_4/main.k @@ -0,0 +1,7 @@ +config = { + main: {env: [{name: "ENV_1", value: "1"}] + } + main: {env += [ + {name: "ENV_2", value: "2"}] + } +} diff --git a/test/grammar/attr_operator/config_inside/insert/dict_4/stdout.golden b/test/grammar/attr_operator/config_inside/insert/dict_4/stdout.golden new file mode 100644 index 000000000..853930d54 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_4/stdout.golden @@ -0,0 +1,7 @@ +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' diff --git a/test/grammar/attr_operator/config_inside/insert/dict_5/main.k b/test/grammar/attr_operator/config_inside/insert/dict_5/main.k new file mode 100644 index 000000000..3779732a7 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_5/main.k @@ -0,0 +1,17 @@ +config = { +main: { +env: [ +{ +name: "ENV_1", +value: "1" +} +] +} +main: {env += [ +{ +name: "ENV_2", +value: "2" +} +] +} +} diff --git a/test/grammar/attr_operator/config_inside/insert/dict_5/stdout.golden b/test/grammar/attr_operator/config_inside/insert/dict_5/stdout.golden new file mode 100644 index 000000000..853930d54 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/dict_5/stdout.golden @@ -0,0 +1,7 @@ +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' diff --git a/test/grammar/attr_operator/config_inside/insert/schema_3/main.k b/test/grammar/attr_operator/config_inside/insert/schema_3/main.k new file mode 100644 index 000000000..4e23781f1 --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/schema_3/main.k @@ -0,0 +1,26 @@ +schema Env: + name: str + value: str + +schema Main: + env: [Env] + +schema Config: + main: Main + +_main = Main {env: [ +{name: "ENV_1", value: "1"} + ] +} + +main1 = Main {env: [{name: "ENV_1", value: "1"} + ] +} + +config = Config { + main: _main + main: Main { + env += [ + {name: "ENV_2", value: "2"} + ]} +} \ No newline at end of file diff --git a/test/grammar/attr_operator/config_inside/insert/schema_3/stdout.golden b/test/grammar/attr_operator/config_inside/insert/schema_3/stdout.golden new file mode 100644 index 000000000..439d02e5a --- /dev/null +++ b/test/grammar/attr_operator/config_inside/insert/schema_3/stdout.golden @@ -0,0 +1,11 @@ +main1: + env: + - name: ENV_1 + value: '1' +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' \ No newline at end of file diff --git a/test/grammar/attr_operator/if_entry/insert/dict_3/main.k b/test/grammar/attr_operator/if_entry/insert/dict_3/main.k new file mode 100644 index 000000000..4eb44875a --- /dev/null +++ b/test/grammar/attr_operator/if_entry/insert/dict_3/main.k @@ -0,0 +1,17 @@ +schema Main: + env: [{str:str}] + +schema Config: + main: Main + +config = Config { + main: { + env: [ + {name: "ENV_1", value: "1"} + ] + } + main: { + if True: + env += [{name: "ENV_2", value: "2"}] + } +} diff --git a/test/grammar/attr_operator/if_entry/insert/dict_3/stdout.golden b/test/grammar/attr_operator/if_entry/insert/dict_3/stdout.golden new file mode 100644 index 000000000..853930d54 --- /dev/null +++ b/test/grammar/attr_operator/if_entry/insert/dict_3/stdout.golden @@ -0,0 +1,7 @@ +config: + main: + env: + - name: ENV_1 + value: '1' + - name: ENV_2 + value: '2' diff --git a/test/grammar/builtins/crypto/sha/filesha256/main.k b/test/grammar/builtins/crypto/sha/filesha256/main.k new file mode 100644 index 000000000..f290fda22 --- /dev/null +++ b/test/grammar/builtins/crypto/sha/filesha256/main.k @@ -0,0 +1,3 @@ +import crypto + +sha = crypto.filesha256("test.txt") diff --git a/test/grammar/builtins/crypto/sha/filesha256/stdout.golden b/test/grammar/builtins/crypto/sha/filesha256/stdout.golden new file mode 100644 index 000000000..98bd79450 --- /dev/null +++ b/test/grammar/builtins/crypto/sha/filesha256/stdout.golden @@ -0,0 +1 @@ +sha: e9c0f8b575cbfcb42ab3b78ecc87efa3b011d9a5d10b09fa4e96f240bf6a82f5 \ No newline at end of file diff --git a/test/grammar/builtins/crypto/sha/filesha256/test.txt b/test/grammar/builtins/crypto/sha/filesha256/test.txt new file mode 100644 index 000000000..1c5f8ba2d --- /dev/null +++ b/test/grammar/builtins/crypto/sha/filesha256/test.txt @@ -0,0 +1 @@ +ABCDEF \ No newline at end of file diff --git a/test/grammar/builtins/default/bin/stdout.golden b/test/grammar/builtins/default/bin/stdout.golden index 70d34a975..d95ec88af 100644 --- a/test/grammar/builtins/default/bin/stdout.golden +++ b/test/grammar/builtins/default/bin/stdout.golden @@ -1,2 +1,2 @@ -a: 0b1010 -b: 0b10100 \ No newline at end of file +a: '0b1010' +b: '0b10100' diff --git a/test/grammar/builtins/default/oct/stdout.golden b/test/grammar/builtins/default/oct/stdout.golden index 637b22f33..e15ca4f32 100644 --- a/test/grammar/builtins/default/oct/stdout.golden +++ b/test/grammar/builtins/default/oct/stdout.golden @@ -1,3 +1,3 @@ -a: 0o12 -b: 0o24 -c: 0o17 +a: '0o12' +b: '0o24' +c: '0o17' diff --git a/test/grammar/builtins/file/glob/main.k b/test/grammar/builtins/file/glob/main.k new file mode 100644 index 000000000..b1605476c --- /dev/null +++ b/test/grammar/builtins/file/glob/main.k @@ -0,0 +1,3 @@ +import file + +contents = [ file.read(_x) for _x in file.glob("./*.json")] diff --git a/test/grammar/builtins/file/glob/stdout.golden b/test/grammar/builtins/file/glob/stdout.golden new file mode 100644 index 000000000..693ad5008 --- /dev/null +++ b/test/grammar/builtins/file/glob/stdout.golden @@ -0,0 +1,19 @@ +contents: +- |- + { + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] + } +- |- + { + "key1": "value3", + "key2": "value4", + "data": [4, 5, 6] + } +- |- + { + "key1": "value5", + "key2": "value6", + "data": [7, 8, 9] + } \ No newline at end of file diff --git a/test/grammar/builtins/file/glob/test1.json b/test/grammar/builtins/file/glob/test1.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/glob/test1.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/glob/test2.json b/test/grammar/builtins/file/glob/test2.json new file mode 100644 index 000000000..fc96ddad8 --- /dev/null +++ b/test/grammar/builtins/file/glob/test2.json @@ -0,0 +1,5 @@ +{ + "key1": "value3", + "key2": "value4", + "data": [4, 5, 6] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/glob/test3.json b/test/grammar/builtins/file/glob/test3.json new file mode 100644 index 000000000..e2d404d66 --- /dev/null +++ b/test/grammar/builtins/file/glob/test3.json @@ -0,0 +1,5 @@ +{ + "key1": "value5", + "key2": "value6", + "data": [7, 8, 9] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/load_file_invalid/main.k b/test/grammar/builtins/file/load_file_invalid/main.k new file mode 100644 index 000000000..a9238ff6d --- /dev/null +++ b/test/grammar/builtins/file/load_file_invalid/main.k @@ -0,0 +1,3 @@ +import file + +a = file.read("not_exist.txt") \ No newline at end of file diff --git a/test/grammar/builtins/file/load_file_invalid/stderr.golden.py b/test/grammar/builtins/file/load_file_invalid/stderr.golden.py new file mode 100644 index 000000000..9d47c45c8 --- /dev/null +++ b/test/grammar/builtins/file/load_file_invalid/stderr.golden.py @@ -0,0 +1,17 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message(kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=3 + column_no=1, + )], + arg_msg="failed to access the file 'not_exist.txt':No such file or directory (os error 2)" + ), + file=sys.stdout) diff --git a/test/grammar/builtins/file/load_json/main.k b/test/grammar/builtins/file/load_json/main.k new file mode 100644 index 000000000..1bda19025 --- /dev/null +++ b/test/grammar/builtins/file/load_json/main.k @@ -0,0 +1,8 @@ +import json +import file + +data_string = json.decode(file.read("test.json")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/load_json/stdout.golden b/test/grammar/builtins/file/load_json/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/load_json/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/load_json/test.json b/test/grammar/builtins/file/load_json/test.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/load_json/test.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/main.k b/test/grammar/builtins/file/load_txt/main.k new file mode 100644 index 000000000..741febc4f --- /dev/null +++ b/test/grammar/builtins/file/load_txt/main.k @@ -0,0 +1,3 @@ +import file + +a = file.read("test.txt") \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/stdout.golden b/test/grammar/builtins/file/load_txt/stdout.golden new file mode 100644 index 000000000..623ab06c1 --- /dev/null +++ b/test/grammar/builtins/file/load_txt/stdout.golden @@ -0,0 +1 @@ +a: Helloworld \ No newline at end of file diff --git a/test/grammar/builtins/file/load_txt/test.txt b/test/grammar/builtins/file/load_txt/test.txt new file mode 100644 index 000000000..0cf453276 --- /dev/null +++ b/test/grammar/builtins/file/load_txt/test.txt @@ -0,0 +1 @@ +Helloworld \ No newline at end of file diff --git a/test/grammar/builtins/file/load_yaml/main.k b/test/grammar/builtins/file/load_yaml/main.k new file mode 100644 index 000000000..01a780149 --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/main.k @@ -0,0 +1,8 @@ +import yaml +import file + +data_string = yaml.decode(file.read("test.yaml")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/load_yaml/stdout.golden b/test/grammar/builtins/file/load_yaml/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/load_yaml/test.yaml b/test/grammar/builtins/file/load_yaml/test.yaml new file mode 100644 index 000000000..0ffe95c1b --- /dev/null +++ b/test/grammar/builtins/file/load_yaml/test.yaml @@ -0,0 +1,3 @@ +key1: "value1" +key2: "value2" +data: [1, 2, 3] diff --git a/test/grammar/builtins/file/mod_root/main.k b/test/grammar/builtins/file/mod_root/main.k new file mode 100644 index 000000000..3fde22987 --- /dev/null +++ b/test/grammar/builtins/file/mod_root/main.k @@ -0,0 +1,8 @@ +import file +import json + +data_string = json.decode(file.read(file.modpath()+"/test.json")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/mod_root/stdout.golden b/test/grammar/builtins/file/mod_root/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/mod_root/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/mod_root/test.json b/test/grammar/builtins/file/mod_root/test.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/mod_root/test.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/mod_root_sub/kcl.mod b/test/grammar/builtins/file/mod_root_sub/kcl.mod new file mode 100644 index 000000000..e70c1ec74 --- /dev/null +++ b/test/grammar/builtins/file/mod_root_sub/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "workdir_sub" +edition = "0.0.1" +version = "0.0.1" + diff --git a/test/grammar/builtins/file/mod_root_sub/stdout.golden b/test/grammar/builtins/file/mod_root_sub/stdout.golden new file mode 100644 index 000000000..3c268cc99 --- /dev/null +++ b/test/grammar/builtins/file/mod_root_sub/stdout.golden @@ -0,0 +1,13 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 diff --git a/test/grammar/builtins/file/mod_root_sub/sub/main.k b/test/grammar/builtins/file/mod_root_sub/sub/main.k new file mode 100644 index 000000000..3fde22987 --- /dev/null +++ b/test/grammar/builtins/file/mod_root_sub/sub/main.k @@ -0,0 +1,8 @@ +import file +import json + +data_string = json.decode(file.read(file.modpath()+"/test.json")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data \ No newline at end of file diff --git a/test/grammar/builtins/file/mod_root_sub/test.json b/test/grammar/builtins/file/mod_root_sub/test.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/mod_root_sub/test.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/file/workdir/main.k b/test/grammar/builtins/file/workdir/main.k new file mode 100644 index 000000000..cec24de81 --- /dev/null +++ b/test/grammar/builtins/file/workdir/main.k @@ -0,0 +1,3 @@ +import file + +workdir = file.workdir() diff --git a/test/grammar/builtins/file/workdir/stdout.golden b/test/grammar/builtins/file/workdir/stdout.golden new file mode 100644 index 000000000..a6ec37904 --- /dev/null +++ b/test/grammar/builtins/file/workdir/stdout.golden @@ -0,0 +1 @@ +workdir: '' diff --git a/test/grammar/builtins/file/workdir_sub/kcl.mod b/test/grammar/builtins/file/workdir_sub/kcl.mod new file mode 100644 index 000000000..e70c1ec74 --- /dev/null +++ b/test/grammar/builtins/file/workdir_sub/kcl.mod @@ -0,0 +1,5 @@ +[package] +name = "workdir_sub" +edition = "0.0.1" +version = "0.0.1" + diff --git a/test/grammar/builtins/file/workdir_sub/stdout.golden b/test/grammar/builtins/file/workdir_sub/stdout.golden new file mode 100644 index 000000000..a0a5fd960 --- /dev/null +++ b/test/grammar/builtins/file/workdir_sub/stdout.golden @@ -0,0 +1,14 @@ +data_string: + key1: value1 + key2: value2 + data: + - 1 + - 2 + - 3 +key1: value1 +key2: value2 +data: +- 1 +- 2 +- 3 +workdir: '' diff --git a/test/grammar/builtins/file/workdir_sub/sub/main.k b/test/grammar/builtins/file/workdir_sub/sub/main.k new file mode 100644 index 000000000..b4042e915 --- /dev/null +++ b/test/grammar/builtins/file/workdir_sub/sub/main.k @@ -0,0 +1,10 @@ +import file +import json + +data_string = json.decode(file.read(file.modpath()+"/test.json")) + +key1 = data_string.key1 +key2 = data_string.key2 +data = data_string.data + +workdir = file.workdir() \ No newline at end of file diff --git a/test/grammar/builtins/file/workdir_sub/test.json b/test/grammar/builtins/file/workdir_sub/test.json new file mode 100644 index 000000000..e8772183f --- /dev/null +++ b/test/grammar/builtins/file/workdir_sub/test.json @@ -0,0 +1,5 @@ +{ + "key1": "value1", + "key2": "value2", + "data": [1, 2, 3] +} \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/0.json b/test/grammar/builtins/json/dump_to_file_0/0.json new file mode 100644 index 000000000..6743ea768 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/0.json @@ -0,0 +1 @@ +"key: value" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/1.json b/test/grammar/builtins/json/dump_to_file_0/1.json new file mode 100644 index 000000000..8350d35db --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/1.json @@ -0,0 +1 @@ +"- 1\n- 2\n- 3" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/2.json b/test/grammar/builtins/json/dump_to_file_0/2.json new file mode 100644 index 000000000..2d81c1ae7 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/2.json @@ -0,0 +1 @@ +"1" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/3.json b/test/grammar/builtins/json/dump_to_file_0/3.json new file mode 100644 index 000000000..f47281b17 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/3.json @@ -0,0 +1 @@ +"1.1" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/4.json b/test/grammar/builtins/json/dump_to_file_0/4.json new file mode 100644 index 000000000..80541ce68 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/4.json @@ -0,0 +1 @@ +"null" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/5.json b/test/grammar/builtins/json/dump_to_file_0/5.json new file mode 100644 index 000000000..e942432aa --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/5.json @@ -0,0 +1 @@ +"true" \ No newline at end of file diff --git a/test/grammar/builtins/json/dump_to_file_0/main.k b/test/grammar/builtins/json/dump_to_file_0/main.k new file mode 100644 index 000000000..d7f9dfd1d --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/main.k @@ -0,0 +1,11 @@ +import json + +jsonStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +_ = [json.dump_to_file(s, "${i}.json") for i, s in jsonStrList] diff --git a/test/grammar/builtins/json/dump_to_file_0/stdout.golden b/test/grammar/builtins/json/dump_to_file_0/stdout.golden new file mode 100644 index 000000000..ea6509147 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_0/stdout.golden @@ -0,0 +1,10 @@ +jsonStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' diff --git a/test/grammar/builtins/json/dump_to_file_1/0.yaml b/test/grammar/builtins/json/dump_to_file_1/0.yaml new file mode 100644 index 000000000..8593e686f --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/0.yaml @@ -0,0 +1 @@ +'key: value' diff --git a/test/grammar/builtins/json/dump_to_file_1/1.yaml b/test/grammar/builtins/json/dump_to_file_1/1.yaml new file mode 100644 index 000000000..726ba9b9d --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/1.yaml @@ -0,0 +1,4 @@ +|- + - 1 + - 2 + - 3 diff --git a/test/grammar/builtins/json/dump_to_file_1/2.yaml b/test/grammar/builtins/json/dump_to_file_1/2.yaml new file mode 100644 index 000000000..cb382054c --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/2.yaml @@ -0,0 +1 @@ +'1' diff --git a/test/grammar/builtins/json/dump_to_file_1/3.yaml b/test/grammar/builtins/json/dump_to_file_1/3.yaml new file mode 100644 index 000000000..95c82787d --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/3.yaml @@ -0,0 +1 @@ +'1.1' diff --git a/test/grammar/builtins/json/dump_to_file_1/4.yaml b/test/grammar/builtins/json/dump_to_file_1/4.yaml new file mode 100644 index 000000000..c99e6404c --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/4.yaml @@ -0,0 +1 @@ +'null' diff --git a/test/grammar/builtins/json/dump_to_file_1/5.yaml b/test/grammar/builtins/json/dump_to_file_1/5.yaml new file mode 100644 index 000000000..fda5ad905 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/5.yaml @@ -0,0 +1 @@ +'true' diff --git a/test/grammar/builtins/json/dump_to_file_1/main.k b/test/grammar/builtins/json/dump_to_file_1/main.k new file mode 100644 index 000000000..aa6738c03 --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/main.k @@ -0,0 +1,11 @@ +import yaml + +yamlStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +_ = [yaml.dump_to_file(s, filename="${i}.yaml") for i, s in yamlStrList] diff --git a/test/grammar/builtins/json/dump_to_file_1/stdout.golden b/test/grammar/builtins/json/dump_to_file_1/stdout.golden new file mode 100644 index 000000000..d013fc8fb --- /dev/null +++ b/test/grammar/builtins/json/dump_to_file_1/stdout.golden @@ -0,0 +1,10 @@ +yamlStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' diff --git a/test/grammar/builtins/json/output_0/main.k b/test/grammar/builtins/json/output_0/main.k index 5be6161d0..ca63c5961 100644 --- a/test/grammar/builtins/json/output_0/main.k +++ b/test/grammar/builtins/json/output_0/main.k @@ -2,7 +2,6 @@ import json schema Person: - __settings__: {str:str} = {"output_type": "STANDALONE"} name?: str age?: int school?: str diff --git a/test/grammar/builtins/json/output_1/main.k b/test/grammar/builtins/json/output_1/main.k index 6e22b6137..e9c3cc5ec 100644 --- a/test/grammar/builtins/json/output_1/main.k +++ b/test/grammar/builtins/json/output_1/main.k @@ -2,16 +2,14 @@ import json schema Person: - __settings__: {str:str} = {"output_type": "STANDALONE"} name?: str age?: int school?: str data?: [int] = [1, 2, None] -_person = Person { +person = Person { name: "Alice" age: 18 } -_filename = "out.json" -print("JSON output is in {}".format(_filename)) -json.dump_to_file(_person, _filename, indent=4, ignore_private=True, ignore_none=True) +filename = "out.json" +json.dump_to_file(person, filename, indent=4, ignore_private=True, ignore_none=True) diff --git a/test/grammar/builtins/json/output_1/stdout.golden b/test/grammar/builtins/json/output_1/stdout.golden index 27297403a..24ff32c56 100644 --- a/test/grammar/builtins/json/output_1/stdout.golden +++ b/test/grammar/builtins/json/output_1/stdout.golden @@ -1 +1,8 @@ -JSON output is in out.json +person: + name: Alice + age: 18 + data: + - 1 + - 2 + - null +filename: out.json diff --git a/test/grammar/builtins/json/validate/main.k b/test/grammar/builtins/json/validate/main.k new file mode 100644 index 000000000..7acff6bd3 --- /dev/null +++ b/test/grammar/builtins/json/validate/main.k @@ -0,0 +1,19 @@ +import json + +# Right cases + +resultRight1: bool = json.validate("1") +resultRight2: bool = json.validate("true") +resultRight3: bool = json.validate("1.20") +resultRight4: bool = json.validate("null") +resultRight5: bool = json.validate("[0, 1, 2]") +resultRight6: bool = json.validate('{"key": "value"}') + +# Wrong cases + +resultWrong1: bool = json.validate("1@") +resultWrong2: bool = json.validate("True") +resultWrong3: bool = json.validate("1.20.23+1") +resultWrong4: bool = json.validate("None") +resultWrong5: bool = json.validate("[0, 1, 2,]") +resultWrong6: bool = json.validate(r'''{"key": 'value'}''') diff --git a/test/grammar/builtins/json/validate/stdout.golden b/test/grammar/builtins/json/validate/stdout.golden new file mode 100644 index 000000000..60321cd70 --- /dev/null +++ b/test/grammar/builtins/json/validate/stdout.golden @@ -0,0 +1,12 @@ +resultRight1: true +resultRight2: true +resultRight3: true +resultRight4: true +resultRight5: true +resultRight6: true +resultWrong1: false +resultWrong2: false +resultWrong3: false +resultWrong4: false +resultWrong5: false +resultWrong6: false diff --git a/test/grammar/builtins/manifests/yaml_stream/config/main.k b/test/grammar/builtins/manifests/yaml_stream/config/main.k new file mode 100644 index 000000000..95d777dd7 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config/main.k @@ -0,0 +1,11 @@ +import manifests + +schema Person: + name: str = "kcl" + age: int = 1 + +x0 = Person {} +x1 = Person { + age = 101 +} +manifests.yaml_stream([x0, x1]) diff --git a/test/grammar/builtins/manifests/yaml_stream/config/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/config/stdout.golden new file mode 100644 index 000000000..c3eb922d7 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config/stdout.golden @@ -0,0 +1,5 @@ +name: kcl +age: 1 +--- +name: kcl +age: 101 diff --git a/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/main.k b/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/main.k new file mode 100644 index 000000000..bb632ddf2 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/main.k @@ -0,0 +1,11 @@ +import manifests + +schema Person: + name: str = "kcl" + age?: int = 1 + +x0 = Person {} +x1 = Person { + age = None +} +manifests.yaml_stream([x0, x1], opts = {ignore_none = True}) diff --git a/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/stdout.golden new file mode 100644 index 000000000..30fcca92f --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config_ignore_none/stdout.golden @@ -0,0 +1,4 @@ +name: kcl +age: 1 +--- +name: kcl diff --git a/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/main.k b/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/main.k new file mode 100644 index 000000000..1421735c6 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/main.k @@ -0,0 +1,11 @@ +import manifests + +schema Person: + name: str = "kcl" + age: int = 1 + +x0 = Person {} +x1 = Person { + age = 101 +} +manifests.yaml_stream([x0, x1], opts = {sort_keys = True}) diff --git a/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/stdout.golden new file mode 100644 index 000000000..e80c18631 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/config_sort_keys/stdout.golden @@ -0,0 +1,5 @@ +age: 1 +name: kcl +--- +age: 101 +name: kcl diff --git a/test/grammar/builtins/manifests/yaml_stream/list/main.k b/test/grammar/builtins/manifests/yaml_stream/list/main.k new file mode 100644 index 000000000..f23e06233 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/list/main.k @@ -0,0 +1,3 @@ +import manifests + +manifests.yaml_stream([{k1 = [1, 2], k2 = [3, 4]}, {k3 = [5, 6], k4 = [7, 8]}, {k5 = [9, 10]}]) diff --git a/test/grammar/builtins/manifests/yaml_stream/list/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/list/stdout.golden new file mode 100644 index 000000000..cf081cf3d --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/list/stdout.golden @@ -0,0 +1,17 @@ +k1: +- 1 +- 2 +k2: +- 3 +- 4 +--- +k3: +- 5 +- 6 +k4: +- 7 +- 8 +--- +k5: +- 9 +- 10 diff --git a/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/main.k b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/main.k new file mode 100644 index 000000000..aad0badc5 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/main.k @@ -0,0 +1,3 @@ +import manifests + +manifests.yaml_stream([1, 2, 3]) diff --git a/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/stdout.golden new file mode 100644 index 000000000..5fd5cb2ad --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_0/stdout.golden @@ -0,0 +1,5 @@ +1 +--- +2 +--- +3 diff --git a/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/main.k b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/main.k new file mode 100644 index 000000000..f9e0ace0d --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/main.k @@ -0,0 +1,3 @@ +import manifests + +manifests.yaml_stream([1, Undefined, 2Mi, 3.0, "literal", True, False, None]) diff --git a/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/stdout.golden new file mode 100644 index 000000000..9897c5c14 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/multiple_literal_1/stdout.golden @@ -0,0 +1,15 @@ +1 +--- +null +--- +2097152.0 +--- +3.0 +--- +literal +--- +true +--- +false +--- +null diff --git a/test/grammar/builtins/manifests/yaml_stream/single_literal_0/main.k b/test/grammar/builtins/manifests/yaml_stream/single_literal_0/main.k new file mode 100644 index 000000000..1d77a8722 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/single_literal_0/main.k @@ -0,0 +1,3 @@ +import manifests + +manifests.yaml_stream([1]) diff --git a/test/grammar/builtins/manifests/yaml_stream/single_literal_0/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/single_literal_0/stdout.golden new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/single_literal_0/stdout.golden @@ -0,0 +1 @@ +1 diff --git a/test/grammar/builtins/manifests/yaml_stream/single_literal_1/main.k b/test/grammar/builtins/manifests/yaml_stream/single_literal_1/main.k new file mode 100644 index 000000000..89df72131 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/single_literal_1/main.k @@ -0,0 +1,3 @@ +import manifests + +manifests.yaml_stream([None]) diff --git a/test/grammar/builtins/manifests/yaml_stream/single_literal_1/stdout.golden b/test/grammar/builtins/manifests/yaml_stream/single_literal_1/stdout.golden new file mode 100644 index 000000000..19765bd50 --- /dev/null +++ b/test/grammar/builtins/manifests/yaml_stream/single_literal_1/stdout.golden @@ -0,0 +1 @@ +null diff --git a/test/grammar/builtins/yaml/decode_all_0/main.k b/test/grammar/builtins/yaml/decode_all_0/main.k new file mode 100644 index 000000000..af7f4da6d --- /dev/null +++ b/test/grammar/builtins/yaml/decode_all_0/main.k @@ -0,0 +1,11 @@ +import yaml + +yamlStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +data = [yaml.decode_all(s) for s in yamlStrList] diff --git a/test/grammar/builtins/yaml/decode_all_0/stdout.golden b/test/grammar/builtins/yaml/decode_all_0/stdout.golden new file mode 100644 index 000000000..e5b0ffa4d --- /dev/null +++ b/test/grammar/builtins/yaml/decode_all_0/stdout.golden @@ -0,0 +1,19 @@ +yamlStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' +data: +- key: value +- - 1 + - 2 + - 3 +- 1 +- 1.1 +- null +- true diff --git a/test/grammar/builtins/yaml/decode_all_1/main.k b/test/grammar/builtins/yaml/decode_all_1/main.k new file mode 100644 index 000000000..e67562cfa --- /dev/null +++ b/test/grammar/builtins/yaml/decode_all_1/main.k @@ -0,0 +1,9 @@ +import yaml + +yamlStrList = [ + 'key1: value2\n---\nkey2: [1, 2, 3]', + '- 1\n- 2\n- 3\n---\nkey: value', + '1\n---\n2', + '1.1\n---\nnull\n---\ntrue\n---\nfalse', +] +data = [yaml.decode_all(s) for s in yamlStrList] diff --git a/test/grammar/builtins/yaml/decode_all_1/stdout.golden b/test/grammar/builtins/yaml/decode_all_1/stdout.golden new file mode 100644 index 000000000..2c4dac91d --- /dev/null +++ b/test/grammar/builtins/yaml/decode_all_1/stdout.golden @@ -0,0 +1,39 @@ +yamlStrList: +- |- + key1: value2 + --- + key2: [1, 2, 3] +- |- + - 1 + - 2 + - 3 + --- + key: value +- |- + 1 + --- + 2 +- |- + 1.1 + --- + null + --- + true + --- + false +data: +- - key1: value2 + - key2: + - 1 + - 2 + - 3 +- - - 1 + - 2 + - 3 + - key: value +- - 1 + - 2 +- - 1.1 + - null + - true + - false diff --git a/test/grammar/builtins/yaml/dump_all_to_file_0/0.yaml b/test/grammar/builtins/yaml/dump_all_to_file_0/0.yaml new file mode 100644 index 000000000..ad428a629 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_all_to_file_0/0.yaml @@ -0,0 +1,19 @@ +'key: value' + +--- +|- + - 1 + - 2 + - 3 + +--- +'1' + +--- +'1.1' + +--- +'null' + +--- +'true' diff --git a/test/grammar/builtins/yaml/dump_all_to_file_0/main.k b/test/grammar/builtins/yaml/dump_all_to_file_0/main.k new file mode 100644 index 000000000..af1607990 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_all_to_file_0/main.k @@ -0,0 +1,11 @@ +import yaml + +yamlStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +yaml.dump_all_to_file(yamlStrList, "0.yaml") diff --git a/test/grammar/builtins/yaml/dump_all_to_file_0/stdout.golden b/test/grammar/builtins/yaml/dump_all_to_file_0/stdout.golden new file mode 100644 index 000000000..d013fc8fb --- /dev/null +++ b/test/grammar/builtins/yaml/dump_all_to_file_0/stdout.golden @@ -0,0 +1,10 @@ +yamlStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/0.yaml b/test/grammar/builtins/yaml/dump_to_file_0/0.yaml new file mode 100644 index 000000000..8593e686f --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/0.yaml @@ -0,0 +1 @@ +'key: value' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/1.yaml b/test/grammar/builtins/yaml/dump_to_file_0/1.yaml new file mode 100644 index 000000000..726ba9b9d --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/1.yaml @@ -0,0 +1,4 @@ +|- + - 1 + - 2 + - 3 diff --git a/test/grammar/builtins/yaml/dump_to_file_0/2.yaml b/test/grammar/builtins/yaml/dump_to_file_0/2.yaml new file mode 100644 index 000000000..cb382054c --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/2.yaml @@ -0,0 +1 @@ +'1' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/3.yaml b/test/grammar/builtins/yaml/dump_to_file_0/3.yaml new file mode 100644 index 000000000..95c82787d --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/3.yaml @@ -0,0 +1 @@ +'1.1' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/4.yaml b/test/grammar/builtins/yaml/dump_to_file_0/4.yaml new file mode 100644 index 000000000..c99e6404c --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/4.yaml @@ -0,0 +1 @@ +'null' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/5.yaml b/test/grammar/builtins/yaml/dump_to_file_0/5.yaml new file mode 100644 index 000000000..fda5ad905 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/5.yaml @@ -0,0 +1 @@ +'true' diff --git a/test/grammar/builtins/yaml/dump_to_file_0/main.k b/test/grammar/builtins/yaml/dump_to_file_0/main.k new file mode 100644 index 000000000..117f93bf9 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/main.k @@ -0,0 +1,11 @@ +import yaml + +yamlStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +_ = [yaml.dump_to_file(s, "${i}.yaml") for i, s in yamlStrList] diff --git a/test/grammar/builtins/yaml/dump_to_file_0/stdout.golden b/test/grammar/builtins/yaml/dump_to_file_0/stdout.golden new file mode 100644 index 000000000..d013fc8fb --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_0/stdout.golden @@ -0,0 +1,10 @@ +yamlStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/0.yaml b/test/grammar/builtins/yaml/dump_to_file_1/0.yaml new file mode 100644 index 000000000..8593e686f --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/0.yaml @@ -0,0 +1 @@ +'key: value' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/1.yaml b/test/grammar/builtins/yaml/dump_to_file_1/1.yaml new file mode 100644 index 000000000..726ba9b9d --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/1.yaml @@ -0,0 +1,4 @@ +|- + - 1 + - 2 + - 3 diff --git a/test/grammar/builtins/yaml/dump_to_file_1/2.yaml b/test/grammar/builtins/yaml/dump_to_file_1/2.yaml new file mode 100644 index 000000000..cb382054c --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/2.yaml @@ -0,0 +1 @@ +'1' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/3.yaml b/test/grammar/builtins/yaml/dump_to_file_1/3.yaml new file mode 100644 index 000000000..95c82787d --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/3.yaml @@ -0,0 +1 @@ +'1.1' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/4.yaml b/test/grammar/builtins/yaml/dump_to_file_1/4.yaml new file mode 100644 index 000000000..c99e6404c --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/4.yaml @@ -0,0 +1 @@ +'null' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/5.yaml b/test/grammar/builtins/yaml/dump_to_file_1/5.yaml new file mode 100644 index 000000000..fda5ad905 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/5.yaml @@ -0,0 +1 @@ +'true' diff --git a/test/grammar/builtins/yaml/dump_to_file_1/main.k b/test/grammar/builtins/yaml/dump_to_file_1/main.k new file mode 100644 index 000000000..aa6738c03 --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/main.k @@ -0,0 +1,11 @@ +import yaml + +yamlStrList = [ + 'key: value', + '- 1\n- 2\n- 3', + '1', + '1.1', + 'null', + 'true', +] +_ = [yaml.dump_to_file(s, filename="${i}.yaml") for i, s in yamlStrList] diff --git a/test/grammar/builtins/yaml/dump_to_file_1/stdout.golden b/test/grammar/builtins/yaml/dump_to_file_1/stdout.golden new file mode 100644 index 000000000..d013fc8fb --- /dev/null +++ b/test/grammar/builtins/yaml/dump_to_file_1/stdout.golden @@ -0,0 +1,10 @@ +yamlStrList: +- 'key: value' +- |- + - 1 + - 2 + - 3 +- '1' +- '1.1' +- 'null' +- 'true' diff --git a/test/grammar/builtins/yaml/encode_0/_main.k b/test/grammar/builtins/yaml/encode_0/_main.k deleted file mode 100644 index da9c24ede..000000000 --- a/test/grammar/builtins/yaml/encode_0/_main.k +++ /dev/null @@ -1,11 +0,0 @@ -import yaml - -dataDict = {"key": "value"} -dataList = [1, 2, 3] -#dataInt = 1 -#dataFloat = 1.1 -#dataNone = None -#dataBool = True - -#yamlStr = [yaml.encode(data) for data in [dataDict, dataList, dataInt, dataFloat, dataNone, dataBool]] -yamlStr = [yaml.encode(data) for data in [dataDict, dataList]] diff --git a/test/grammar/builtins/yaml/encode_0/main.k b/test/grammar/builtins/yaml/encode_0/main.k new file mode 100644 index 000000000..51e77fba3 --- /dev/null +++ b/test/grammar/builtins/yaml/encode_0/main.k @@ -0,0 +1,6 @@ +import yaml + +dataDict = {"key": "value"} +dataList = [1, 2, 3] + +yamlStr = [yaml.encode(data) for data in [dataDict, dataList]] diff --git a/test/grammar/builtins/yaml/encode_1/_main.k b/test/grammar/builtins/yaml/encode_1/main.k similarity index 100% rename from test/grammar/builtins/yaml/encode_1/_main.k rename to test/grammar/builtins/yaml/encode_1/main.k diff --git a/test/grammar/builtins/yaml/encode_all_0/main.k b/test/grammar/builtins/yaml/encode_all_0/main.k new file mode 100644 index 000000000..f99c6b70a --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_0/main.k @@ -0,0 +1,6 @@ +import yaml + +dataDict = {"key": "value"} +dataList = [1, 2, 3] + +yamlStr = yaml.encode_all([dataDict, dataList]) diff --git a/test/grammar/builtins/yaml/encode_all_0/stdout.golden b/test/grammar/builtins/yaml/encode_all_0/stdout.golden new file mode 100644 index 000000000..7f546203d --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_0/stdout.golden @@ -0,0 +1,13 @@ +dataDict: + key: value +dataList: +- 1 +- 2 +- 3 +yamlStr: | + key: value + + --- + - 1 + - 2 + - 3 diff --git a/test/grammar/builtins/yaml/encode_all_1/main.k b/test/grammar/builtins/yaml/encode_all_1/main.k new file mode 100644 index 000000000..be26367f6 --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_1/main.k @@ -0,0 +1,3 @@ +import yaml + +yamlStr = yaml.encode_all([{"key": [1, 2, 3]}, [1, 2, 3]]) diff --git a/test/grammar/builtins/yaml/encode_all_1/stdout.golden b/test/grammar/builtins/yaml/encode_all_1/stdout.golden new file mode 100644 index 000000000..7484e6014 --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_1/stdout.golden @@ -0,0 +1,10 @@ +yamlStr: | + key: + - 1 + - 2 + - 3 + + --- + - 1 + - 2 + - 3 diff --git a/test/grammar/builtins/yaml/encode_all_2/main.k b/test/grammar/builtins/yaml/encode_all_2/main.k new file mode 100644 index 000000000..39c7e53db --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_2/main.k @@ -0,0 +1,3 @@ +import yaml + +yamlStr = yaml.encode_all([1, 2, 3]) diff --git a/test/grammar/builtins/yaml/encode_all_2/stdout.golden b/test/grammar/builtins/yaml/encode_all_2/stdout.golden new file mode 100644 index 000000000..f5df77f8d --- /dev/null +++ b/test/grammar/builtins/yaml/encode_all_2/stdout.golden @@ -0,0 +1,8 @@ +yamlStr: | + 1 + + --- + 2 + + --- + 3 diff --git a/test/grammar/builtins/yaml/output_0/_main.k b/test/grammar/builtins/yaml/output_0/_main.k deleted file mode 100644 index d0c0fd63f..000000000 --- a/test/grammar/builtins/yaml/output_0/_main.k +++ /dev/null @@ -1,24 +0,0 @@ - -import yaml - -schema Person: - __settings__: {str:str} = {"output_type": "STANDALONE"} - name?: str - age?: int - school?: str - data?: [int] = [1, 2, None] - -_person = Person { - name: "Alice" - age: 18 -} -# print(yaml.encode(_person), end="") -# print("---") -# print(yaml.encode(_person, ignore_private=True), end="") -# print("---") -# print(yaml.encode(_person, ignore_none=True), end="") -# print("---") -# print(yaml.encode(_person, ignore_private=True, ignore_none=True), end="") - -a1 = yaml.encode(_person, ignore_private=True) -a2 = yaml.encode(_person, ignore_private=True, ignore_none=True) diff --git a/test/grammar/builtins/yaml/output_0/main.k b/test/grammar/builtins/yaml/output_0/main.k new file mode 100644 index 000000000..cb728ede7 --- /dev/null +++ b/test/grammar/builtins/yaml/output_0/main.k @@ -0,0 +1,15 @@ + +import yaml + +schema Person: + name?: str + age?: int + school?: str + data?: [int] = [1, 2, None] + +_person = Person { + name: "Alice" + age: 18 +} +a1 = yaml.encode(_person, ignore_private=True) +a2 = yaml.encode(_person, ignore_private=True, ignore_none=True) diff --git a/test/grammar/builtins/yaml/output_1/main.k b/test/grammar/builtins/yaml/output_1/main.k index 01c2b23a4..4e1830afb 100644 --- a/test/grammar/builtins/yaml/output_1/main.k +++ b/test/grammar/builtins/yaml/output_1/main.k @@ -2,16 +2,14 @@ import yaml schema Person: - __settings__: {str:str} = {"output_type": "STANDALONE"} name?: str age?: int school?: str data?: [int] = [1, 2, None] -_person = Person { +person = Person { name: "Alice" age: 18 } -_filename = "out.yaml" -print("YAML output is in {}".format(_filename)) -yaml.dump_to_file(_person, _filename, ignore_private=True, ignore_none=True) +filename = "out.yaml" +yaml.dump_to_file(person, filename, ignore_private=True, ignore_none=True) diff --git a/test/grammar/builtins/yaml/output_1/stdout.golden b/test/grammar/builtins/yaml/output_1/stdout.golden index e244fa844..4d4e735e2 100644 --- a/test/grammar/builtins/yaml/output_1/stdout.golden +++ b/test/grammar/builtins/yaml/output_1/stdout.golden @@ -1 +1,8 @@ -YAML output is in out.yaml +person: + name: Alice + age: 18 + data: + - 1 + - 2 + - null +filename: out.yaml diff --git a/test/grammar/builtins/yaml/validate/main.k b/test/grammar/builtins/yaml/validate/main.k new file mode 100644 index 000000000..46a22fa05 --- /dev/null +++ b/test/grammar/builtins/yaml/validate/main.k @@ -0,0 +1,21 @@ +import yaml + +# Right cases + +resultRight1: bool = yaml.validate("1") +resultRight2: bool = yaml.validate("true") +resultRight3: bool = yaml.validate("1.20") +resultRight4: bool = yaml.validate("null") +resultRight5: bool = yaml.validate("[0, 1, 2]") +resultRight6: bool = yaml.validate('{"key": "value"}') +resultRight7: bool = yaml.validate('a:1\n---\nb:2') + +# Wrong cases + +resultWrong1: bool = yaml.validate("a:\n1") +resultWrong2: bool = yaml.validate("a:\n1\n - 2") +resultWrong3: bool = yaml.validate("a:\n-1") +resultWrong4: bool = yaml.validate("1a : \n1") +resultWrong5: bool = yaml.validate("a:\n- 1\n-----\na:\n- 1") +resultWrong6: bool = yaml.validate(r'''{"key" + 'value'}''') +resultWrong7: bool = yaml.validate("a:1\n-----\nb:\n-2") diff --git a/test/grammar/builtins/yaml/validate/stdout.golden b/test/grammar/builtins/yaml/validate/stdout.golden new file mode 100644 index 000000000..f8d846f47 --- /dev/null +++ b/test/grammar/builtins/yaml/validate/stdout.golden @@ -0,0 +1,14 @@ +resultRight1: true +resultRight2: true +resultRight3: true +resultRight4: true +resultRight5: true +resultRight6: true +resultRight7: true +resultWrong1: false +resultWrong2: false +resultWrong3: false +resultWrong4: false +resultWrong5: false +resultWrong6: false +resultWrong7: false diff --git a/test/grammar/comprehension/dict/local_var_as_key/main.k b/test/grammar/comprehension/dict/local_var_as_key/main.k new file mode 100644 index 000000000..1acf2c7a5 --- /dev/null +++ b/test/grammar/comprehension/dict/local_var_as_key/main.k @@ -0,0 +1,10 @@ +_data = { + "a": 'foo' + "b": 'bar' +} + +r0 = [{v = k} for k, v in _data] +r1 = [{k = v} for k, v in _data] +r2 = [{k.foo = v} for k, v in _data] +r3 = [[k] for k, v in _data] +r4 = [[k, v] for k, v in _data] diff --git a/test/grammar/comprehension/dict/local_var_as_key/stdout.golden b/test/grammar/comprehension/dict/local_var_as_key/stdout.golden new file mode 100644 index 000000000..0c16d7b0f --- /dev/null +++ b/test/grammar/comprehension/dict/local_var_as_key/stdout.golden @@ -0,0 +1,19 @@ +r0: +- foo: a +- bar: b +r1: +- a: foo +- b: bar +r2: +- a: + foo: foo +- b: + foo: bar +r3: +- - a +- - b +r4: +- - a + - foo +- - b + - bar diff --git a/test/grammar/datatype/dict/mutual_ref_14/main.k b/test/grammar/datatype/dict/mutual_ref_14/main.k new file mode 100644 index 000000000..4b94a8d26 --- /dev/null +++ b/test/grammar/datatype/dict/mutual_ref_14/main.k @@ -0,0 +1,6 @@ +deployment = { + metadata.labels.k1 = "v1" + metadata.namespace = "default" + spec.selector.matchLabels = metadata.labels | {k2 = "v2"} +} +labels: {str:str} = deployment.metadata.labels diff --git a/test/grammar/datatype/dict/mutual_ref_14/stdout.golden b/test/grammar/datatype/dict/mutual_ref_14/stdout.golden new file mode 100644 index 000000000..30497ce0c --- /dev/null +++ b/test/grammar/datatype/dict/mutual_ref_14/stdout.golden @@ -0,0 +1,12 @@ +deployment: + metadata: + labels: + k1: v1 + namespace: default + spec: + selector: + matchLabels: + k1: v1 + k2: v2 +labels: + k1: v1 diff --git a/test/grammar/datatype/undefined/fail_1/stderr.golden.py b/test/grammar/datatype/undefined/fail_1/stderr.golden.py index 08affb444..6ed112d57 100644 --- a/test/grammar/datatype/undefined/fail_1/stderr.golden.py +++ b/test/grammar/datatype/undefined/fail_1/stderr.golden.py @@ -14,7 +14,7 @@ line_no=1 ) ], - arg_msg="int() argument must be a string, a bytes-like object or a number, not 'UndefinedType'" + arg_msg="int() argument must be a string or a number, not 'UndefinedType'" ) , file=sys.stdout ) diff --git a/test/grammar/datatype/units/simple_4/stdout.golden b/test/grammar/datatype/units/simple_4/stdout.golden index 10b6fed8c..7c3083df8 100644 --- a/test/grammar/datatype/units/simple_4/stdout.golden +++ b/test/grammar/datatype/units/simple_4/stdout.golden @@ -1,11 +1,11 @@ -x0: 1000000 -x1: 1000000 +x0: 1000000.0 +x1: 1000000.0 x2: 1000000 x3: 1000000.0 -x4: 1000000 -x5: 1000000 -x6: 1024 -x7: 1024 +x4: 1000000.0 +x5: 1000000.0 +x6: 1024.0 +x7: 1024.0 x0str: 1M x1str: 1M x2str: '1000000' @@ -13,4 +13,4 @@ x3str: '1000000.0' x4str: 1M x5str: 1M x6str: 1Ki -x7str: '{"k": "1Ki"}' +x7str: '{"k": 1024.0}' diff --git a/test/grammar/expr/select_expr/in_for_0/stdout.golden b/test/grammar/expr/select_expr/in_for_0/stdout.golden index a13ffd4bb..7f05c6719 100644 --- a/test/grammar/expr/select_expr/in_for_0/stdout.golden +++ b/test/grammar/expr/select_expr/in_for_0/stdout.golden @@ -1,2 +1,3 @@ c: - name: main + volumeMounts: [] diff --git a/test/grammar/lambda/arg_type/main.k b/test/grammar/lambda/arg_type/main.k new file mode 100644 index 000000000..3cf3c8756 --- /dev/null +++ b/test/grammar/lambda/arg_type/main.k @@ -0,0 +1,9 @@ +import sub as s + +identity = lambda res: s.Test { + res { + name = "world" + } +} + +c = identity(s.Test{name="hello"}) diff --git a/test/grammar/lambda/arg_type/stdout.golden b/test/grammar/lambda/arg_type/stdout.golden new file mode 100644 index 000000000..81be50f43 --- /dev/null +++ b/test/grammar/lambda/arg_type/stdout.golden @@ -0,0 +1,2 @@ +c: + name: world \ No newline at end of file diff --git a/test/grammar/lambda/arg_type/sub.k b/test/grammar/lambda/arg_type/sub.k new file mode 100644 index 000000000..df60bab68 --- /dev/null +++ b/test/grammar/lambda/arg_type/sub.k @@ -0,0 +1,2 @@ +schema Test: + name: str \ No newline at end of file diff --git a/test/grammar/lambda/arg_type_annotation/main.k b/test/grammar/lambda/arg_type_annotation/main.k new file mode 100644 index 000000000..3306437e7 --- /dev/null +++ b/test/grammar/lambda/arg_type_annotation/main.k @@ -0,0 +1,9 @@ +import sub as s + +identity: (s.Test) -> s.Test = lambda res: s.Test { + res { + name = "world" + } +} + +c = identity(s.Test{name="hello"}) diff --git a/test/grammar/lambda/arg_type_annotation/stdout.golden b/test/grammar/lambda/arg_type_annotation/stdout.golden new file mode 100644 index 000000000..81be50f43 --- /dev/null +++ b/test/grammar/lambda/arg_type_annotation/stdout.golden @@ -0,0 +1,2 @@ +c: + name: world \ No newline at end of file diff --git a/test/grammar/lambda/arg_type_annotation/sub.k b/test/grammar/lambda/arg_type_annotation/sub.k new file mode 100644 index 000000000..df60bab68 --- /dev/null +++ b/test/grammar/lambda/arg_type_annotation/sub.k @@ -0,0 +1,2 @@ +schema Test: + name: str \ No newline at end of file diff --git a/test/grammar/lambda/closure_0_annotation/main.k b/test/grammar/lambda/closure_0_annotation/main.k new file mode 100644 index 000000000..52e2d4053 --- /dev/null +++ b/test/grammar/lambda/closure_0_annotation/main.k @@ -0,0 +1,6 @@ +x : int = lambda { + a = 1 + lambda { + a + 1 + }() +}() diff --git a/test/grammar/lambda/closure_0_annotation/stdout.golden b/test/grammar/lambda/closure_0_annotation/stdout.golden new file mode 100644 index 000000000..ad932ccf5 --- /dev/null +++ b/test/grammar/lambda/closure_0_annotation/stdout.golden @@ -0,0 +1 @@ +x: 2 diff --git a/test/grammar/lambda/closure_10/main.k b/test/grammar/lambda/closure_10/main.k new file mode 100644 index 000000000..d0fa36e81 --- /dev/null +++ b/test/grammar/lambda/closure_10/main.k @@ -0,0 +1,14 @@ +func = lambda config: {str:} { + x = 1 + lambda { + y = 1 + lambda { + z = 1 + [lambda q { + {value = x + y + z + config.key + q + i} + }(1) for i in range(1, 2)][0] + }() + }() +} + +x = func({key = 1}) diff --git a/test/grammar/lambda/closure_10/stdout.golden b/test/grammar/lambda/closure_10/stdout.golden new file mode 100644 index 000000000..8094c6f61 --- /dev/null +++ b/test/grammar/lambda/closure_10/stdout.golden @@ -0,0 +1,2 @@ +x: + value: 6 diff --git a/test/grammar/lambda/closure_1_annotation/main.k b/test/grammar/lambda/closure_1_annotation/main.k new file mode 100644 index 000000000..2311aa8e5 --- /dev/null +++ b/test/grammar/lambda/closure_1_annotation/main.k @@ -0,0 +1,7 @@ +x: int = lambda { + a = 1 + b = 2 + lambda x { + a + b + x + }(3) +}() diff --git a/test/grammar/lambda/closure_1_annotation/stdout.golden b/test/grammar/lambda/closure_1_annotation/stdout.golden new file mode 100644 index 000000000..a1ad2d1c9 --- /dev/null +++ b/test/grammar/lambda/closure_1_annotation/stdout.golden @@ -0,0 +1 @@ +x: 6 diff --git a/test/grammar/lambda/closure_2_annotation/main.k b/test/grammar/lambda/closure_2_annotation/main.k new file mode 100644 index 000000000..c52ea6265 --- /dev/null +++ b/test/grammar/lambda/closure_2_annotation/main.k @@ -0,0 +1,10 @@ +x: int = lambda { + a = 1 + lambda { + b = 2 + c = 3 + lambda a { + a + b + c + }(a) + }() +}() diff --git a/test/grammar/lambda/closure_2_annotation/stdout.golden b/test/grammar/lambda/closure_2_annotation/stdout.golden new file mode 100644 index 000000000..a1ad2d1c9 --- /dev/null +++ b/test/grammar/lambda/closure_2_annotation/stdout.golden @@ -0,0 +1 @@ +x: 6 diff --git a/test/grammar/lambda/closure_4_annotation/main.k b/test/grammar/lambda/closure_4_annotation/main.k new file mode 100644 index 000000000..c19e4845a --- /dev/null +++ b/test/grammar/lambda/closure_4_annotation/main.k @@ -0,0 +1,9 @@ +x: int = lambda { + a = 1 + lambda { + b = a + 1 + lambda { + c = b + 1 + }() + }() +}() diff --git a/test/grammar/lambda/closure_4_annotation/stdout.golden b/test/grammar/lambda/closure_4_annotation/stdout.golden new file mode 100644 index 000000000..e5cfddc4f --- /dev/null +++ b/test/grammar/lambda/closure_4_annotation/stdout.golden @@ -0,0 +1 @@ +x: 3 diff --git a/test/grammar/lambda/closure_5_annotation/main.k b/test/grammar/lambda/closure_5_annotation/main.k new file mode 100644 index 000000000..24781567a --- /dev/null +++ b/test/grammar/lambda/closure_5_annotation/main.k @@ -0,0 +1,12 @@ +x: int = lambda { + a = 1 + lambda { + b = a + 1 + lambda { + c = b + 1 + lambda { + d = c + 1 + }() + }() + }() +}() diff --git a/test/grammar/lambda/closure_5_annotation/stdout.golden b/test/grammar/lambda/closure_5_annotation/stdout.golden new file mode 100644 index 000000000..456a2f814 --- /dev/null +++ b/test/grammar/lambda/closure_5_annotation/stdout.golden @@ -0,0 +1 @@ +x: 4 diff --git a/test/grammar/lambda/closure_6/main.k b/test/grammar/lambda/closure_6/main.k new file mode 100644 index 000000000..f1c0869a1 --- /dev/null +++ b/test/grammar/lambda/closure_6/main.k @@ -0,0 +1,14 @@ +func = lambda config: {str:} { + x = 1 + lambda { + y = 1 + lambda { + z = 1 + lambda { + x + y + z + config.key + }() + }() + }() +} + +x = func({key = 1}) diff --git a/test/grammar/lambda/closure_6/stdout.golden b/test/grammar/lambda/closure_6/stdout.golden new file mode 100644 index 000000000..456a2f814 --- /dev/null +++ b/test/grammar/lambda/closure_6/stdout.golden @@ -0,0 +1 @@ +x: 4 diff --git a/test/grammar/lambda/closure_7/main.k b/test/grammar/lambda/closure_7/main.k new file mode 100644 index 000000000..059a15ae7 --- /dev/null +++ b/test/grammar/lambda/closure_7/main.k @@ -0,0 +1,14 @@ +func = lambda config: {str:} { + x = 1 + lambda { + y = 1 + lambda { + z = 1 + lambda { + {value = x + y + z + config.key} + }() + }() + }() +} + +x = func({key = 1}) diff --git a/test/grammar/lambda/closure_7/stdout.golden b/test/grammar/lambda/closure_7/stdout.golden new file mode 100644 index 000000000..711dd9f7c --- /dev/null +++ b/test/grammar/lambda/closure_7/stdout.golden @@ -0,0 +1,2 @@ +x: + value: 4 diff --git a/test/grammar/lambda/closure_8/main.k b/test/grammar/lambda/closure_8/main.k new file mode 100644 index 000000000..a126e994f --- /dev/null +++ b/test/grammar/lambda/closure_8/main.k @@ -0,0 +1,8 @@ +items = [1, 2, 3] +func = lambda config: {str:} { + [lambda { + config.key + i + }() for i in items] +} + +x = func({key = 1}) diff --git a/test/grammar/lambda/closure_8/stdout.golden b/test/grammar/lambda/closure_8/stdout.golden new file mode 100644 index 000000000..30c4fe9ae --- /dev/null +++ b/test/grammar/lambda/closure_8/stdout.golden @@ -0,0 +1,8 @@ +items: +- 1 +- 2 +- 3 +x: +- 2 +- 3 +- 4 diff --git a/test/grammar/lambda/closure_9/main.k b/test/grammar/lambda/closure_9/main.k new file mode 100644 index 000000000..8a1084c5f --- /dev/null +++ b/test/grammar/lambda/closure_9/main.k @@ -0,0 +1,14 @@ +func = lambda config: {str:} { + x = 1 + lambda { + y = 1 + lambda { + z = 1 + lambda q { + {value = x + y + z + config.key + q} + }(1) + }() + }() +} + +x = func({key = 1}) diff --git a/test/grammar/lambda/closure_9/stdout.golden b/test/grammar/lambda/closure_9/stdout.golden new file mode 100644 index 000000000..963929266 --- /dev/null +++ b/test/grammar/lambda/closure_9/stdout.golden @@ -0,0 +1,2 @@ +x: + value: 5 diff --git a/test/grammar/lambda/in_diff_pkg/kcl.mod b/test/grammar/lambda/in_diff_pkg/kcl.mod index e69de29bb..c51d42cae 100644 --- a/test/grammar/lambda/in_diff_pkg/kcl.mod +++ b/test/grammar/lambda/in_diff_pkg/kcl.mod @@ -0,0 +1,2 @@ +[package] + diff --git a/test/grammar/lambda/in_diff_pkg_annotation/kcl.mod b/test/grammar/lambda/in_diff_pkg_annotation/kcl.mod new file mode 100644 index 000000000..c51d42cae --- /dev/null +++ b/test/grammar/lambda/in_diff_pkg_annotation/kcl.mod @@ -0,0 +1,2 @@ +[package] + diff --git a/test/grammar/lambda/in_diff_pkg_annotation/main.k b/test/grammar/lambda/in_diff_pkg_annotation/main.k new file mode 100644 index 000000000..d05facd61 --- /dev/null +++ b/test/grammar/lambda/in_diff_pkg_annotation/main.k @@ -0,0 +1,11 @@ +import .pkg + +f: ( int , int ) -> int = lambda x, y { + pkg.f(x, y) +} +x0 = [ + (lambda x, y { + x + y + })(x, y) for x in [1, 2, 3] for y in [1, 2, 3] +] +x1 = [f(x, y) for x in [1, 2, 3] for y in [1, 2, 3]] diff --git a/test/grammar/lambda/in_diff_pkg_annotation/pkg/pkg.k b/test/grammar/lambda/in_diff_pkg_annotation/pkg/pkg.k new file mode 100644 index 000000000..8277643c6 --- /dev/null +++ b/test/grammar/lambda/in_diff_pkg_annotation/pkg/pkg.k @@ -0,0 +1,3 @@ +f: ( int , int ) -> int = lambda x, y { + x * y +} \ No newline at end of file diff --git a/test/grammar/lambda/in_diff_pkg_annotation/stdout.golden b/test/grammar/lambda/in_diff_pkg_annotation/stdout.golden new file mode 100644 index 000000000..fe09dbb02 --- /dev/null +++ b/test/grammar/lambda/in_diff_pkg_annotation/stdout.golden @@ -0,0 +1,20 @@ +x0: +- 2 +- 3 +- 4 +- 3 +- 4 +- 5 +- 4 +- 5 +- 6 +x1: +- 1 +- 2 +- 3 +- 2 +- 4 +- 6 +- 3 +- 6 +- 9 diff --git a/test/grammar/lambda/in_for_0_annotation/main.k b/test/grammar/lambda/in_for_0_annotation/main.k new file mode 100644 index 000000000..b270feba1 --- /dev/null +++ b/test/grammar/lambda/in_for_0_annotation/main.k @@ -0,0 +1,9 @@ +f: (int, int) -> int = lambda x, y { + x * y +} +x0 = [ + (lambda x, y { + x + y + })(x, y) for x in [1, 2, 3] for y in [1, 2, 3] +] +x1 = [f(x, y) for x in [1, 2, 3] for y in [1, 2, 3]] diff --git a/test/grammar/lambda/in_for_0_annotation/stdout.golden b/test/grammar/lambda/in_for_0_annotation/stdout.golden new file mode 100644 index 000000000..fe09dbb02 --- /dev/null +++ b/test/grammar/lambda/in_for_0_annotation/stdout.golden @@ -0,0 +1,20 @@ +x0: +- 2 +- 3 +- 4 +- 3 +- 4 +- 5 +- 4 +- 5 +- 6 +x1: +- 1 +- 2 +- 3 +- 2 +- 4 +- 6 +- 3 +- 6 +- 9 diff --git a/test/grammar/lambda/in_for_1_annotation/main.k b/test/grammar/lambda/in_for_1_annotation/main.k new file mode 100644 index 000000000..1fd25e3ed --- /dev/null +++ b/test/grammar/lambda/in_for_1_annotation/main.k @@ -0,0 +1,15 @@ +f: (int , int , int) -> int = lambda x, y, z { + x * y + z +} +schema Data: + val: int = 0 + x0 = [ + (lambda x, y, z { + x + y + })(x, y, val) for x in [1, 2] for y in [1, 2] + ] + x1 = [f(x, y, val) for x in [1, 2] for y in [1, 2]] + +data = Data { + val = 1 +} diff --git a/test/grammar/lambda/in_for_1_annotation/stdout.golden b/test/grammar/lambda/in_for_1_annotation/stdout.golden new file mode 100644 index 000000000..a647b35d4 --- /dev/null +++ b/test/grammar/lambda/in_for_1_annotation/stdout.golden @@ -0,0 +1,12 @@ +data: + val: 1 + x0: + - 2 + - 3 + - 3 + - 4 + x1: + - 2 + - 3 + - 3 + - 5 diff --git a/test/grammar/lambda/in_for_2_annotation/main.k b/test/grammar/lambda/in_for_2_annotation/main.k new file mode 100644 index 000000000..1aebec3ba --- /dev/null +++ b/test/grammar/lambda/in_for_2_annotation/main.k @@ -0,0 +1,12 @@ +data0: int = (lambda x, y { + z = x * 2 + z + y +})(1, 1) + +schema Data: + data = [(lambda x, y { + _z = 2 * x + _z = _z + y + })(x, y) for x in [1, 2] for y in [1, 2]] + +data = Data() diff --git a/test/grammar/lambda/in_for_2_annotation/stdout.golden b/test/grammar/lambda/in_for_2_annotation/stdout.golden new file mode 100644 index 000000000..144005631 --- /dev/null +++ b/test/grammar/lambda/in_for_2_annotation/stdout.golden @@ -0,0 +1,7 @@ +data0: 3 +data: + data: + - 3 + - 4 + - 5 + - 6 diff --git a/test/grammar/lambda/in_pkg_0_annotation/kcl.mod b/test/grammar/lambda/in_pkg_0_annotation/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/test/grammar/lambda/in_pkg_0_annotation/main.k b/test/grammar/lambda/in_pkg_0_annotation/main.k new file mode 100644 index 000000000..1e1157f63 --- /dev/null +++ b/test/grammar/lambda/in_pkg_0_annotation/main.k @@ -0,0 +1,7 @@ +import pkg + +func = pkg.func +a = pkg.a +b = pkg.b +c = func(1, 1) +d = func("1", "1") diff --git a/test/grammar/lambda/in_pkg_0_annotation/pkg/pkg.k b/test/grammar/lambda/in_pkg_0_annotation/pkg/pkg.k new file mode 100644 index 000000000..1743cf95a --- /dev/null +++ b/test/grammar/lambda/in_pkg_0_annotation/pkg/pkg.k @@ -0,0 +1,5 @@ +func:(int|str, int|str) -> int = lambda x: int | str, y: int | str { + int(x) + int(y) +} +a = func(1, 1) +b = func("1", "1") diff --git a/test/grammar/lambda/in_pkg_0_annotation/stdout.golden b/test/grammar/lambda/in_pkg_0_annotation/stdout.golden new file mode 100644 index 000000000..b9996f995 --- /dev/null +++ b/test/grammar/lambda/in_pkg_0_annotation/stdout.golden @@ -0,0 +1,4 @@ +a: 2 +b: 2 +c: 2 +d: 2 diff --git a/test/grammar/lambda/in_pkg_1_annotation/kcl.mod b/test/grammar/lambda/in_pkg_1_annotation/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/test/grammar/lambda/in_pkg_1_annotation/main.k b/test/grammar/lambda/in_pkg_1_annotation/main.k new file mode 100644 index 000000000..1e1157f63 --- /dev/null +++ b/test/grammar/lambda/in_pkg_1_annotation/main.k @@ -0,0 +1,7 @@ +import pkg + +func = pkg.func +a = pkg.a +b = pkg.b +c = func(1, 1) +d = func("1", "1") diff --git a/test/grammar/lambda/in_pkg_1_annotation/pkg/pkg.k b/test/grammar/lambda/in_pkg_1_annotation/pkg/pkg.k new file mode 100644 index 000000000..99305feb2 --- /dev/null +++ b/test/grammar/lambda/in_pkg_1_annotation/pkg/pkg.k @@ -0,0 +1,8 @@ +global = 1 +func: ( int|str, int|str ) -> int = lambda x: int | str, y: int | str { + (lambda x, y { + int(x) + int(y) + global + })(x, y) +} +a = func(1, 1) +b = func("1", "1") diff --git a/test/grammar/lambda/in_pkg_1_annotation/stdout.golden b/test/grammar/lambda/in_pkg_1_annotation/stdout.golden new file mode 100644 index 000000000..b899d7959 --- /dev/null +++ b/test/grammar/lambda/in_pkg_1_annotation/stdout.golden @@ -0,0 +1,4 @@ +a: 3 +b: 3 +c: 3 +d: 3 diff --git a/test/grammar/lambda/in_schema_0_annotation/main.k b/test/grammar/lambda/in_schema_0_annotation/main.k new file mode 100644 index 000000000..1084b9556 --- /dev/null +++ b/test/grammar/lambda/in_schema_0_annotation/main.k @@ -0,0 +1,12 @@ +schema Data: + var: int = 1 + _func: (int|str, int|str) -> int = lambda x: int | str, y: int | str { + (lambda x, y { + int(x) + int(y) + var + })(x, y) + } + + a = _func(1, 1) + b = _func("123", "456") + +data = Data() diff --git a/test/grammar/lambda/in_schema_0_annotation/stdout.golden b/test/grammar/lambda/in_schema_0_annotation/stdout.golden new file mode 100644 index 000000000..32df9eb86 --- /dev/null +++ b/test/grammar/lambda/in_schema_0_annotation/stdout.golden @@ -0,0 +1,4 @@ +data: + var: 1 + a: 3 + b: 580 diff --git a/test/grammar/lambda/in_schema_1_annotation/main.k b/test/grammar/lambda/in_schema_1_annotation/main.k new file mode 100644 index 000000000..e5d0061b9 --- /dev/null +++ b/test/grammar/lambda/in_schema_1_annotation/main.k @@ -0,0 +1,14 @@ +global: int = 10 + +schema Data: + var: int = 1 + _func = lambda x: int | str, y: int | str { + (lambda x, y { + int(x) + int(y) + var + global + })(x, y) + } + + a = _func(1, 1) + b = _func("123", "456") + +data = Data() diff --git a/test/grammar/lambda/in_schema_1_annotation/stdout.golden b/test/grammar/lambda/in_schema_1_annotation/stdout.golden new file mode 100644 index 000000000..50ae2ab28 --- /dev/null +++ b/test/grammar/lambda/in_schema_1_annotation/stdout.golden @@ -0,0 +1,5 @@ +global: 10 +data: + var: 1 + a: 13 + b: 590 diff --git a/test/grammar/lambda/in_schema_2_annotation/main.k b/test/grammar/lambda/in_schema_2_annotation/main.k new file mode 100644 index 000000000..3fa3a3975 --- /dev/null +++ b/test/grammar/lambda/in_schema_2_annotation/main.k @@ -0,0 +1,15 @@ +global: int = 10 + +schema Data: + var: int = 1 + _func: (int|str, int|str) -> int = lambda x: int | str, y: int | str { + (lambda x, y { + _val = int(x) + int(y) + _val = _val + var + global + })(x, y) + } + + a = _func(1, 1) + b = _func("123", "456") + +data = Data() diff --git a/test/grammar/lambda/in_schema_2_annotation/stdout.golden b/test/grammar/lambda/in_schema_2_annotation/stdout.golden new file mode 100644 index 000000000..50ae2ab28 --- /dev/null +++ b/test/grammar/lambda/in_schema_2_annotation/stdout.golden @@ -0,0 +1,5 @@ +global: 10 +data: + var: 1 + a: 13 + b: 590 diff --git a/test/grammar/lambda/in_schema_5/main.k b/test/grammar/lambda/in_schema_5/main.k new file mode 100644 index 000000000..e0dec3f90 --- /dev/null +++ b/test/grammar/lambda/in_schema_5/main.k @@ -0,0 +1,16 @@ +# Issue 1078 +# Errors caused by deep copy of circular references within schema and schema lambda +schema A: + a: int = 1 + f = lambda { + a + } + +schema B[a: A]: + +C = lambda a: A { +} +a = A {} + +C(a) +B(a) diff --git a/test/grammar/lambda/in_schema_5/stdout.golden b/test/grammar/lambda/in_schema_5/stdout.golden new file mode 100644 index 000000000..f410a92b7 --- /dev/null +++ b/test/grammar/lambda/in_schema_5/stdout.golden @@ -0,0 +1,2 @@ +a: + a: 1 diff --git a/test/grammar/lambda/top_level_0_annotation/main.k b/test/grammar/lambda/top_level_0_annotation/main.k new file mode 100644 index 000000000..9b9aa1bc4 --- /dev/null +++ b/test/grammar/lambda/top_level_0_annotation/main.k @@ -0,0 +1,5 @@ +func:(int|str, int|str) -> int = lambda x: int | str, y: int | str { + int(x) + int(y) +} +a = func(1, 1) +b = func("123", "456") diff --git a/test/grammar/lambda/top_level_0_annotation/stdout.golden b/test/grammar/lambda/top_level_0_annotation/stdout.golden new file mode 100644 index 000000000..73f656a99 --- /dev/null +++ b/test/grammar/lambda/top_level_0_annotation/stdout.golden @@ -0,0 +1,2 @@ +a: 2 +b: 579 diff --git a/test/grammar/lambda/top_level_1_annotation/main.k b/test/grammar/lambda/top_level_1_annotation/main.k new file mode 100644 index 000000000..b46bd254f --- /dev/null +++ b/test/grammar/lambda/top_level_1_annotation/main.k @@ -0,0 +1,7 @@ +func: (int|str, int|str) -> int = lambda x: int | str, y: int | str { + (lambda x, y { + int(x) + int(y) + })(x, y) +} +a = func(1, 1) +b = func("123", "456") diff --git a/test/grammar/lambda/top_level_1_annotation/stdout.golden b/test/grammar/lambda/top_level_1_annotation/stdout.golden new file mode 100644 index 000000000..73f656a99 --- /dev/null +++ b/test/grammar/lambda/top_level_1_annotation/stdout.golden @@ -0,0 +1,2 @@ +a: 2 +b: 579 diff --git a/test/grammar/lambda/top_level_2_annotation/main.k b/test/grammar/lambda/top_level_2_annotation/main.k new file mode 100644 index 000000000..c6e6f5718 --- /dev/null +++ b/test/grammar/lambda/top_level_2_annotation/main.k @@ -0,0 +1,8 @@ +func: (int|str, int|str) -> int = lambda x: int | str, y: int | str { + (lambda x, y { + int(x) + int(y) + })(x, y) +} +afunc = func +a = afunc(1, 1) +b = afunc("123", "456") diff --git a/test/grammar/lambda/top_level_2_annotation/stdout.golden b/test/grammar/lambda/top_level_2_annotation/stdout.golden new file mode 100644 index 000000000..73f656a99 --- /dev/null +++ b/test/grammar/lambda/top_level_2_annotation/stdout.golden @@ -0,0 +1,2 @@ +a: 2 +b: 579 diff --git a/test/grammar/lambda/top_level_4_annotation/main.k b/test/grammar/lambda/top_level_4_annotation/main.k new file mode 100644 index 000000000..39f35d46a --- /dev/null +++ b/test/grammar/lambda/top_level_4_annotation/main.k @@ -0,0 +1,9 @@ +f:({str:}) -> {str:} = lambda x: {str:} -> {str:} { + 1 + _x = 1 + { + x = _x + } +} + +x = f({data = [1]}) diff --git a/test/grammar/lambda/top_level_4_annotation/stdout.golden b/test/grammar/lambda/top_level_4_annotation/stdout.golden new file mode 100644 index 000000000..6f947823f --- /dev/null +++ b/test/grammar/lambda/top_level_4_annotation/stdout.golden @@ -0,0 +1,2 @@ +x: + x: 1 diff --git a/test/grammar/lambda/top_level_5_annotation/main.k b/test/grammar/lambda/top_level_5_annotation/main.k new file mode 100644 index 000000000..d3725aa2f --- /dev/null +++ b/test/grammar/lambda/top_level_5_annotation/main.k @@ -0,0 +1,4 @@ +f: () -> int = lambda -> int { + 1 +} +x = f() diff --git a/test/grammar/lambda/top_level_5_annotation/stdout.golden b/test/grammar/lambda/top_level_5_annotation/stdout.golden new file mode 100644 index 000000000..d508cf756 --- /dev/null +++ b/test/grammar/lambda/top_level_5_annotation/stdout.golden @@ -0,0 +1 @@ +x: 1 diff --git a/test/grammar/misc/empty_file/stdout.golden b/test/grammar/misc/empty_file/stdout.golden index e69de29bb..9e26dfeeb 100644 --- a/test/grammar/misc/empty_file/stdout.golden +++ b/test/grammar/misc/empty_file/stdout.golden @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/grammar/misc/empty_plan/stdout.golden b/test/grammar/misc/empty_plan/stdout.golden index e69de29bb..0967ef424 100644 --- a/test/grammar/misc/empty_plan/stdout.golden +++ b/test/grammar/misc/empty_plan/stdout.golden @@ -0,0 +1 @@ +{} diff --git a/test/grammar/scalar/number/number_1/main.k b/test/grammar/scalar/number/number_1/main.k deleted file mode 100644 index 61ab367f3..000000000 --- a/test/grammar/scalar/number/number_1/main.k +++ /dev/null @@ -1,2 +0,0 @@ -_a = 1 -_a \ No newline at end of file diff --git a/test/grammar/scalar/number/number_1/stdout.golden b/test/grammar/scalar/number/number_1/stdout.golden deleted file mode 100644 index 56a6051ca..000000000 --- a/test/grammar/scalar/number/number_1/stdout.golden +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/test/grammar/schema/assign_stmt/assign_stmt_0/main.k b/test/grammar/schema/assign_stmt/assign_stmt_0/main.k new file mode 100644 index 000000000..1066a82a3 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_0/main.k @@ -0,0 +1,14 @@ +schema Metadata: + environment?: str = "qa" + region?: str + name?: str + +schema MySchema1: + metadata?: Metadata = {} + + metadata.environment = "dev" + metadata.region = "us-east-1" + +output = MySchema1 { + metadata.name = "config" +} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_0/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_0/stdout.golden new file mode 100644 index 000000000..e2a1effb3 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_0/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: dev + region: us-east-1 + name: config diff --git a/test/grammar/schema/assign_stmt/assign_stmt_1/main.k b/test/grammar/schema/assign_stmt/assign_stmt_1/main.k new file mode 100644 index 000000000..9992d221e --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_1/main.k @@ -0,0 +1,14 @@ +schema Metadata: + environment?: str = "qa" + region?: str + name?: str + +schema MySchema1: + metadata?: Metadata = {} + + metadata.environment = "dev" + + +output = MySchema1 { + metadata.name = "config" +} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_1/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_1/stdout.golden new file mode 100644 index 000000000..23403df35 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_1/stdout.golden @@ -0,0 +1,4 @@ +output: + metadata: + environment: dev + name: config diff --git a/test/grammar/schema/assign_stmt/assign_stmt_2/main.k b/test/grammar/schema/assign_stmt/assign_stmt_2/main.k new file mode 100644 index 000000000..8be0f05ba --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_2/main.k @@ -0,0 +1,13 @@ +schema Metadata: + environment?: str = "qa" + region?: str + name?: str + +schema MySchema1: + metadata?: Metadata = { + name = "config" + } + metadata.environment = "dev" + metadata.region = "us-east-1" + +output = MySchema1 {} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_2/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_2/stdout.golden new file mode 100644 index 000000000..e2a1effb3 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_2/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: dev + region: us-east-1 + name: config diff --git a/test/grammar/schema/assign_stmt/assign_stmt_3/main.k b/test/grammar/schema/assign_stmt/assign_stmt_3/main.k new file mode 100644 index 000000000..f1568a0f2 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_3/main.k @@ -0,0 +1,16 @@ +schema Metadata: + environment: str + region: str + name: str + +schema MySchema1: + metadata: Metadata + +schema MySchema2(MySchema1): + metadata.environment = "dev" + +schema MySchema3(MySchema2): + metadata.region = "us-east-1" + +output = MySchema3 {metadata.name = "hello"} + diff --git a/test/grammar/schema/assign_stmt/assign_stmt_3/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_3/stdout.golden new file mode 100644 index 000000000..5f647f0ee --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_3/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: dev + region: us-east-1 + name: hello diff --git a/test/grammar/schema/assign_stmt/assign_stmt_4/main.k b/test/grammar/schema/assign_stmt/assign_stmt_4/main.k new file mode 100644 index 000000000..ab61e786e --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_4/main.k @@ -0,0 +1,18 @@ +schema Metadata: + environment: str + region: str + name: str + +schema MySchema1: + metadata: Metadata + +schema MySchema2(MySchema1): + metadata.environment = "dev" + +schema MySchema3(MySchema2): + metadata.region = "us-east-1" + +output = MySchema3 { + metadata.name = "hello" + metadata.environment = "qa" +} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_4/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_4/stdout.golden new file mode 100644 index 000000000..c55b51309 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_4/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: qa + region: us-east-1 + name: hello diff --git a/test/grammar/schema/assign_stmt/assign_stmt_5/main.k b/test/grammar/schema/assign_stmt/assign_stmt_5/main.k new file mode 100644 index 000000000..a08d60fb8 --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_5/main.k @@ -0,0 +1,9 @@ +schema MySchema: + metadata: {str:} = {} + + metadata.environment = "dev" + + +output = MySchema { + metadata.name = "config" +} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_5/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_5/stdout.golden new file mode 100644 index 000000000..37a73361b --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_5/stdout.golden @@ -0,0 +1,4 @@ +output: + metadata: + name: config + environment: dev diff --git a/test/grammar/schema/assign_stmt/assign_stmt_6/main.k b/test/grammar/schema/assign_stmt/assign_stmt_6/main.k new file mode 100644 index 000000000..5279413be --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_6/main.k @@ -0,0 +1,10 @@ +schema MySchema: + metadata: {str:} = {} + + metadata.environment = "dev" + + +output = MySchema { + metadata.environment = "qa" + metadata.name = "config" +} diff --git a/test/grammar/schema/assign_stmt/assign_stmt_6/stdout.golden b/test/grammar/schema/assign_stmt/assign_stmt_6/stdout.golden new file mode 100644 index 000000000..0ce8e1b8c --- /dev/null +++ b/test/grammar/schema/assign_stmt/assign_stmt_6/stdout.golden @@ -0,0 +1,4 @@ +output: + metadata: + environment: qa + name: config diff --git a/test/grammar/schema/assign_stmt/fail_0/main.k b/test/grammar/schema/assign_stmt/fail_0/main.k new file mode 100644 index 000000000..240e2d106 --- /dev/null +++ b/test/grammar/schema/assign_stmt/fail_0/main.k @@ -0,0 +1,4 @@ +schema Schema: + a.b = 1 + +s = Schema {} diff --git a/test/grammar/schema/assign_stmt/fail_0/stderr.golden.py b/test/grammar/schema/assign_stmt/fail_0/stderr.golden.py new file mode 100644 index 000000000..8af3810e4 --- /dev/null +++ b/test/grammar/schema/assign_stmt/fail_0/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=2, + ), + ], + arg_msg="failed to update the dict. An iterable of key-value pairs was expected, but got UndefinedType. Check if the syntax for updating the dictionary with the attribute 'b' is correct") + , file=sys.stdout +) diff --git a/test/grammar/schema/config_op/override/override_3/main.k b/test/grammar/schema/config_op/override/override_3/main.k new file mode 100644 index 000000000..a37f015f8 --- /dev/null +++ b/test/grammar/schema/config_op/override/override_3/main.k @@ -0,0 +1,10 @@ +schema MySubSchema: + a: int + b: str + c: {str:str} + d: str = c[b] + +schema MyTestSchema: + field1?: [MySubSchema] = [{a = 1, b = "key", c = {key = "value"}}] + +instance = MyTestSchema {field1: None} diff --git a/test/grammar/schema/config_op/override/override_3/stdout.golden b/test/grammar/schema/config_op/override/override_3/stdout.golden new file mode 100644 index 000000000..ad5c75267 --- /dev/null +++ b/test/grammar/schema/config_op/override/override_3/stdout.golden @@ -0,0 +1,7 @@ +instance: + field1: + - a: 1 + b: key + c: + key: value + d: value diff --git a/test/grammar/schema/config_op/override/override_4/main.k b/test/grammar/schema/config_op/override/override_4/main.k new file mode 100644 index 000000000..6ebce8331 --- /dev/null +++ b/test/grammar/schema/config_op/override/override_4/main.k @@ -0,0 +1,10 @@ +schema MySubSchema: + a: int + b: str + c: {str:str} + d: str = c[b] + +schema MyTestSchema: + field1?: [MySubSchema] = [{a: 1}] + +instance = MyTestSchema {field1 = None} diff --git a/test/grammar/schema/config_op/override/override_4/stdout.golden b/test/grammar/schema/config_op/override/override_4/stdout.golden new file mode 100644 index 000000000..044cef528 --- /dev/null +++ b/test/grammar/schema/config_op/override/override_4/stdout.golden @@ -0,0 +1,2 @@ +instance: + field1: null diff --git a/test/grammar/schema/index_signature/fail_10/main.k b/test/grammar/schema/index_signature/fail_10/main.k new file mode 100644 index 000000000..9913722f7 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_10/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws: {} +} diff --git a/test/grammar/schema/index_signature/fail_10/stderr.golden.py b/test/grammar/schema/index_signature/fail_10/stderr.golden.py new file mode 100644 index 000000000..0d5a27eb3 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_10/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=9, + ), + ], + arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/index_signature/fail_11/main.k b/test/grammar/schema/index_signature/fail_11/main.k new file mode 100644 index 000000000..d3dd5088b --- /dev/null +++ b/test/grammar/schema/index_signature/fail_11/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws = {} +} diff --git a/test/grammar/schema/index_signature/fail_11/stderr.golden.py b/test/grammar/schema/index_signature/fail_11/stderr.golden.py new file mode 100644 index 000000000..c861cfcb4 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_11/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=9, + ), + ], + arg_msg="attribute 'name' of WithComponent is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/index_signature/fail_7/main.k b/test/grammar/schema/index_signature/fail_7/main.k new file mode 100644 index 000000000..0080b8347 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_7/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type: str + +schema WithComponents: + [name: str]: WithComponent = {name: name} + +components: WithComponents { + ws: {} +} diff --git a/test/grammar/schema/index_signature/fail_7/stderr.golden.py b/test/grammar/schema/index_signature/fail_7/stderr.golden.py new file mode 100644 index 000000000..0d5a27eb3 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_7/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=9, + ), + ], + arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/index_signature/fail_8/main.k b/test/grammar/schema/index_signature/fail_8/main.k new file mode 100644 index 000000000..2d87773f9 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_8/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type: str + +schema WithComponents: + [name: str]: WithComponent = {name: name} + +components: WithComponents { + ws: WithComponent {} +} diff --git a/test/grammar/schema/index_signature/fail_8/stderr.golden.py b/test/grammar/schema/index_signature/fail_8/stderr.golden.py new file mode 100644 index 000000000..0d5a27eb3 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_8/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=9, + ), + ], + arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/index_signature/fail_9/main.k b/test/grammar/schema/index_signature/fail_9/main.k new file mode 100644 index 000000000..6ccc50367 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_9/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws: WithComponent {} +} diff --git a/test/grammar/schema/index_signature/fail_9/stderr.golden.py b/test/grammar/schema/index_signature/fail_9/stderr.golden.py new file mode 100644 index 000000000..0d5a27eb3 --- /dev/null +++ b/test/grammar/schema/index_signature/fail_9/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=9, + ), + ], + arg_msg="attribute 'type' of WithComponent is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/index_signature/key_alias_1/main.k b/test/grammar/schema/index_signature/key_alias_1/main.k index cac408192..af69f88c2 100644 --- a/test/grammar/schema/index_signature/key_alias_1/main.k +++ b/test/grammar/schema/index_signature/key_alias_1/main.k @@ -1,6 +1,6 @@ schema TeamSpec: fullName: str - name = id + name: str shortName: str = name schema TeamMap: diff --git a/test/grammar/schema/index_signature/normal_10/main.k b/test/grammar/schema/index_signature/normal_10/main.k new file mode 100644 index 000000000..8e2ed2500 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_10/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name?: str + $type?: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws = {} +} diff --git a/test/grammar/schema/index_signature/normal_10/stdout.golden b/test/grammar/schema/index_signature/normal_10/stdout.golden new file mode 100644 index 000000000..16cff31f0 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_10/stdout.golden @@ -0,0 +1,2 @@ +components: + ws: {} diff --git a/test/grammar/schema/index_signature/normal_6/main.k b/test/grammar/schema/index_signature/normal_6/main.k new file mode 100644 index 000000000..7e128c187 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_6/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type?: str + +schema WithComponents: + [name: str]: WithComponent = {name: name} + +components: WithComponents { + ws: {} +} diff --git a/test/grammar/schema/index_signature/normal_6/stdout.golden b/test/grammar/schema/index_signature/normal_6/stdout.golden new file mode 100644 index 000000000..7ef2dbb12 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_6/stdout.golden @@ -0,0 +1,3 @@ +components: + ws: + name: ws diff --git a/test/grammar/schema/index_signature/normal_7/main.k b/test/grammar/schema/index_signature/normal_7/main.k new file mode 100644 index 000000000..c40963bcb --- /dev/null +++ b/test/grammar/schema/index_signature/normal_7/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type?: str + +schema WithComponents: + [name: str]: WithComponent = {name: name} + +components: WithComponents { + ws: WithComponent {} +} diff --git a/test/grammar/schema/index_signature/normal_7/stdout.golden b/test/grammar/schema/index_signature/normal_7/stdout.golden new file mode 100644 index 000000000..7ef2dbb12 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_7/stdout.golden @@ -0,0 +1,3 @@ +components: + ws: + name: ws diff --git a/test/grammar/schema/index_signature/normal_8/main.k b/test/grammar/schema/index_signature/normal_8/main.k new file mode 100644 index 000000000..5d6577cab --- /dev/null +++ b/test/grammar/schema/index_signature/normal_8/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type?: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws: WithComponent {} +} diff --git a/test/grammar/schema/index_signature/normal_8/stdout.golden b/test/grammar/schema/index_signature/normal_8/stdout.golden new file mode 100644 index 000000000..7ef2dbb12 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_8/stdout.golden @@ -0,0 +1,3 @@ +components: + ws: + name: ws diff --git a/test/grammar/schema/index_signature/normal_9/main.k b/test/grammar/schema/index_signature/normal_9/main.k new file mode 100644 index 000000000..81c9494f3 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_9/main.k @@ -0,0 +1,10 @@ +schema WithComponent: + name: str + $type?: str + +schema WithComponents: + [name: str]: WithComponent = WithComponent {name: name} + +components: WithComponents { + ws: {} +} diff --git a/test/grammar/schema/index_signature/normal_9/stdout.golden b/test/grammar/schema/index_signature/normal_9/stdout.golden new file mode 100644 index 000000000..7ef2dbb12 --- /dev/null +++ b/test/grammar/schema/index_signature/normal_9/stdout.golden @@ -0,0 +1,3 @@ +components: + ws: + name: ws diff --git a/test/grammar/schema/init/init_nested_schema_1/stdout.golden b/test/grammar/schema/init/init_nested_schema_1/stdout.golden index 788dbbed5..71e6cb93a 100644 --- a/test/grammar/schema/init/init_nested_schema_1/stdout.golden +++ b/test/grammar/schema/init/init_nested_schema_1/stdout.golden @@ -1,5 +1,5 @@ alice: name: name: - name: rename - gender: female \ No newline at end of file + name: alice + gender: female diff --git a/test/grammar/schema/instances/complex/complex_2/backend.k b/test/grammar/schema/instances/complex/complex_2/backend.k index 24e902f04..5fe279a43 100644 --- a/test/grammar/schema/instances/complex/complex_2/backend.k +++ b/test/grammar/schema/instances/complex/complex_2/backend.k @@ -1,5 +1,4 @@ schema Backend: - __settings__: {str:str} = {"output_type": "STANDALONE"} """ existence of this attribute indicates that the model will be treated standalone by KCLVM. """ diff --git a/test/grammar/schema/instances/complex/complex_2/stdout.golden b/test/grammar/schema/instances/complex/complex_2/stdout.golden index e8f43377d..09d75a312 100644 --- a/test/grammar/schema/instances/complex/complex_2/stdout.golden +++ b/test/grammar/schema/instances/complex/complex_2/stdout.golden @@ -1,34 +1,34 @@ -apiVersion: v1 -kind: Deployment -metadata: - name: model1 - labels: - key1: value1 - key2: value2 - annotations: - key: value -spec: - minReadySeconds: 0 - paused: false - progressDeadlineSeconds: 600 - replicas: 2 - revisionHistoryLimit: 10 - selector: - matchLabels: +backends: +- apiVersion: v1 + kind: Deployment + metadata: + name: model1 + labels: key1: value1 key2: value2 ---- -apiVersion: v1 -kind: Deployment -metadata: - name: model2 - labels: null - annotations: null -spec: - minReadySeconds: 0 - paused: false - progressDeadlineSeconds: 600 - replicas: 3 - revisionHistoryLimit: 10 - selector: - matchLabels: null + annotations: + key: value + spec: + minReadySeconds: 0 + paused: false + progressDeadlineSeconds: 600 + replicas: 2 + revisionHistoryLimit: 10 + selector: + matchLabels: + key1: value1 + key2: value2 +- apiVersion: v1 + kind: Deployment + metadata: + name: model2 + labels: null + annotations: null + spec: + minReadySeconds: 0 + paused: false + progressDeadlineSeconds: 600 + replicas: 3 + revisionHistoryLimit: 10 + selector: + matchLabels: null diff --git a/test/grammar/schema/irrelevant_order/complex_2/main.k b/test/grammar/schema/irrelevant_order/complex_2/main.k index e317c61ff..094169b14 100644 --- a/test/grammar/schema/irrelevant_order/complex_2/main.k +++ b/test/grammar/schema/irrelevant_order/complex_2/main.k @@ -1,5 +1,4 @@ schema KubeNamespace: - __settings__: {str:str} = {"output_type": "STANDALONE"} apiVersion: str = "v1" kind: str = "Namespace" metadata: {str:} @@ -34,10 +33,6 @@ schema Namespace(Metadata): name: str = "prod-frontend" finalizers: [str] - __settings__: {str:} = { - "output_type": "IGNORE" - } - node = Namespace { finalizers: ["test"] } diff --git a/test/grammar/schema/irrelevant_order/complex_2/stdout.golden b/test/grammar/schema/irrelevant_order/complex_2/stdout.golden index 588b0e586..1964ad8c6 100644 --- a/test/grammar/schema/irrelevant_order/complex_2/stdout.golden +++ b/test/grammar/schema/irrelevant_order/complex_2/stdout.golden @@ -1,7 +1,14 @@ -apiVersion: v1 -kind: Namespace -metadata: +node: name: prod-frontend -spec: + metadata: + name: prod-frontend finalizers: - test + kubeNamespace: + apiVersion: v1 + kind: Namespace + metadata: + name: prod-frontend + spec: + finalizers: + - test diff --git a/test/grammar/schema/irrelevant_order/inherit_1/main.k b/test/grammar/schema/irrelevant_order/inherit_1/main.k index 766908ca8..c8364678f 100644 --- a/test/grammar/schema/irrelevant_order/inherit_1/main.k +++ b/test/grammar/schema/irrelevant_order/inherit_1/main.k @@ -1,4 +1,6 @@ schema BasePerson: + firstName: str + lastName: str fullName = firstName + ' ' + lastName schema Person(BasePerson): diff --git a/test/grammar/schema/irrelevant_order/inherit_1/stdout.golden b/test/grammar/schema/irrelevant_order/inherit_1/stdout.golden index c7bb08aef..7caad7724 100644 --- a/test/grammar/schema/irrelevant_order/inherit_1/stdout.golden +++ b/test/grammar/schema/irrelevant_order/inherit_1/stdout.golden @@ -1,4 +1,4 @@ JohnDoe: - fullName: John Doe firstName: John lastName: Doe + fullName: John Doe diff --git a/test/grammar/schema/irrelevant_order/inherit_6/main.k b/test/grammar/schema/irrelevant_order/inherit_6/main.k index b48c7089d..0302a0b16 100644 --- a/test/grammar/schema/irrelevant_order/inherit_6/main.k +++ b/test/grammar/schema/irrelevant_order/inherit_6/main.k @@ -3,11 +3,11 @@ schema Parent: key: str = "key" + " " + name name2: str = "Alice" key2: str = "key2" + " " + name2 - _tempA = "tempA" + _tempA: str = "tempA" schema Son1(Parent): name: str = "Son1" - _tempB = "tempB" + _tempB: str = "tempB" schema Son2(Son1): name: str = "Son2" + _tempA diff --git a/test/grammar/schema/mixin/dict_2_schema_0/main.k b/test/grammar/schema/mixin/dict_2_schema_0/main.k index 3ea5962e2..510feaf0c 100644 --- a/test/grammar/schema/mixin/dict_2_schema_0/main.k +++ b/test/grammar/schema/mixin/dict_2_schema_0/main.k @@ -10,9 +10,6 @@ schema Rule: kind: str = "Rule" access: [str] entity: Person - __settings__: {str:} = { - "output_type": "STANDALONE" - } schema RuleMixin: if rule: diff --git a/test/grammar/schema/mixin/dict_2_schema_0/stdout.golden b/test/grammar/schema/mixin/dict_2_schema_0/stdout.golden index 8a6f91af1..1cbedfe0a 100644 --- a/test/grammar/schema/mixin/dict_2_schema_0/stdout.golden +++ b/test/grammar/schema/mixin/dict_2_schema_0/stdout.golden @@ -7,13 +7,13 @@ alice: access: - read - write ---- -kind: Rule -access: -- read -- write -entity: - name: alice - relatives: - - relation: father - name: Reese \ No newline at end of file + ruleModel: + kind: Rule + access: + - read + - write + entity: + name: alice + relatives: + - relation: father + name: Reese diff --git a/test/grammar/schema/mixin/dict_2_schema_1/main.k b/test/grammar/schema/mixin/dict_2_schema_1/main.k index 8321e6cf4..757c7e22b 100644 --- a/test/grammar/schema/mixin/dict_2_schema_1/main.k +++ b/test/grammar/schema/mixin/dict_2_schema_1/main.k @@ -10,9 +10,6 @@ schema Rule: kind: str = "Rule" access: [str] entity: Person - __settings__: {str:} = { - "output_type": "STANDALONE" - } schema RuleMixin: if rule: diff --git a/test/grammar/schema/mixin/dict_2_schema_1/stdout.golden b/test/grammar/schema/mixin/dict_2_schema_1/stdout.golden index e92a589ac..3df72e7e6 100644 --- a/test/grammar/schema/mixin/dict_2_schema_1/stdout.golden +++ b/test/grammar/schema/mixin/dict_2_schema_1/stdout.golden @@ -7,13 +7,13 @@ alice: access: - read - write ---- -kind: Rule -access: -- read -- write -entity: - name: alice - relatives: - - relation: father - name: Reese + ruleModels: + - kind: Rule + access: + - read + - write + entity: + name: alice + relatives: + - relation: father + name: Reese diff --git a/test/grammar/schema/mixin/dict_2_schema_2/main.k b/test/grammar/schema/mixin/dict_2_schema_2/main.k index 2029b2adb..f27bc719e 100644 --- a/test/grammar/schema/mixin/dict_2_schema_2/main.k +++ b/test/grammar/schema/mixin/dict_2_schema_2/main.k @@ -10,9 +10,6 @@ schema Rule: kind: str = "Rule" access: [str] entity: Person - __settings__: {str:} = { - output_type = "STANDALONE" - } schema RuleMixin: if rule: diff --git a/test/grammar/schema/mixin/dict_2_schema_2/stdout.golden b/test/grammar/schema/mixin/dict_2_schema_2/stdout.golden index e92a589ac..3df72e7e6 100644 --- a/test/grammar/schema/mixin/dict_2_schema_2/stdout.golden +++ b/test/grammar/schema/mixin/dict_2_schema_2/stdout.golden @@ -7,13 +7,13 @@ alice: access: - read - write ---- -kind: Rule -access: -- read -- write -entity: - name: alice - relatives: - - relation: father - name: Reese + ruleModels: + - kind: Rule + access: + - read + - write + entity: + name: alice + relatives: + - relation: father + name: Reese diff --git a/test/grammar/schema/optional_attr/fail_13/main.k b/test/grammar/schema/optional_attr/fail_13/main.k new file mode 100644 index 000000000..b7e2564af --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_13/main.k @@ -0,0 +1,11 @@ +schema S: + a: int + b: str + +schema L: + ss?: [S] + sss?: {str:S} + +L { + ss = [S {b = "b"}] +} diff --git a/test/grammar/schema/optional_attr/fail_13/stderr.golden.py b/test/grammar/schema/optional_attr/fail_13/stderr.golden.py new file mode 100644 index 000000000..4f08cb3e5 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_13/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'a' of S is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_14/main.k b/test/grammar/schema/optional_attr/fail_14/main.k new file mode 100644 index 000000000..96fd0f211 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_14/main.k @@ -0,0 +1,11 @@ +schema S: + a: int + b: str + +schema L: + ss?: [S] + sss?: {str:S} + +L { + sss.aa: S {b = "2"} +} diff --git a/test/grammar/schema/optional_attr/fail_14/stderr.golden.py b/test/grammar/schema/optional_attr/fail_14/stderr.golden.py new file mode 100644 index 000000000..4f08cb3e5 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_14/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'a' of S is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_15/main.k b/test/grammar/schema/optional_attr/fail_15/main.k new file mode 100644 index 000000000..7d3adbc34 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_15/main.k @@ -0,0 +1,9 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: [Data] = [data] diff --git a/test/grammar/schema/optional_attr/fail_15/stderr.golden.py b/test/grammar/schema/optional_attr/fail_15/stderr.golden.py new file mode 100644 index 000000000..e5a110212 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_15/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=9, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_16/main.k b/test/grammar/schema/optional_attr/fail_16/main.k new file mode 100644 index 000000000..eb8bc3dd6 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_16/main.k @@ -0,0 +1,9 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: [[Data]] = [[data]] diff --git a/test/grammar/schema/optional_attr/fail_16/stderr.golden.py b/test/grammar/schema/optional_attr/fail_16/stderr.golden.py new file mode 100644 index 000000000..e5a110212 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_16/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=9, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_17/main.k b/test/grammar/schema/optional_attr/fail_17/main.k new file mode 100644 index 000000000..0ed33fb6c --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_17/main.k @@ -0,0 +1,11 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: {str:Data} = { + data = data +} diff --git a/test/grammar/schema/optional_attr/fail_17/stderr.golden.py b/test/grammar/schema/optional_attr/fail_17/stderr.golden.py new file mode 100644 index 000000000..65fa60d4b --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_17/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_18/main.k b/test/grammar/schema/optional_attr/fail_18/main.k new file mode 100644 index 000000000..e8700b21d --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_18/main.k @@ -0,0 +1,11 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: {str:{str:Data}} = { + data.data = data +} diff --git a/test/grammar/schema/optional_attr/fail_18/stderr.golden.py b/test/grammar/schema/optional_attr/fail_18/stderr.golden.py new file mode 100644 index 000000000..65fa60d4b --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_18/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_19/main.k b/test/grammar/schema/optional_attr/fail_19/main.k new file mode 100644 index 000000000..dc378c832 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_19/main.k @@ -0,0 +1,11 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: {str:[Data]} = { + data = [data] +} diff --git a/test/grammar/schema/optional_attr/fail_19/stderr.golden.py b/test/grammar/schema/optional_attr/fail_19/stderr.golden.py new file mode 100644 index 000000000..65fa60d4b --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_19/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/fail_20/main.k b/test/grammar/schema/optional_attr/fail_20/main.k new file mode 100644 index 000000000..de01e7434 --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_20/main.k @@ -0,0 +1,11 @@ +schema Data: + name: str + type: str + +data = { + name = "data" +} + +datas: [{str:[Data]}] = [{ + data = [data] +}] diff --git a/test/grammar/schema/optional_attr/fail_20/stderr.golden.py b/test/grammar/schema/optional_attr/fail_20/stderr.golden.py new file mode 100644 index 000000000..65fa60d4b --- /dev/null +++ b/test/grammar/schema/optional_attr/fail_20/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import os + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.EvaluationError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=os.path.join(cwd, "main.k"), + line_no=10, + ), + ], + arg_msg="attribute 'type' of Data is required and can't be None or Undefined") + , file=sys.stdout +) diff --git a/test/grammar/schema/optional_attr/inherit_2/main.k b/test/grammar/schema/optional_attr/inherit_2/main.k new file mode 100644 index 000000000..bdfd4c299 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_2/main.k @@ -0,0 +1,16 @@ +schema Metadata: + environment: str + region: str + name: str + +schema MySchema1: + metadata: Metadata + +schema MySchema2(MySchema1): + metadata: Metadata {environment = "dev"} + +schema MySchema3(MySchema2): + metadata: Metadata {region = "us-east-1"} + +output = MySchema3 {metadata.name = "hello"} + diff --git a/test/grammar/schema/optional_attr/inherit_2/stdout.golden b/test/grammar/schema/optional_attr/inherit_2/stdout.golden new file mode 100644 index 000000000..5f647f0ee --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_2/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: dev + region: us-east-1 + name: hello diff --git a/test/grammar/schema/optional_attr/inherit_3/main.k b/test/grammar/schema/optional_attr/inherit_3/main.k new file mode 100644 index 000000000..8edc480a2 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_3/main.k @@ -0,0 +1,18 @@ +schema Metadata: + environment: str + region: str + name: str + +schema MySchema1: + metadata: Metadata + +schema MySchema2(MySchema1): + metadata: Metadata {environment = "dev"} + +schema MySchema3(MySchema2): + metadata: Metadata {region = "us-east-1"} + +output = MySchema3 { + metadata.name = "hello" + metadata.environment = "qa" +} diff --git a/test/grammar/schema/optional_attr/inherit_3/stdout.golden b/test/grammar/schema/optional_attr/inherit_3/stdout.golden new file mode 100644 index 000000000..c55b51309 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_3/stdout.golden @@ -0,0 +1,5 @@ +output: + metadata: + environment: qa + region: us-east-1 + name: hello diff --git a/test/grammar/schema/rule/rule_with_index_signature/main.k b/test/grammar/schema/rule/rule_with_index_signature/main.k new file mode 100644 index 000000000..3b7031802 --- /dev/null +++ b/test/grammar/schema/rule/rule_with_index_signature/main.k @@ -0,0 +1,17 @@ +protocol XProtocol: + [...str]: str + alice: str + +rule XRule for XProtocol: + alice == "Alice", "expected Alice, got ${alice}" + bob == "Bob", "expected Bob, got ${bob}" + +p = XProtocol { + alice = "Alice" + bob = "Bob" +} + +x = XRule { + alice = "Alice" + bob = "Bob" +} diff --git a/test/grammar/schema/rule/rule_with_index_signature/stdout.golden b/test/grammar/schema/rule/rule_with_index_signature/stdout.golden new file mode 100644 index 000000000..7ea472fb1 --- /dev/null +++ b/test/grammar/schema/rule/rule_with_index_signature/stdout.golden @@ -0,0 +1,6 @@ +p: + alice: Alice + bob: Bob +x: + alice: Alice + bob: Bob diff --git a/test/grammar/schema/str_attr/str_attr_0/main.k b/test/grammar/schema/str_attr/str_attr_0/main.k new file mode 100644 index 000000000..a14982d6b --- /dev/null +++ b/test/grammar/schema/str_attr/str_attr_0/main.k @@ -0,0 +1,23 @@ +schema Data: + "spec": Spec + +schema Spec: + "config": Config + +schema Config: + "template": Template + +schema Template: + [...str]: int + "name": str + +data = Data { + spec: { + config: { + template: { + name: "template" + id: 1 + } + } + } +} diff --git a/test/grammar/schema/str_attr/str_attr_0/stdout.golden b/test/grammar/schema/str_attr/str_attr_0/stdout.golden new file mode 100644 index 000000000..373d3582f --- /dev/null +++ b/test/grammar/schema/str_attr/str_attr_0/stdout.golden @@ -0,0 +1,6 @@ +data: + spec: + config: + template: + name: template + id: 1 diff --git a/test/grammar/schema/str_attr/str_attr_1/main.k b/test/grammar/schema/str_attr/str_attr_1/main.k new file mode 100644 index 000000000..14aa70d8f --- /dev/null +++ b/test/grammar/schema/str_attr/str_attr_1/main.k @@ -0,0 +1,22 @@ +schema Data: + "spec": Spec + +schema Spec: + "config": Config + +schema Config: + "template": Template + +schema Template: + "name": str + +data = Data { + spec: { + config: { + template: { + name: "template" + } + } + } +} +name = data["spec"]["config"]["template"].name diff --git a/test/grammar/schema/str_attr/str_attr_1/stdout.golden b/test/grammar/schema/str_attr/str_attr_1/stdout.golden new file mode 100644 index 000000000..d4216f94e --- /dev/null +++ b/test/grammar/schema/str_attr/str_attr_1/stdout.golden @@ -0,0 +1,6 @@ +data: + spec: + config: + template: + name: template +name: template diff --git a/test/grammar/schema/type/combination_4/main.k b/test/grammar/schema/type/combination_4/main.k index a0ac2de69..506d86054 100644 --- a/test/grammar/schema/type/combination_4/main.k +++ b/test/grammar/schema/type/combination_4/main.k @@ -20,9 +20,6 @@ schema Rule: kind: str = "Rule" access: [str] entity: Person - __settings__: {str:} = { - "output_type": "STANDALONE" - } schema Model: mixin [RuleMixin] diff --git a/test/grammar/schema/type/combination_4/stdout.golden b/test/grammar/schema/type/combination_4/stdout.golden index 8a6f91af1..1cbedfe0a 100644 --- a/test/grammar/schema/type/combination_4/stdout.golden +++ b/test/grammar/schema/type/combination_4/stdout.golden @@ -7,13 +7,13 @@ alice: access: - read - write ---- -kind: Rule -access: -- read -- write -entity: - name: alice - relatives: - - relation: father - name: Reese \ No newline at end of file + ruleModel: + kind: Rule + access: + - read + - write + entity: + name: alice + relatives: + - relation: father + name: Reese diff --git a/test/grammar/schema/union/arguments/keyword_argument_0/main.k b/test/grammar/schema/union/arguments/keyword_argument_0/main.k new file mode 100644 index 000000000..2bc3701dd --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_0/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(separator=" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden b/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/keyword_argument_1/main.k b/test/grammar/schema/union/arguments/keyword_argument_1/main.k new file mode 100644 index 000000000..601a9cd2c --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_1/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person(separator="-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden b/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_0/main.k b/test/grammar/schema/union/arguments/single_argument_0/main.k new file mode 100644 index 000000000..422efd147 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_0/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/single_argument_0/stdout.golden b/test/grammar/schema/union/arguments/single_argument_0/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_0/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_1/main.k b/test/grammar/schema/union/arguments/single_argument_1/main.k new file mode 100644 index 000000000..83a0f95d6 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_1/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/single_argument_1/stdout.golden b/test/grammar/schema/union/arguments/single_argument_1/stdout.golden new file mode 100644 index 000000000..b981466f5 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_1/stdout.golden @@ -0,0 +1,10 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + lastName: Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_2/main.k b/test/grammar/schema/union/arguments/single_argument_2/main.k new file mode 100644 index 000000000..b81ebc06c --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_2/main.k @@ -0,0 +1,13 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = Person("*") { + **x + **y +} diff --git a/test/grammar/schema/union/arguments/single_argument_2/stdout.golden b/test/grammar/schema/union/arguments/single_argument_2/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_2/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/binary_union/binary_union_5/stdout.golden b/test/grammar/schema/union/binary_union/binary_union_5/stdout.golden index 87fe725dd..6ac69ff7b 100644 --- a/test/grammar/schema/union/binary_union/binary_union_5/stdout.golden +++ b/test/grammar/schema/union/binary_union/binary_union_5/stdout.golden @@ -1,2 +1,2 @@ -data1: 0b10101111 -data2: 0b11111111 +data1: '0b10101111' +data2: '0b11111111' diff --git a/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/main.k b/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/main.k new file mode 100644 index 000000000..b426e207e --- /dev/null +++ b/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/main.k @@ -0,0 +1,11 @@ +import regex + +schema Base: + cc: int = 1 + +schema Person(Base): + image: str + + check: + regex.match(image, "^[a-zA-Z]+:\d+\.\d+\.\d+$"), "image name should be like 'nginx:1.14.2'" + ccc > 2 diff --git a/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/stderr.golden.py b/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/stderr.golden.py new file mode 100644 index 000000000..8e9707787 --- /dev/null +++ b/test/grammar/schema/var_not_define_fail/var_not_define_fail_0/stderr.golden.py @@ -0,0 +1,22 @@ +import os +import sys + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=11, + col_no=9 + ) + ], + arg_msg="name 'ccc' is not defined" + ), + file=sys.stdout +) + diff --git a/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/main.k b/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/main.k new file mode 100644 index 000000000..aa4e34e3f --- /dev/null +++ b/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/main.k @@ -0,0 +1,8 @@ +schema Base: + cc: int = 1 + +schema Person(Base): + image: str + + check: + regex.match(image, "^[a-zA-Z]+:\d+\.\d+\.\d+$"), "image name should be like 'nginx:1.14.2'" diff --git a/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/stderr.golden.py b/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/stderr.golden.py new file mode 100644 index 000000000..aa42b9e85 --- /dev/null +++ b/test/grammar/schema/var_not_define_fail/var_not_define_fail_1/stderr.golden.py @@ -0,0 +1,21 @@ +import os +import sys + +import kclvm.kcl.error as kcl_error + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=11, + col_no=9 + ) + ], + arg_msg="name 'regex' is not defined" + ), + file=sys.stdout +) diff --git a/test/grammar/show_hidden/config/main.k b/test/grammar/show_hidden/config/main.k new file mode 100644 index 000000000..3437290d8 --- /dev/null +++ b/test/grammar/show_hidden/config/main.k @@ -0,0 +1 @@ +a = {_b = 1} diff --git a/test/grammar/show_hidden/config/settings.yaml b/test/grammar/show_hidden/config/settings.yaml new file mode 100644 index 000000000..7c23f622a --- /dev/null +++ b/test/grammar/show_hidden/config/settings.yaml @@ -0,0 +1 @@ +kcl_options: --show_hidden diff --git a/test/grammar/show_hidden/config/stdout.golden b/test/grammar/show_hidden/config/stdout.golden new file mode 100644 index 000000000..d167dd546 --- /dev/null +++ b/test/grammar/show_hidden/config/stdout.golden @@ -0,0 +1,2 @@ +a: + _b: 1 diff --git a/test/grammar/show_hidden/schema/main.k b/test/grammar/show_hidden/schema/main.k new file mode 100644 index 000000000..be064edb3 --- /dev/null +++ b/test/grammar/show_hidden/schema/main.k @@ -0,0 +1,4 @@ +schema Data: + [...str]: int + +a = Data {_b = 1} diff --git a/test/grammar/show_hidden/schema/settings.yaml b/test/grammar/show_hidden/schema/settings.yaml new file mode 100644 index 000000000..7c23f622a --- /dev/null +++ b/test/grammar/show_hidden/schema/settings.yaml @@ -0,0 +1 @@ +kcl_options: --show_hidden diff --git a/test/grammar/show_hidden/schema/stdout.golden b/test/grammar/show_hidden/schema/stdout.golden new file mode 100644 index 000000000..d167dd546 --- /dev/null +++ b/test/grammar/show_hidden/schema/stdout.golden @@ -0,0 +1,2 @@ +a: + _b: 1 diff --git a/test/grammar/show_hidden/simple/main.k b/test/grammar/show_hidden/simple/main.k new file mode 100644 index 000000000..ea1b2cfee --- /dev/null +++ b/test/grammar/show_hidden/simple/main.k @@ -0,0 +1,2 @@ +_b = 1 +a = 2 diff --git a/test/grammar/show_hidden/simple/settings.yaml b/test/grammar/show_hidden/simple/settings.yaml new file mode 100644 index 000000000..7c23f622a --- /dev/null +++ b/test/grammar/show_hidden/simple/settings.yaml @@ -0,0 +1 @@ +kcl_options: --show_hidden diff --git a/test/grammar/show_hidden/simple/stdout.golden b/test/grammar/show_hidden/simple/stdout.golden new file mode 100644 index 000000000..b4180cd89 --- /dev/null +++ b/test/grammar/show_hidden/simple/stdout.golden @@ -0,0 +1,2 @@ +_b: 1 +a: 2 diff --git a/test/grammar/sort_keys/config/main.k b/test/grammar/sort_keys/config/main.k new file mode 100644 index 000000000..4d1b2cda2 --- /dev/null +++ b/test/grammar/sort_keys/config/main.k @@ -0,0 +1,4 @@ +c = { + b = 1 + a = 2 +} diff --git a/test/grammar/sort_keys/config/settings.yaml b/test/grammar/sort_keys/config/settings.yaml new file mode 100644 index 000000000..c35040c35 --- /dev/null +++ b/test/grammar/sort_keys/config/settings.yaml @@ -0,0 +1 @@ +kcl_options: -d --sort_keys diff --git a/test/grammar/sort_keys/config/stdout.golden b/test/grammar/sort_keys/config/stdout.golden new file mode 100644 index 000000000..88df2d698 --- /dev/null +++ b/test/grammar/sort_keys/config/stdout.golden @@ -0,0 +1,3 @@ +c: + a: 2 + b: 1 diff --git a/test/grammar/sort_keys/schema/main.k b/test/grammar/sort_keys/schema/main.k new file mode 100644 index 000000000..a09337391 --- /dev/null +++ b/test/grammar/sort_keys/schema/main.k @@ -0,0 +1,8 @@ +schema X: + b: int + a: int + +c = X { + b = 1 + a = 2 +} diff --git a/test/grammar/sort_keys/schema/settings.yaml b/test/grammar/sort_keys/schema/settings.yaml new file mode 100644 index 000000000..c35040c35 --- /dev/null +++ b/test/grammar/sort_keys/schema/settings.yaml @@ -0,0 +1 @@ +kcl_options: -d --sort_keys diff --git a/test/grammar/sort_keys/schema/stdout.golden b/test/grammar/sort_keys/schema/stdout.golden new file mode 100644 index 000000000..88df2d698 --- /dev/null +++ b/test/grammar/sort_keys/schema/stdout.golden @@ -0,0 +1,3 @@ +c: + a: 2 + b: 1 diff --git a/test/grammar/syntax/else_if_token/main.k b/test/grammar/syntax/else_if_token/main.k new file mode 100644 index 000000000..ca259cb9f --- /dev/null +++ b/test/grammar/syntax/else_if_token/main.k @@ -0,0 +1,4 @@ +if True: + a = 1 +else if False: + b = 1 diff --git a/test/grammar/syntax/else_if_token/stderr.golden.py b/test/grammar/syntax/else_if_token/stderr.golden.py new file mode 100644 index 000000000..902f563d4 --- /dev/null +++ b/test/grammar/syntax/else_if_token/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=3, + col_no=6, + ) + ], + arg_msg="'else if' here is invalid in KCL, consider using the 'elif' keyword", + file=sys.stdout, + ) +) diff --git a/test/grammar/syntax/underline/main.k b/test/grammar/syntax/underline/main.k new file mode 100644 index 000000000..839a15078 --- /dev/null +++ b/test/grammar/syntax/underline/main.k @@ -0,0 +1 @@ +a = __b \ No newline at end of file diff --git a/test/grammar/syntax/underline/stderr.golden.py b/test/grammar/syntax/underline/stderr.golden.py new file mode 100644 index 000000000..f11123412 --- /dev/null +++ b/test/grammar/syntax/underline/stderr.golden.py @@ -0,0 +1,18 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception(err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=1, + col_no=5, + ) + ], + arg_msg="name '__b' is not defined", + file=sys.stdout +) \ No newline at end of file diff --git a/test/grammar/types/args/call_expr_err_too_few_args_0/main.k b/test/grammar/types/args/call_expr_err_too_few_args_0/main.k new file mode 100644 index 000000000..4cd8dcec2 --- /dev/null +++ b/test/grammar/types/args/call_expr_err_too_few_args_0/main.k @@ -0,0 +1 @@ +a = "".startswith() diff --git a/test/grammar/types/args/call_expr_err_too_few_args_0/stderr.golden.py b/test/grammar/types/args/call_expr_err_too_few_args_0/stderr.golden.py new file mode 100644 index 000000000..7a4521194 --- /dev/null +++ b/test/grammar/types/args/call_expr_err_too_few_args_0/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.TypeError_Compile_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=1, + col_no=5, + ) + ], + arg_msg='expected 1 argument, found 0' + ), + file=sys.stdout +) diff --git a/test/grammar/types/args/call_expr_err_too_few_args_1/main.k b/test/grammar/types/args/call_expr_err_too_few_args_1/main.k new file mode 100644 index 000000000..0bfc01a41 --- /dev/null +++ b/test/grammar/types/args/call_expr_err_too_few_args_1/main.k @@ -0,0 +1 @@ +a = "".replace("old") diff --git a/test/grammar/types/args/call_expr_err_too_few_args_1/stderr.golden.py b/test/grammar/types/args/call_expr_err_too_few_args_1/stderr.golden.py new file mode 100644 index 000000000..7a4521194 --- /dev/null +++ b/test/grammar/types/args/call_expr_err_too_few_args_1/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.TypeError_Compile_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=1, + col_no=5, + ) + ], + arg_msg='expected 1 argument, found 0' + ), + file=sys.stdout +) diff --git a/test/grammar/types/args/schema_types_err_too_many_args_0/main.k b/test/grammar/types/args/schema_types_err_too_many_args_0/main.k new file mode 100644 index 000000000..b805bcf68 --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_0/main.k @@ -0,0 +1,4 @@ +schema SchemaInMainK: + msg?: str + +schema_in_main_k = SchemaInMainK(msg='I am the instance of SchemaInMainK') diff --git a/test/grammar/types/args/schema_types_err_too_many_args_0/stderr.golden.py b/test/grammar/types/args/schema_types_err_too_many_args_0/stderr.golden.py new file mode 100644 index 000000000..7dc21d230 --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_0/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.TypeError_Compile_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=4, + col_no=34, + ) + ], + arg_msg='"SchemaInMainK" got an unexpected keyword argument \'msg\'' + ), + file=sys.stdout +) diff --git a/test/grammar/types/args/schema_types_err_too_many_args_1/main.k b/test/grammar/types/args/schema_types_err_too_many_args_1/main.k new file mode 100644 index 000000000..6cdd9cb7a --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_1/main.k @@ -0,0 +1,4 @@ +schema SchemaInMainK: + msg?: str + +schema_in_main_k = SchemaInMainK('I am the instance of SchemaInMainK') diff --git a/test/grammar/types/args/schema_types_err_too_many_args_1/stderr.golden.py b/test/grammar/types/args/schema_types_err_too_many_args_1/stderr.golden.py new file mode 100644 index 000000000..51132d69c --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_1/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.TypeError_Compile_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=4, + col_no=34, + ) + ], + arg_msg='"SchemaInMainK" takes 0 positional argument but 1 were given' + ), + file=sys.stdout +) diff --git a/test/grammar/types/args/schema_types_err_too_many_args_2/main.k b/test/grammar/types/args/schema_types_err_too_many_args_2/main.k new file mode 100644 index 000000000..de45e7a45 --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_2/main.k @@ -0,0 +1,4 @@ +schema SchemaInMainK[m: str]: + msg?: str + +schema_in_main_k = SchemaInMainK('param1', "param2") diff --git a/test/grammar/types/args/schema_types_err_too_many_args_2/stderr.golden.py b/test/grammar/types/args/schema_types_err_too_many_args_2/stderr.golden.py new file mode 100644 index 000000000..a479cb2ca --- /dev/null +++ b/test/grammar/types/args/schema_types_err_too_many_args_2/stderr.golden.py @@ -0,0 +1,20 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.TypeError_Compile_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=4, + col_no=34, + ) + ], + arg_msg='"SchemaInMainK" takes 1 positional argument but 2 were given' + ), + file=sys.stdout +) diff --git a/test/grammar/types/config/config_ty_0/main.k b/test/grammar/types/config/config_ty_0/main.k new file mode 100644 index 000000000..377e25e8d --- /dev/null +++ b/test/grammar/types/config/config_ty_0/main.k @@ -0,0 +1,14 @@ +config: {str:} = { + "key" = [ + { + key = "value" + } + ] + "values": [ + "foo" + "bar" + ] +} + +if "foo" in config.values: + a = 1 diff --git a/test/grammar/types/config/config_ty_0/stdout.golden b/test/grammar/types/config/config_ty_0/stdout.golden new file mode 100644 index 000000000..5868ff014 --- /dev/null +++ b/test/grammar/types/config/config_ty_0/stdout.golden @@ -0,0 +1,7 @@ +config: + key: + - key: value + values: + - foo + - bar +a: 1 diff --git a/test/grammar/types/config/config_ty_1/main.k b/test/grammar/types/config/config_ty_1/main.k new file mode 100644 index 000000000..ea3920300 --- /dev/null +++ b/test/grammar/types/config/config_ty_1/main.k @@ -0,0 +1,14 @@ +config: {str:} = { + key = [ + { + key = "value" + } + ] + values: [ + "foo" + "bar" + ] +} + +if "foo" in config.values: + a = 1 diff --git a/test/grammar/types/config/config_ty_1/stdout.golden b/test/grammar/types/config/config_ty_1/stdout.golden new file mode 100644 index 000000000..5868ff014 --- /dev/null +++ b/test/grammar/types/config/config_ty_1/stdout.golden @@ -0,0 +1,7 @@ +config: + key: + - key: value + values: + - foo + - bar +a: 1 diff --git a/test/grammar/types/config/config_ty_2/main.k b/test/grammar/types/config/config_ty_2/main.k new file mode 100644 index 000000000..f93e476a1 --- /dev/null +++ b/test/grammar/types/config/config_ty_2/main.k @@ -0,0 +1,12 @@ +config: {str:} = { + "key" = [ + { + key = "value" + } + ] + "values" = [ + "foo" + "bar" + ] +} +values: [str] = config.values diff --git a/test/grammar/types/config/config_ty_2/stdout.golden b/test/grammar/types/config/config_ty_2/stdout.golden new file mode 100644 index 000000000..e5349a781 --- /dev/null +++ b/test/grammar/types/config/config_ty_2/stdout.golden @@ -0,0 +1,9 @@ +config: + key: + - key: value + values: + - foo + - bar +values: +- foo +- bar diff --git a/test/grammar/types/config/config_ty_3/main.k b/test/grammar/types/config/config_ty_3/main.k new file mode 100644 index 000000000..7e1a11194 --- /dev/null +++ b/test/grammar/types/config/config_ty_3/main.k @@ -0,0 +1,12 @@ +config: {str:} = { + "map" = [ + { + key = "value" + } + ] + "values" = [ + "foo" + "bar" + ] +} +$map: [{str:str}] = config.map diff --git a/test/grammar/types/config/config_ty_3/stdout.golden b/test/grammar/types/config/config_ty_3/stdout.golden new file mode 100644 index 000000000..cf7c1c5e8 --- /dev/null +++ b/test/grammar/types/config/config_ty_3/stdout.golden @@ -0,0 +1,8 @@ +config: + map: + - key: value + values: + - foo + - bar +map: +- key: value diff --git a/test/grammar/types/loop/loop_0/main.k b/test/grammar/types/loop/loop_0/main.k new file mode 100644 index 000000000..8a2f48e78 --- /dev/null +++ b/test/grammar/types/loop/loop_0/main.k @@ -0,0 +1,12 @@ +name = "volume" +configMapVolumes1: {str:{str:}} = { + name = { + name = name + } for _ in range(1) +} + +configMapVolumes2: [{str:}] = [ + { + name = name + } for _ in range(1) +] diff --git a/test/grammar/types/loop/loop_0/stdout.golden b/test/grammar/types/loop/loop_0/stdout.golden new file mode 100644 index 000000000..1e94842a9 --- /dev/null +++ b/test/grammar/types/loop/loop_0/stdout.golden @@ -0,0 +1,6 @@ +name: volume +configMapVolumes1: + volume: + name: volume +configMapVolumes2: +- name: volume diff --git a/test/grammar/types/loop/loop_1/main.k b/test/grammar/types/loop/loop_1/main.k new file mode 100644 index 000000000..6fb5cbe39 --- /dev/null +++ b/test/grammar/types/loop/loop_1/main.k @@ -0,0 +1,12 @@ +name = "volume" +configMapVolumes1: [{str:{str:}}] = [{ + name = { + name = name + } for _ in range(1) +}] + +configMapVolumes2: {str:[{str:}]} = {name = [ + { + name = name + } for _ in range(1) +]} diff --git a/test/grammar/types/loop/loop_1/stdout.golden b/test/grammar/types/loop/loop_1/stdout.golden new file mode 100644 index 000000000..f3239790e --- /dev/null +++ b/test/grammar/types/loop/loop_1/stdout.golden @@ -0,0 +1,7 @@ +name: volume +configMapVolumes1: +- volume: + name: volume +configMapVolumes2: + name: + - name: volume \ No newline at end of file diff --git a/test/grammar/types/union_ty/union_ty_0/main.k b/test/grammar/types/union_ty/union_ty_0/main.k new file mode 100644 index 000000000..4067fdc5f --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_0/main.k @@ -0,0 +1,12 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: A | B + +x = X { + x.a = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_0/stdout.golden b/test/grammar/types/union_ty/union_ty_0/stdout.golden new file mode 100644 index 000000000..09785193a --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_0/stdout.golden @@ -0,0 +1,3 @@ +x: + x: + a: 1 diff --git a/test/grammar/types/union_ty/union_ty_1/main.k b/test/grammar/types/union_ty/union_ty_1/main.k new file mode 100644 index 000000000..9ce97d381 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_1/main.k @@ -0,0 +1,12 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: A | B + +x = X { + x.b = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_1/stdout.golden b/test/grammar/types/union_ty/union_ty_1/stdout.golden new file mode 100644 index 000000000..5e7e776a0 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_1/stdout.golden @@ -0,0 +1,3 @@ +x: + x: + b: 1 diff --git a/test/grammar/types/union_ty/union_ty_10/main.k b/test/grammar/types/union_ty/union_ty_10/main.k new file mode 100644 index 000000000..d9305905c --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_10/main.k @@ -0,0 +1,13 @@ +schema A: + a: int + +schema B(A): + b: int = a + +schema X: + x: A | B + +x = X { + x.a = 1 + x.b = 2 +} diff --git a/test/grammar/types/union_ty/union_ty_10/stdout.golden b/test/grammar/types/union_ty/union_ty_10/stdout.golden new file mode 100644 index 000000000..eaa1a7893 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_10/stdout.golden @@ -0,0 +1,4 @@ +x: + x: + a: 1 + b: 2 diff --git a/test/grammar/types/union_ty/union_ty_11/main.k b/test/grammar/types/union_ty/union_ty_11/main.k new file mode 100644 index 000000000..0ecbbb635 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_11/main.k @@ -0,0 +1,6 @@ +metadata = { + name = "app" + labels.app = "app" +} +labels: {str:str} = metadata.labels + diff --git a/test/grammar/types/union_ty/union_ty_11/stdout.golden b/test/grammar/types/union_ty/union_ty_11/stdout.golden new file mode 100644 index 000000000..b230162b2 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_11/stdout.golden @@ -0,0 +1,6 @@ +metadata: + name: app + labels: + app: app +labels: + app: app diff --git a/test/grammar/types/union_ty/union_ty_12/main.k b/test/grammar/types/union_ty/union_ty_12/main.k new file mode 100644 index 000000000..44a97d4e9 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_12/main.k @@ -0,0 +1,6 @@ +metadata = { + name = "app" + labels.app = "app" +} +labels: {str:str} = {**metadata.labels} + diff --git a/test/grammar/types/union_ty/union_ty_12/stdout.golden b/test/grammar/types/union_ty/union_ty_12/stdout.golden new file mode 100644 index 000000000..b230162b2 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_12/stdout.golden @@ -0,0 +1,6 @@ +metadata: + name: app + labels: + app: app +labels: + app: app diff --git a/test/grammar/types/union_ty/union_ty_2/main.k b/test/grammar/types/union_ty/union_ty_2/main.k new file mode 100644 index 000000000..487889c33 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_2/main.k @@ -0,0 +1,15 @@ +schema A: + a: int + +schema B: + b: int + +schema C(B): + c: int + +schema X: + x: A | B + +x = X { + x.b = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_2/stdout.golden b/test/grammar/types/union_ty/union_ty_2/stdout.golden new file mode 100644 index 000000000..5e7e776a0 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_2/stdout.golden @@ -0,0 +1,3 @@ +x: + x: + b: 1 diff --git a/test/grammar/types/union_ty/union_ty_3/main.k b/test/grammar/types/union_ty/union_ty_3/main.k new file mode 100644 index 000000000..c46394792 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_3/main.k @@ -0,0 +1,12 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: [A | B] + +x = X { + x = [{a = 1}, {b = 2}] +} diff --git a/test/grammar/types/union_ty/union_ty_3/stdout.golden b/test/grammar/types/union_ty/union_ty_3/stdout.golden new file mode 100644 index 000000000..1ea03027e --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_3/stdout.golden @@ -0,0 +1,4 @@ +x: + x: + - a: 1 + - b: 2 diff --git a/test/grammar/types/union_ty/union_ty_4/main.k b/test/grammar/types/union_ty/union_ty_4/main.k new file mode 100644 index 000000000..a4d8b4f78 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_4/main.k @@ -0,0 +1,9 @@ +schema A: + a: int + +schema X: + x: A | "1" + +x = X { + x.a = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_4/stdout.golden b/test/grammar/types/union_ty/union_ty_4/stdout.golden new file mode 100644 index 000000000..09785193a --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_4/stdout.golden @@ -0,0 +1,3 @@ +x: + x: + a: 1 diff --git a/test/grammar/types/union_ty/union_ty_5/main.k b/test/grammar/types/union_ty/union_ty_5/main.k new file mode 100644 index 000000000..a6d17ea0a --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_5/main.k @@ -0,0 +1,11 @@ +schema A: + a: int + +schema X: + x: [A | "1"] + y: ["2" | A] + +x = X { + x: [{a = 1}] + y: [{a = 2}] +} diff --git a/test/grammar/types/union_ty/union_ty_5/stdout.golden b/test/grammar/types/union_ty/union_ty_5/stdout.golden new file mode 100644 index 000000000..52ed8310b --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_5/stdout.golden @@ -0,0 +1,5 @@ +x: + x: + - a: 1 + y: + - a: 2 diff --git a/test/grammar/types/union_ty/union_ty_6/main.k b/test/grammar/types/union_ty/union_ty_6/main.k new file mode 100644 index 000000000..f893ca3c6 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_6/main.k @@ -0,0 +1,14 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: A | "1" + y: "2" | B + +x = X { + x.a = 1 + y.b = 2 +} diff --git a/test/grammar/types/union_ty/union_ty_6/stdout.golden b/test/grammar/types/union_ty/union_ty_6/stdout.golden new file mode 100644 index 000000000..5b52e9920 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_6/stdout.golden @@ -0,0 +1,5 @@ +x: + x: + a: 1 + y: + b: 2 diff --git a/test/grammar/types/union_ty/union_ty_7/main.k b/test/grammar/types/union_ty/union_ty_7/main.k new file mode 100644 index 000000000..55e2e105c --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_7/main.k @@ -0,0 +1,13 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: {str: A | B} + +x = X { + x.a.a = 1 + x.b.b = 2 +} diff --git a/test/grammar/types/union_ty/union_ty_7/stdout.golden b/test/grammar/types/union_ty/union_ty_7/stdout.golden new file mode 100644 index 000000000..2006676c6 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_7/stdout.golden @@ -0,0 +1,6 @@ +x: + x: + a: + a: 1 + b: + b: 2 diff --git a/test/grammar/types/union_ty/union_ty_8/main.k b/test/grammar/types/union_ty/union_ty_8/main.k new file mode 100644 index 000000000..a4b3044c1 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_8/main.k @@ -0,0 +1,14 @@ +schema A: + a: int + +schema B: + b: int + c: int = b + 1 + +schema X: + x: {str: A | B} + +x = X { + x.a.a = 1 + x.b.b = 2 +} diff --git a/test/grammar/types/union_ty/union_ty_8/stdout.golden b/test/grammar/types/union_ty/union_ty_8/stdout.golden new file mode 100644 index 000000000..690d4b806 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_8/stdout.golden @@ -0,0 +1,7 @@ +x: + x: + a: + a: 1 + b: + b: 2 + c: 3 diff --git a/test/grammar/types/union_ty/union_ty_9/main.k b/test/grammar/types/union_ty/union_ty_9/main.k new file mode 100644 index 000000000..0f95a06c6 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_9/main.k @@ -0,0 +1,12 @@ +schema A: + a: int + +schema B(A): + b: int = a + +schema X: + x: B + +x = X { + x.a = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_9/stdout.golden b/test/grammar/types/union_ty/union_ty_9/stdout.golden new file mode 100644 index 000000000..8103e3962 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_9/stdout.golden @@ -0,0 +1,4 @@ +x: + x: + a: 1 + b: 1 diff --git a/test/grammar/types/union_ty/union_ty_err_0/main.k b/test/grammar/types/union_ty/union_ty_err_0/main.k new file mode 100644 index 000000000..f561dfb38 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_err_0/main.k @@ -0,0 +1,12 @@ +schema A: + a: int + +schema B: + b: int + +schema X: + x: A | B + +x = X { + x.c = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_err_0/stderr.golden.py b/test/grammar/types/union_ty/union_ty_err_0/stderr.golden.py new file mode 100644 index 000000000..fd10182e7 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_err_0/stderr.golden.py @@ -0,0 +1,19 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=8, + ) + ], + arg_msg="expect A|B, got dict" + ), + file=sys.stdout +) diff --git a/test/grammar/types/union_ty/union_ty_err_1/main.k b/test/grammar/types/union_ty/union_ty_err_1/main.k new file mode 100644 index 000000000..5a59573a0 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_err_1/main.k @@ -0,0 +1,15 @@ +schema A: + a: int + +schema B: + b: int + +schema C(B): + c: int + +schema X: + x: A | B | C + +x = X { + x.d = 1 +} diff --git a/test/grammar/types/union_ty/union_ty_err_1/stderr.golden.py b/test/grammar/types/union_ty/union_ty_err_1/stderr.golden.py new file mode 100644 index 000000000..3754d2dc5 --- /dev/null +++ b/test/grammar/types/union_ty/union_ty_err_1/stderr.golden.py @@ -0,0 +1,19 @@ +import sys +import kclvm.kcl.error as kcl_error +import os + +cwd = os.path.dirname(os.path.realpath(__file__)) + +kcl_error.print_kcl_error_message( + kcl_error.get_exception( + err_type=kcl_error.ErrType.CompileError_TYPE, + file_msgs=[ + kcl_error.ErrFileMsg( + filename=cwd + "/main.k", + line_no=11, + ) + ], + arg_msg="expect A|B|C, got dict" + ), + file=sys.stdout +)