diff --git a/.envrc b/.envrc deleted file mode 100644 index 8392d15..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake \ No newline at end of file diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 88ed82a..9611de9 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -3,7 +3,10 @@ name: Go -on: ["push", "pull_request"] +on: + pull_request: + branches: + - main jobs: build: diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml deleted file mode 100644 index 6790e55..0000000 --- a/.github/workflows/nix.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Nix CI - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - tests: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest] - system: [x86_64-linux, aarch64-darwin] - steps: - - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v25 - with: - nix_path: nixpkgs=channel:nixos-unstable - - uses: DeterminateSystems/magic-nix-cache-action@v2 - - run: | - nix build \ - --extra-access-tokens "github.com=${{ secrets.GITHUB_TOKEN }}" \ - .#default diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 119b07e..bb30800 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -16,7 +16,7 @@ before: builds: - env: - CGO_ENABLED=0 - main: ./internal/numscript/numscript.go + main: ./main.go goos: - wasip1 goarch: diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cce71ca..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Formance, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Numscript.g4 b/Numscript.g4 deleted file mode 100644 index 793d2d9..0000000 --- a/Numscript.g4 +++ /dev/null @@ -1,105 +0,0 @@ -grammar Numscript; - -// Tokens -WS: [ \t\r\n]+ -> skip; -NEWLINE: [\r\n]+; -MULTILINE_COMMENT: '/*' (MULTILINE_COMMENT | .)*? '*/' -> skip; -LINE_COMMENT: '//' .*? NEWLINE -> skip; - -VARS: 'vars'; -MAX: 'max'; -SOURCE: 'source'; -DESTINATION: 'destination'; -SEND: 'send'; -FROM: 'from'; -UP: 'up'; -TO: 'to'; -REMAINING: 'remaining'; -ALLOWING: 'allowing'; -UNBOUNDED: 'unbounded'; -OVERDRAFT: 'overdraft'; -KEPT: 'kept'; -SAVE: 'save'; -LPARENS: '('; -RPARENS: ')'; -LBRACKET: '['; -RBRACKET: ']'; -LBRACE: '{'; -RBRACE: '}'; -COMMA: ','; -EQ: '='; -STAR: '*'; -MINUS: '-'; - -RATIO_PORTION_LITERAL: [0-9]+ [ ]? '/' [ ]? [0-9]+; -PERCENTAGE_PORTION_LITERAL: [0-9]+ ('.' [0-9]+)? '%'; - -STRING: '"' ('\\"' | ~[\r\n"])* '"'; - -IDENTIFIER: [a-z]+ [a-z_]*; -NUMBER: MINUS? [0-9]+; -VARIABLE_NAME: '$' [a-z_]+ [a-z0-9_]*; -ACCOUNT: '@' [a-zA-Z0-9_-]+ (':' [a-zA-Z0-9_-]+)*; -ASSET: [A-Z/0-9]+; - -monetaryLit: - LBRACKET (asset = valueExpr) (amt = valueExpr) RBRACKET; - -portion: - RATIO_PORTION_LITERAL # ratio - | PERCENTAGE_PORTION_LITERAL # percentage; - -valueExpr: - VARIABLE_NAME # variableExpr - | ASSET # assetLiteral - | STRING # stringLiteral - | ACCOUNT # accountLiteral - | NUMBER # numberLiteral - | monetaryLit # monetaryLiteral - | portion # portionLiteral - | left = valueExpr op = ('+' | '-') right = valueExpr # infixExpr; - -functionCallArgs: valueExpr ( COMMA valueExpr)*; -functionCall: IDENTIFIER LPARENS functionCallArgs? RPARENS; - -varOrigin: EQ functionCall; -varDeclaration: - type_ = IDENTIFIER name = VARIABLE_NAME varOrigin?; -varsDeclaration: VARS LBRACE varDeclaration* RBRACE; - -program: varsDeclaration? statement* EOF; - -sentAllLit: LBRACKET (asset = valueExpr) STAR RBRACKET; - -allotment: - portion # portionedAllotment - | VARIABLE_NAME # portionVariable - | REMAINING # remainingAllotment; - -source: - address = valueExpr ALLOWING UNBOUNDED OVERDRAFT # srcAccountUnboundedOverdraft - | address = valueExpr ALLOWING OVERDRAFT UP TO maxOvedraft = valueExpr # - srcAccountBoundedOverdraft - | valueExpr # srcAccount - | LBRACE allotmentClauseSrc+ RBRACE # srcAllotment - | LBRACE source* RBRACE # srcInorder - | MAX cap = valueExpr FROM source # srcCapped; -allotmentClauseSrc: allotment FROM source; - -keptOrDestination: - TO destination # destinationTo - | KEPT # destinationKept; -destinationInOrderClause: MAX valueExpr keptOrDestination; - -destination: - valueExpr # destAccount - | LBRACE allotmentClauseDest+ RBRACE # destAllotment - | LBRACE destinationInOrderClause* REMAINING keptOrDestination RBRACE # destInorder; -allotmentClauseDest: allotment keptOrDestination; - -sentValue: valueExpr # sentLiteral | sentAllLit # sentAll; - -statement: - SEND sentValue LPARENS SOURCE EQ source DESTINATION EQ destination RPARENS # sendStatement - | SAVE sentValue FROM valueExpr # saveStatement - | functionCall # fnCallStatement; \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index e7159aa..0000000 --- a/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Numscript CLI - -[![Go](https://github.com/PagoPlus/numscriptex/actions/workflows/checks.yml/badge.svg)](https://github.com/PagoPlus/numscriptex/actions/workflows/checks.yml) [![codecov](https://codecov.io/gh/formancehq/numscript/graph/badge.svg?token=njjqGhFQ2p)](https://codecov.io/gh/formancehq/numscript) - -Numscript is the DSL used to express financial transaction within the [Formance](https://www.formance.com/) ledger - -The CLI in this repo allows you to play with numscript locally, check if there are parsing or logic errors in your numscript files, and run the numscript language server - -The language server features include: - -- Diagnostics -- Hover on values -- Detect document symbols -- Go to definition - -### Develop locally - -You can update snaphshots with the -`UPDATE_SNAPS=true` variable while running the tests - -If you need to update the grammar, you can generate the parser using the `generate-parser.sh` script (you'll need to install the antlr4 command first) diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 396ec32..0000000 --- a/flake.lock +++ /dev/null @@ -1,61 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1734649271, - "narHash": "sha256-4EVBRhOjMDuGtMaofAIqzJbg4Ql7Ai0PSeuVZTHjyKQ=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "d70bd19e0a38ad4790d3913bf08fcbfc9eeca507", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 56a4c67..0000000 --- a/flake.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ - description = "A Nix flake for NumScript WASM compilation"; - - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - }; - - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: - let - inherit (pkgs.lib) optional optionals; - pkgs = import nixpkgs { inherit system; }; - - inputs = with pkgs; [ - go - tinygo - git - just - ] ++ optional stdenv.isLinux inotify-tools - ++ optionals stdenv.isDarwin - (with darwin.apple_sdk.frameworks; [ CoreFoundation CoreServices ]); - - in with pkgs; { - packages.default = mkShell { - name = "numscript-wasm"; - packages = inputs; - - shellHook = '' - echo "NumScript WASM development environment" - echo "TinyGo version: $(tinygo version)" - echo "Go version: $(go version)" - ''; - }; - }); -} diff --git a/generate-cover.sh b/generate-cover.sh deleted file mode 100644 index 1fb6418..0000000 --- a/generate-cover.sh +++ /dev/null @@ -1,2 +0,0 @@ -go test ./... -coverprofile=coverage.txt -go tool cover -html=coverage.txt diff --git a/generate-parser.sh b/generate-parser.sh deleted file mode 100644 index c2869e4..0000000 --- a/generate-parser.sh +++ /dev/null @@ -1 +0,0 @@ -antlr4 -Dlanguage=Go Numscript.g4 -o internal/parser/antlr diff --git a/go.mod b/go.mod index 121f710..53802be 100644 --- a/go.mod +++ b/go.mod @@ -1,36 +1,16 @@ -module github.com/PagoPlus/numscript-wasm +module numscript -go 1.22.1 +go 1.23.0 require ( - github.com/Jeffail/gabs/v2 v2.7.0 - github.com/antlr4-go/antlr/v4 v4.13.1 - github.com/gkampitakis/go-snaps v0.5.4 + github.com/formancehq/numscript v0.0.18 + github.com/spf13/cobra v1.9.1 ) -require github.com/gorilla/websocket v1.5.0 // indirect - require ( - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - -require ( - github.com/gkampitakis/ciinfo v0.3.0 // indirect - github.com/gkampitakis/go-diff v1.3.2 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/maruel/natural v1.1.1 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect - github.com/sourcegraph/jsonrpc2 v0.2.0 - github.com/stretchr/testify v1.9.0 - github.com/tidwall/gjson v1.17.1 // indirect - github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.1 // indirect - github.com/tidwall/sjson v1.2.5 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 + github.com/spf13/pflag v1.0.6 // indirect + github.com/stretchr/testify v1.10.0 // indirect + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect ) diff --git a/go.sum b/go.sum index 14c0c23..f54c860 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,16 @@ -github.com/Jeffail/gabs/v2 v2.7.0 h1:Y2edYaTcE8ZpRsR2AtmPu5xQdFDIthFG0jYhu5PY8kg= -github.com/Jeffail/gabs/v2 v2.7.0/go.mod h1:dp5ocw1FvBBQYssgHsG7I1WYsiLRtkUaB1FEtSwvNUw= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/formancehq/numscript v0.0.18 h1:+TjMZkuW2CqS3w2dT8t1Akjt+vp20glrUfWoRUPdYCA= +github.com/formancehq/numscript v0.0.18/go.mod h1:8WhBIqcK6zu27njxy7ZG7CaDX0MHtI9qF9Ggfj07wfU= github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvpAv8= github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= github.com/gkampitakis/go-snaps v0.5.4 h1:GX+dkKmVsRenz7SoTbdIEL4KQARZctkMiZ8ZKprRwT8= github.com/gkampitakis/go-snaps v0.5.4/go.mod h1:ZABkO14uCuVxBHAXAfKG+bqNz+aa1bGPAg8jkI0Nk8Y= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -23,34 +19,27 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sourcegraph/jsonrpc2 v0.2.0 h1:KjN/dC4fP6aN9030MZCJs9WQbTOjWHhrtKVpzzSrr/U= -github.com/sourcegraph/jsonrpc2 v0.2.0/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/analysis/check.go b/internal/analysis/check.go deleted file mode 100644 index f26b19a..0000000 --- a/internal/analysis/check.go +++ /dev/null @@ -1,656 +0,0 @@ -package analysis - -import ( - "math/big" - "slices" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -const TypeMonetary = "monetary" -const TypeAccount = "account" -const TypePortion = "portion" -const TypeAsset = "asset" -const TypeNumber = "number" -const TypeString = "string" - -const TypeAny = "any" - -var AllowedTypes = []string{ - TypeMonetary, - TypeAccount, - TypePortion, - TypeAsset, - TypeNumber, - TypeString, -} - -type FnCallResolution interface { - ContextName() string - GetParams() []string - fnCallResolution() -} - -type VarOriginFnCallResolution struct { - Params []string - Docs string - Return string -} -type StatementFnCallResolution struct { - Params []string - Docs string -} - -func (VarOriginFnCallResolution) ContextName() string { return "variable origin" } -func (StatementFnCallResolution) ContextName() string { return "statement" } - -func (VarOriginFnCallResolution) fnCallResolution() {} -func (StatementFnCallResolution) fnCallResolution() {} - -func (r VarOriginFnCallResolution) GetParams() []string { return r.Params } -func (r StatementFnCallResolution) GetParams() []string { return r.Params } - -const FnSetTxMeta = "set_tx_meta" -const FnSetAccountMeta = "set_account_meta" -const FnVarOriginMeta = "meta" -const FnVarOriginBalance = "balance" - -var Builtins = map[string]FnCallResolution{ - FnSetTxMeta: StatementFnCallResolution{ - Params: []string{TypeString, TypeAny}, - Docs: "set transaction metadata", - }, - FnSetAccountMeta: StatementFnCallResolution{ - Params: []string{TypeAccount, TypeString, TypeAny}, - Docs: "set account metadata", - }, - FnVarOriginMeta: VarOriginFnCallResolution{ - Params: []string{TypeAccount, TypeString}, - Return: TypeAny, - Docs: "fetch account metadata", - }, - FnVarOriginBalance: VarOriginFnCallResolution{ - Params: []string{TypeAccount, TypeAsset}, - Return: TypeMonetary, - Docs: "fetch account balance", - }, -} - -type Diagnostic struct { - Range parser.Range - Kind DiagnosticKind -} - -type CheckResult struct { - unboundedAccountInSend parser.ValueExpr - emptiedAccount map[string]struct{} - unboundedSend bool - declaredVars map[string]parser.VarDeclaration - unusedVars map[string]parser.Range - varResolution map[*parser.Variable]parser.VarDeclaration - fnCallResolution map[*parser.FnCallIdentifier]FnCallResolution - Diagnostics []Diagnostic - Program parser.Program -} - -func (r CheckResult) GetErrorsCount() int { - c := 0 - for _, d := range r.Diagnostics { - if d.Kind.Severity() == ErrorSeverity { - c++ - } - } - return c -} - -func (r CheckResult) GetWarningsCount() int { - c := 0 - for _, d := range r.Diagnostics { - if d.Kind.Severity() == WarningSeverity { - c++ - } - } - return c -} - -func (r CheckResult) ResolveVar(v *parser.Variable) *parser.VarDeclaration { - k, ok := r.varResolution[v] - if !ok { - return nil - } - return &k -} - -func (r CheckResult) ResolveBuiltinFn(v *parser.FnCallIdentifier) FnCallResolution { - k, ok := r.fnCallResolution[v] - if !ok { - return nil - } - return k -} - -func newCheckResult(program parser.Program) CheckResult { - return CheckResult{ - emptiedAccount: make(map[string]struct{}), - declaredVars: make(map[string]parser.VarDeclaration), - unusedVars: make(map[string]parser.Range), - varResolution: make(map[*parser.Variable]parser.VarDeclaration), - fnCallResolution: make(map[*parser.FnCallIdentifier]FnCallResolution), - Program: program, - } -} - -func (res *CheckResult) check() { - for _, varDecl := range res.Program.Vars { - if varDecl.Type != nil { - res.checkVarType(*varDecl.Type) - } - - if varDecl.Name != nil { - res.checkDuplicateVars(*varDecl.Name, varDecl) - } - - if varDecl.Origin != nil { - res.checkVarOrigin(*varDecl.Origin, varDecl) - } - } - for _, statement := range res.Program.Statements { - res.unboundedAccountInSend = nil - res.checkStatement(statement) - } - - // after static AST traversal is complete, check for unused vars - for name, rng := range res.unusedVars { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: rng, - Kind: &UnusedVar{Name: name}, - }) - } -} - -func (res *CheckResult) checkStatement(statement parser.Statement) { - res.emptiedAccount = make(map[string]struct{}) - - switch statement := statement.(type) { - case *parser.SaveStatement: - res.checkSentValue(statement.SentValue) - res.checkExpression(statement.Amount, TypeAccount) - - case *parser.SendStatement: - _, isSendAll := statement.SentValue.(*parser.SentValueAll) - res.unboundedSend = isSendAll - - res.checkSentValue(statement.SentValue) - res.checkSource(statement.Source) - res.checkDestination(statement.Destination) - case *parser.FnCall: - resolution, ok := Builtins[statement.Caller.Name] - if ok { - if varOrigin, ok := resolution.(StatementFnCallResolution); ok { - res.fnCallResolution[statement.Caller] = varOrigin - } - } - - // This must come after resolution - res.checkFnCallArity(statement) - } -} - -func CheckProgram(program parser.Program) CheckResult { - res := newCheckResult(program) - res.check() - return res -} - -func CheckSource(source string) CheckResult { - result := parser.Parse(source) - res := newCheckResult(result.Value) - for _, parserError := range result.Errors { - res.Diagnostics = append(res.Diagnostics, parsingErrorToDiagnostic(parserError)) - } - res.check() - return res -} - -func parsingErrorToDiagnostic(parserError parser.ParserError) Diagnostic { - return Diagnostic{ - Range: parserError.Range, - Kind: &Parsing{Description: parserError.Msg}, - } -} - -func (res *CheckResult) checkFnCallArity(fnCall *parser.FnCall) { - resolution, resolved := res.fnCallResolution[fnCall.Caller] - - var validArgs []parser.ValueExpr - for _, lit := range fnCall.Args { - if lit != nil { - validArgs = append(validArgs, lit) - } - } - - if resolved { - sig := resolution.GetParams() - actualArgs := len(validArgs) - expectedArgs := len(sig) - - if actualArgs < expectedArgs { - // Too few args - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: fnCall.Range, - Kind: &BadArity{ - Expected: expectedArgs, - Actual: actualArgs, - }, - }) - } else if actualArgs > expectedArgs { - // Too many args - firstIllegalArg := validArgs[expectedArgs] - lastIllegalArg := validArgs[len(validArgs)-1] - - if lastIllegalArg != nil { - rng := parser.Range{ - Start: firstIllegalArg.GetRange().Start, - End: lastIllegalArg.GetRange().End, - } - - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: rng, - Kind: &BadArity{ - Expected: expectedArgs, - Actual: actualArgs, - }, - }) - } - - } - - for index, arg := range validArgs { - lastElemIndex := len(sig) - 1 - if index > lastElemIndex { - break - } - - type_ := sig[index] - res.checkExpression(arg, type_) - } - } else { - for _, arg := range validArgs { - res.checkExpression(arg, TypeAny) - } - - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: fnCall.Caller.Range, - Kind: &UnknownFunction{ - Name: fnCall.Caller.Name, - }, - }) - } -} - -func isTypeAllowed(typeName string) bool { - return slices.Contains(AllowedTypes, typeName) -} - -func (res *CheckResult) checkVarType(typeDecl parser.TypeDecl) { - if !isTypeAllowed(typeDecl.Name) { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: typeDecl.Range, - Kind: &InvalidType{Name: typeDecl.Name}, - }) - } -} - -func (res *CheckResult) checkDuplicateVars(variableName parser.Variable, decl parser.VarDeclaration) { - // check there aren't duplicate variables - if _, ok := res.declaredVars[variableName.Name]; ok { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: variableName.Range, - Kind: &DuplicateVariable{Name: variableName.Name}, - }) - } else { - res.declaredVars[variableName.Name] = decl - res.unusedVars[variableName.Name] = variableName.Range - } -} - -func (res *CheckResult) checkVarOrigin(fnCall parser.FnCall, decl parser.VarDeclaration) { - resolution, ok := Builtins[fnCall.Caller.Name] - if ok { - resolution, ok := resolution.(VarOriginFnCallResolution) - if ok { - res.fnCallResolution[decl.Origin.Caller] = resolution - res.assertHasType(decl.Name, resolution.Return, decl.Type.Name) - } - } - - // this must come after resolution - res.checkFnCallArity(&fnCall) -} - -func (res *CheckResult) checkExpression(lit parser.ValueExpr, requiredType string) { - switch lit := lit.(type) { - case *parser.Variable: - if varDeclaration, ok := res.declaredVars[lit.Name]; ok { - res.varResolution[lit] = varDeclaration - } else { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: lit.Range, - Kind: &UnboundVariable{Name: lit.Name}, - }) - } - delete(res.unusedVars, lit.Name) - - resolved := res.ResolveVar(lit) - if resolved == nil || resolved.Type == nil || !isTypeAllowed(resolved.Type.Name) { - return - } - res.assertHasType(lit, requiredType, resolved.Type.Name) - - case *parser.MonetaryLiteral: - res.assertHasType(lit, requiredType, TypeMonetary) - res.checkExpression(lit.Asset, TypeAsset) - res.checkExpression(lit.Amount, TypeNumber) - case *parser.AccountLiteral: - res.assertHasType(lit, requiredType, TypeAccount) - case *parser.RatioLiteral: - res.assertHasType(lit, requiredType, TypePortion) - case *parser.AssetLiteral: - res.assertHasType(lit, requiredType, TypeAsset) - case *parser.NumberLiteral: - res.assertHasType(lit, requiredType, TypeNumber) - case *parser.StringLiteral: - res.assertHasType(lit, requiredType, TypeString) - case *parser.BinaryInfix: - res.checkExpression(lit.Left, TypeAny) - res.checkExpression(lit.Right, TypeAny) - } -} - -func (res *CheckResult) assertHasType(lit parser.ValueExpr, requiredType string, actualType string) { - if requiredType == TypeAny || requiredType == actualType { - return - } - - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: lit.GetRange(), - Kind: &TypeMismatch{ - Expected: requiredType, - Got: actualType, - }, - }) - -} - -func (res *CheckResult) checkSentValue(sentValue parser.SentValue) { - switch sentValue := sentValue.(type) { - case *parser.SentValueAll: - res.checkExpression(sentValue.Asset, TypeAsset) - case *parser.SentValueLiteral: - res.checkExpression(sentValue.Monetary, TypeMonetary) - } -} - -func (res *CheckResult) checkSource(source parser.Source) { - if source == nil { - return - } - - if res.unboundedAccountInSend != nil { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: source.GetRange(), - Kind: &UnboundedAccountIsNotLast{}, - }) - } - - switch source := source.(type) { - case *parser.SourceAccount: - res.checkExpression(source.ValueExpr, TypeAccount) - if account, ok := source.ValueExpr.(*parser.AccountLiteral); ok { - if account.IsWorld() && res.unboundedSend { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: source.GetRange(), - Kind: &InvalidUnboundedAccount{}, - }) - } else if account.IsWorld() { - res.unboundedAccountInSend = account - } - - if _, emptied := res.emptiedAccount[account.Name]; emptied && !account.IsWorld() { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Kind: &EmptiedAccount{Name: account.Name}, - Range: account.Range, - }) - } - - res.emptiedAccount[account.Name] = struct{}{} - } - - case *parser.SourceOverdraft: - if accountLiteral, ok := source.Address.(*parser.AccountLiteral); ok && accountLiteral.IsWorld() { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: accountLiteral.Range, - Kind: &InvalidWorldOverdraft{}, - }) - } - - if source.Bounded == nil { - res.unboundedAccountInSend = source.Address - } - - if res.unboundedSend { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: source.Address.GetRange(), - Kind: &InvalidUnboundedAccount{}, - }) - } - - res.checkExpression(source.Address, TypeAccount) - if source.Bounded != nil { - res.checkExpression(*source.Bounded, TypeMonetary) - } - - case *parser.SourceInorder: - for _, source := range source.Sources { - res.checkSource(source) - } - - case *parser.SourceCapped: - onExit := res.enterCappedSource() - - res.checkExpression(source.Cap, TypeMonetary) - res.checkSource(source.From) - - onExit() - - case *parser.SourceAllotment: - if res.unboundedSend { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Kind: &NoAllotmentInSendAll{}, - Range: source.Range, - }) - } - - var remainingAllotment *parser.RemainingAllotment = nil - var variableLiterals []parser.Variable - - sum := big.NewRat(0, 1) - for i, allottedItem := range source.Items { - isLast := i == len(source.Items)-1 - - switch allotment := allottedItem.Allotment.(type) { - case *parser.Variable: - variableLiterals = append(variableLiterals, *allotment) - res.checkExpression(allotment, TypePortion) - case *parser.RatioLiteral: - sum.Add(sum, allotment.ToRatio()) - case *parser.RemainingAllotment: - if isLast { - remainingAllotment = allotment - } else { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: source.Range, - Kind: &RemainingIsNotLast{}, - }) - } - } - - onExit := res.enterCappedSource() - res.checkSource(allottedItem.From) - onExit() - } - - res.checkHasBadAllotmentSum(*sum, source.Range, remainingAllotment, variableLiterals) - - default: - utils.NonExhaustiveMatchPanic[any](source) - } -} - -func (res *CheckResult) checkDestination(destination parser.Destination) { - if destination == nil { - return - } - - switch destination := destination.(type) { - case *parser.DestinationAccount: - res.checkExpression(destination.ValueExpr, TypeAccount) - - case *parser.DestinationInorder: - for _, clause := range destination.Clauses { - res.checkExpression(clause.Cap, TypeMonetary) - res.checkKeptOrDestination(clause.To) - } - res.checkKeptOrDestination(destination.Remaining) - - case *parser.DestinationAllotment: - var remainingAllotment *parser.RemainingAllotment - var variableLiterals []parser.Variable - sum := big.NewRat(0, 1) - - for i, allottedItem := range destination.Items { - isLast := i == len(destination.Items)-1 - - switch allotment := allottedItem.Allotment.(type) { - case *parser.Variable: - variableLiterals = append(variableLiterals, *allotment) - res.checkExpression(allotment, TypePortion) - case *parser.RatioLiteral: - sum.Add(sum, allotment.ToRatio()) - case *parser.RemainingAllotment: - if isLast { - remainingAllotment = allotment - } else { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: destination.Range, - Kind: &RemainingIsNotLast{}, - }) - } - } - - res.checkKeptOrDestination(allottedItem.To) - } - - res.checkHasBadAllotmentSum(*sum, destination.Range, remainingAllotment, variableLiterals) - } -} - -func (res *CheckResult) checkKeptOrDestination(target parser.KeptOrDestination) { - switch target := target.(type) { - case *parser.DestinationTo: - res.checkDestination(target.Destination) - case *parser.DestinationKept: - // nothing to do - } -} - -func (res *CheckResult) checkHasBadAllotmentSum( - sum big.Rat, - rng parser.Range, - remaining *parser.RemainingAllotment, - variableLiterals []parser.Variable, -) { - cmp := sum.Cmp(big.NewRat(1, 1)) - switch cmp { - case 1, -1: - if (cmp == -1 && remaining != nil) || (cmp == -1 && len(variableLiterals) > 1) { - return - } - - if cmp == -1 && len(variableLiterals) == 1 { - var value big.Rat - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: variableLiterals[0].Range, - Kind: &FixedPortionVariable{ - Value: *value.Sub(big.NewRat(1, 1), &sum), - }, - }) - } else { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: rng, - Kind: &BadAllotmentSum{ - Sum: sum, - }, - }) - } - - // sum == 1 - case 0: - for _, varLit := range variableLiterals { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: varLit.Range, - Kind: &FixedPortionVariable{ - Value: *big.NewRat(0, 1), - }, - }) - } - if remaining != nil { - res.Diagnostics = append(res.Diagnostics, Diagnostic{ - Range: remaining.Range, - Kind: &RedundantRemaining{}, - }) - } - } -} - -func (res *CheckResult) withCloneEmptyAccount() func() { - initial := res.emptiedAccount - res.emptiedAccount = make(map[string]struct{}) - for k, v := range initial { - res.emptiedAccount[k] = v - } - return func() { - res.emptiedAccount = initial - } -} - -func (res *CheckResult) withCloneUnboundedAccountInSend() func() { - initial := res.unboundedAccountInSend - res.unboundedAccountInSend = nil - - return func() { - res.unboundedAccountInSend = initial - } -} - -func (res *CheckResult) withCloneUnboundedSend() func() { - initial := res.unboundedSend - res.unboundedSend = false - - return func() { - res.unboundedSend = initial - } -} - -func (res *CheckResult) enterCappedSource() func() { - exitCloneEmptyAccount := res.withCloneEmptyAccount() - exitCloneUnboundeAccountInSend := res.withCloneUnboundedAccountInSend() - exitCloneUnboundedSend := res.withCloneUnboundedSend() - - return func() { - exitCloneEmptyAccount() - exitCloneUnboundeAccountInSend() - exitCloneUnboundedSend() - } -} diff --git a/internal/analysis/check_test.go b/internal/analysis/check_test.go deleted file mode 100644 index f9ff564..0000000 --- a/internal/analysis/check_test.go +++ /dev/null @@ -1,1559 +0,0 @@ -package analysis_test - -import ( - "math/big" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestInvalidType(t *testing.T) { - t.Parallel() - - input := `vars { invalid $my_var } -send [C 10] ( - source = $my_var - destination = $my_var -)` - - res := analysis.CheckSource(input) - require.Lenf(t, res.Diagnostics, 1, "xs: %#v", res.Diagnostics) - - d1 := res.Diagnostics[0] - assert.Equal(t, - parser.Range{ - Start: parser.Position{Character: 7}, - End: parser.Position{Character: 7 + len("invalid")}, - }, - d1.Range, - ) - - assert.Equal(t, - &analysis.InvalidType{Name: "invalid"}, - d1.Kind, - ) -} - -func TestValidType(t *testing.T) { - t.Parallel() - - input := `vars { account $my_var } -send [C 10] ( - source = $my_var - destination = $my_var -)` - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 0) -} - -func TestDuplicateVariable(t *testing.T) { - t.Parallel() - - input := `vars { - account $x - account $y - portion $x -} - send [C 10] ( - source = { $x $y } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 3, Character: 10}, - End: parser.Position{Line: 3, Character: 10 + len("$x")}, - }, - d1.Range, - ) - - assert.Equal(t, - &analysis.DuplicateVariable{Name: "x"}, - d1.Kind, - ) -} - -func TestUnboundVarInSaveAccount(t *testing.T) { - t.Parallel() - - input := `save $unbound_mon from $unbound_acc` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 2) - - assert.Equal(t, - []analysis.Diagnostic{ - { - Kind: &analysis.UnboundVariable{Name: "unbound_mon"}, - Range: parser.RangeOfIndexed(input, "$unbound_mon", 0), - }, - { - Kind: &analysis.UnboundVariable{Name: "unbound_acc"}, - Range: parser.RangeOfIndexed(input, "$unbound_acc", 0), - }, - }, - diagnostics, - ) -} - -func TestUnboundVarInInfixOp(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 10] + $unbound_mon1 ( - source = max [COIN 10] + $unbound_mon2 from @world - destination = @b - ) - ` - - parseResult := parser.Parse(input) - require.Empty(t, parseResult.Errors) - - assert.Equal(t, - []analysis.Diagnostic{ - { - Kind: &analysis.UnboundVariable{Name: "unbound_mon1"}, - Range: parser.RangeOfIndexed(input, "$unbound_mon1", 0), - }, - { - Kind: &analysis.UnboundVariable{Name: "unbound_mon2"}, - Range: parser.RangeOfIndexed(input, "$unbound_mon2", 0), - }, - }, - analysis.CheckProgram(parseResult.Value).Diagnostics, - ) -} - -func TestMismatchedTypeInSave(t *testing.T) { - t.Parallel() - - input := `vars { - string $str - number $n -} - -save $str from $n -` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 2) - - assert.Equal(t, - []analysis.Diagnostic{ - { - Kind: &analysis.TypeMismatch{Expected: "monetary", Got: "string"}, - Range: parser.RangeOfIndexed(input, "$str", 1), - }, - { - Kind: &analysis.TypeMismatch{Expected: "account", Got: "number"}, - Range: parser.RangeOfIndexed(input, "$n", 1), - }, - }, - diagnostics, - ) -} - -func TestUnboundVarInSource(t *testing.T) { - t.Parallel() - - input := `send [C 1] ( - source = { max [C 1] from $unbound_var } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 1, Character: 28}, - End: parser.Position{Line: 1, Character: 28 + len("$unbound_var")}, - }, - d1.Range, - ) - - assert.Equal(t, - &analysis.UnboundVariable{Name: "unbound_var"}, - d1.Kind, - ) -} - -func TestUnboundVarInDest(t *testing.T) { - t.Parallel() - - input := `send [C 1] ( - source = @src - destination = { - 1/2 to @a - 1/2 to $unbound_var - } -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "expected len to be 1") - - d1 := diagnostics[0] - assert.Equal(t, - parser.RangeOfIndexed(input, "$unbound_var", 0), - d1.Range, - ) - assert.Equal(t, - &analysis.UnboundVariable{Name: "unbound_var"}, - d1.Kind, - ) -} - -func TestUnboundMany(t *testing.T) { - t.Parallel() - - input := `send [C 1] ( - source = { - 1/3 from $unbound1 - 2/3 from $unbound2 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 2) -} - -func TestUnboundCurrenciesVars(t *testing.T) { - t.Parallel() - - input := `send $unbound1 ( - source = { - max $unbound2 from @a - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 2) -} - -// TODO unbound vars in declr - -func TestUnusedVarInSource(t *testing.T) { - t.Parallel() - - input := `vars { monetary $unused_var }` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - parser.Range{ - Start: parser.Position{Character: 16}, - End: parser.Position{Character: 16 + len("$unused_var")}, - }, - d1.Range, - ) - - assert.Equal(t, - &analysis.UnusedVar{Name: "unused_var"}, - d1.Kind, - ) -} - -func TestWrongTypeForMonetaryLitAsset(t *testing.T) { - t.Parallel() - - input := `vars { account $a } - -send [$a 100] ( - source = @src - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "asset", - Got: "account", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$a", 1), - d1.Range, - ) -} - -func TestWrongTypeForMonetaryLitNumber(t *testing.T) { - t.Parallel() - - input := `vars { account $n } - -send [EUR/2 $n] ( - source = @src - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "number", - Got: "account", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$n", 1), - d1.Range, - ) -} - -func TestWrongTypeForCap(t *testing.T) { - t.Parallel() - - input := `vars { account $account } - -send [COIN 100] ( - source = max $account from @a - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "monetary", - Got: "account", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$account", 1), - d1.Range, - ) -} - -func TestWrongTypeForSrcAccount(t *testing.T) { - t.Parallel() - - input := `vars { portion $x } - -send [COIN 100] ( - source = $x - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "account", - Got: "portion", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$x", 1), - d1.Range, - ) -} - -func TestWrongTypeForDestAccount(t *testing.T) { - t.Parallel() - - input := `vars { portion $x } - -send [COIN 100] ( - source = @src - destination = $x -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "account", - Got: "portion", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$x", 1), - d1.Range, - ) -} - -func TestWrongTypeForUnboundedAccount(t *testing.T) { - t.Parallel() - - input := `vars { portion $x } - -send [COIN 100] ( - source = $x allowing unbounded overdraft - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "account", - Got: "portion", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$x", 1), - d1.Range, - ) -} - -func TestWrongTypeForBoundedOverdraftCap(t *testing.T) { - t.Parallel() - - input := `vars { portion $x } - -send [COIN 100] ( - source = @x allowing overdraft up to $x - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "monetary", - Got: "portion", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$x", 1), - d1.Range, - ) -} - -func TestWrongTypeForSrcAllotmentPortion(t *testing.T) { - t.Parallel() - - input := `vars { string $p } - -send [COIN 100] ( - source = { - $p from @a - remaining from @b - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "portion", - Got: "string", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$p", 1), - d1.Range, - ) -} - -func TestWrongTypeForDestAllotmentPortion(t *testing.T) { - t.Parallel() - - input := `vars { string $p } - -send [COIN 100] ( - source = @s - destination = { - $p to @a - remaining to @dest - } -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "portion", - Got: "string", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "$p", 1), - d1.Range, - ) -} - -func TestBadRemainingInSource(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 1/2 from @a - remaining from @b - 1/2 from @c - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.RemainingIsNotLast{}, - d1.Kind, - ) - - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 1, Character: 12}, - End: parser.Position{Line: 5, Character: 5}, - }, - d1.Range, - ) - -} - -func TestBadRemainingInDest(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = @a - destination = { - 1/2 from @a - remaining from @b - 1/2 from @c - } -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.RemainingIsNotLast{}, - d1.Kind, - ) - - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 2, Character: 17}, - End: parser.Position{Line: 6, Character: 5}, - }, - d1.Range, - ) - -} - -func TestBadAllotmentSumInSourceLessThanOne(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 1/3 from @s1 - 1/3 from @s2 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "wrong diagnostics len") - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadAllotmentSum{ - Sum: *big.NewRat(2, 3), - }, - d1.Kind, - ) - - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 1, Character: 12}, - End: parser.Position{Line: 4, Character: 5}, - }, - d1.Range, - ) -} - -func TestBadAllotmentSumInSourceMoreThanOne(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 2/3 from @s1 - 2/3 from @s2 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "wrong diagnostics len") - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadAllotmentSum{ - Sum: *big.NewRat(4, 3), - }, - d1.Kind, - ) - - assert.Equal(t, - parser.Range{ - Start: parser.Position{Line: 1, Character: 12}, - End: parser.Position{Line: 4, Character: 5}, - }, - d1.Range, - ) - -} - -func TestBadAllotmentSumInDestinationLessThanOne(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = @src - destination = { - 1/3 to @d1 - 1/3 to @d2 - } -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "wrong diagnostics len") - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadAllotmentSum{ - Sum: *big.NewRat(2, 3), - }, - d1.Kind, - ) -} - -func TestNoAllotmentLt1ErrIfVariable(t *testing.T) { - t.Parallel() - - input := `vars { - portion $portion1 - portion $portion2 -} - -send [COIN 100] ( - source = { - 1/3 from @s1 - 1/3 from @s2 - $portion1 from @s3 - $portion2 from @s4 - } - destination = @d -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 0) -} - -func TestAllotmentGt1ErrIfVariable(t *testing.T) { - t.Parallel() - - input := `vars { - portion $portion1 - portion $portion2 -} - -send [COIN 100] ( - source = @src - destination = { - 2/3 to @d1 - 2/3 to @d2 - $portion1 to @d3 - $portion2 to @d4 - } -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - assert.IsType(t, diagnostics[0].Kind, &analysis.BadAllotmentSum{}) -} - -func TestAllotmentErrOnlyOneVar(t *testing.T) { - t.Parallel() - - input := `vars { portion $portion } - -send [COIN 100] ( - source = { - 2/3 from @s1 - $portion from @s2 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - assert.Equal(t, diagnostics[0], analysis.Diagnostic{ - Kind: &analysis.FixedPortionVariable{ - Value: *big.NewRat(1, 3), - }, - Range: parser.RangeOfIndexed(input, "$portion", 1), - }) -} - -func TestAllotmentErrWhenVarIsZero(t *testing.T) { - t.Parallel() - - input := `vars { - portion $portion1 - portion $portion2 -} - -send [COIN 100] ( - source = { - 2/3 from @s1 - 1/3 from @s2 - $portion1 from @s3 - $portion2 from @s4 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 2) - - assert.Equal(t, diagnostics[0], analysis.Diagnostic{ - Kind: &analysis.FixedPortionVariable{ - Value: *big.NewRat(0, 1), - }, - Range: parser.RangeOfIndexed(input, "$portion1", 1), - }) - - assert.Equal(t, diagnostics[1], analysis.Diagnostic{ - Kind: &analysis.FixedPortionVariable{ - Value: *big.NewRat(0, 1), - }, - Range: parser.RangeOfIndexed(input, "$portion2", 1), - }) -} - -func TestNoBadAllotmentWhenRemaining(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 1/3 from @s1 - 1/3 from @s2 - remaining from @s3 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 0, "wrong diagnostics len") -} - -func TestBadAllotmentWhenRemainingButGt1(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 2/3 from @s1 - 2/3 from @s2 - remaining from @s3 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "wrong diagnostics len") - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadAllotmentSum{ - Sum: *big.NewRat(4, 3), - }, - d1.Kind, - ) -} - -func TestRedundantRemainingWhenSumIsOne(t *testing.T) { - t.Parallel() - - input := `send [COIN 100] ( - source = { - 2/3 from @s1 - 1/3 from @s2 - remaining from @s3 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 1, "wrong diagnostics len") - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.RedundantRemaining{}, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "remaining", 0), - d1.Range, - ) -} - -func TestNoSingleAllotmentVariable(t *testing.T) { - t.Parallel() - - input := `vars { portion $allot } - -send [COIN 100] ( - source = { - $allot from @s1 - remaining from @s2 - } - destination = @dest -)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Lenf(t, diagnostics, 0, "wrong diagnostics len") -} - -func TestCheckNoUnboundFunctionCall(t *testing.T) { - t.Parallel() - - input := `invalid_fn_call()` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.UnknownFunction{Name: "invalid_fn_call"}, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "invalid_fn_call", 0), - d1.Range, - ) -} - -func TestAllowedFnCall(t *testing.T) { - t.Parallel() - - input := `set_tx_meta("for_cone", "true")` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 0) -} - -func TestCheckFnCallTypesWrongType(t *testing.T) { - t.Parallel() - - input := `set_tx_meta(@addr, 42)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "string", - Got: "account", - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, "@addr", 0), - d1.Range, - ) -} - -func TestTooFewFnArgs(t *testing.T) { - t.Parallel() - - input := `set_tx_meta("arg")` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadArity{ - Expected: 2, - Actual: 1, - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, `set_tx_meta("arg")`, 0), - d1.Range, - ) -} - -func TestTooManyFnArgs(t *testing.T) { - t.Parallel() - - input := `set_tx_meta("arg", "ok", 10, 20)` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.BadArity{ - Expected: 2, - Actual: 4, - }, - d1.Kind, - ) - - assert.Equal(t, - parser.RangeOfIndexed(input, `10, 20`, 0), - d1.Range, - ) -} - -func TestCheckTrailingCommaFnCall(t *testing.T) { - t.Parallel() - - input := `set_tx_meta("ciao", 42, 10, )` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) -} - -func TestCheckTypesOriginFn(t *testing.T) { - t.Parallel() - - input := ` - vars { - monetary $mon = meta(42, "str") - } - - send $mon ( - source = @s - destination = @d - ) - ` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "account", - Got: "number", - }, - d1.Kind, - ) -} - -func TestCheckReturnTypeOriginFn(t *testing.T) { - t.Parallel() - - input := ` - vars { - account $mon = balance(@account, EUR/2) - } - - send [EUR/2 100] ( - source = $mon - destination = @d - ) - ` - - program := parser.Parse(input).Value - - diagnostics := analysis.CheckProgram(program).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.TypeMismatch{ - Expected: "monetary", - Got: "account", - }, - d1.Kind, - ) -} - -func TestWorldOverdraft(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 100] ( - source = { - @a - @world allowing unbounded overdraft - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.InvalidWorldOverdraft{}, - d1.Kind, - ) - - assert.Equal(t, d1.Range, parser.RangeOfIndexed(input, "@world", 0)) -} - -func TestForbidAllotmentInSendAll(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 *] ( - source = { - 1/2 from @s1 - remaining from @s2 - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.NoAllotmentInSendAll{}, - d1.Kind, - ) -} - -func TestAllowAllotmentInCappedSendAll(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 *] ( - source = { - max [EUR/2 10] from { - 1/2 from @s1 - remaining from @s2 - } - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestDisallowAllotmentInCappedSendAllOutsideMax(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 *] ( - source = { - max [EUR/2 10] from @a - { - 1/2 from @s1 - remaining from @s2 - } - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - d1 := diagnostics[0] - assert.Equal(t, - &analysis.NoAllotmentInSendAll{}, - d1.Kind, - ) -} - -func TestNoForbidAllotmentInSendAll(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 *] ( - source = @a - destination = @dest - ) - - - send [EUR/2 100] ( - source = { - 1/2 from @s1 - remaining from @s2 - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestForbidUnboundedSrcInSendAll(t *testing.T) { - t.Parallel() - - input := ` - send [GEM *] ( - source = { - @ok - @illegal allowing unbounded overdraft // <- err - } - destination = @b - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.InvalidUnboundedAccount{}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@illegal", 0), - ) -} - -func TestAllowUnboundedSrcInSendAllWhenCapped(t *testing.T) { - t.Parallel() - - input := ` - send [GEM *] ( - source = max [GEM 100] from { - @ok - @illegal allowing unbounded overdraft - } - destination = @b - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestForbidWorldSrcInSendAll(t *testing.T) { - t.Parallel() - - input := ` - send [EUR/2 *] ( - source = @world - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) -} - -func TestForbidEmptiedAccount(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @a - @b - @a // <- err - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.EmptiedAccount{Name: "a"}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@a", 1), - ) -} - -func TestResetEmptiedAccount(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = @a - destination = @dest - ) - - send [COIN 100] ( - source = @a - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestEmptiedAccountInMax(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @emptied - max [COIN 10] from { - @a - @emptied // <- err - @b - } - @c - } - destination = @b - ) - - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.EmptiedAccount{Name: "emptied"}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@emptied", 1), - ) -} - -func TestEmptiedAccountDoNotLeakMaxed(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - max [COIN 10] from @emptied - @emptied - } - destination = @b - ) - - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestDoNotEmptyAccountInMax(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @a - max [COIN 10] from { - @a1 - @emptied - @b1 - @emptied // <- err - } - } - destination = @b - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.EmptiedAccount{Name: "emptied"}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@emptied", 1), - ) -} - -func TestDoNotEmitEmptiedAccountOnAllotment(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - 1/2 from @emptied - 1/2 from @emptied - } - destination = @b - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} - -func TestDoNotAllowExprAfterWorld(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @world - @another - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.UnboundedAccountIsNotLast{}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@another", 0), - ) -} - -func TestAllowWorldInNextExpr(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 1] ( - source = @world - destination = @dest - ) - - send [COIN 1] ( - source = @world - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) - -} - -func TestAllowWorldInMaxedExpr(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 10] ( - source = { - max [COIN 1] from @world - @x - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) - -} - -func TestDoNotAllowExprAfterWorldInsideMaxed(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 10] ( - source = max [COIN 1] from { - @world - @x - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.UnboundedAccountIsNotLast{}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@x", 0), - ) -} - -func TestDoNotAllowExprAfterUnbounded(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @unbounded allowing unbounded overdraft - @another - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Len(t, diagnostics, 1) - - require.Equal(t, - diagnostics[0].Kind, - &analysis.UnboundedAccountIsNotLast{}, - ) - - require.Equal(t, - diagnostics[0].Range, - parser.RangeOfIndexed(input, "@another", 0), - ) -} - -func TestAllowExprAfterBoundedOverdraft(t *testing.T) { - t.Parallel() - - input := ` - send [COIN 100] ( - source = { - @unbounded allowing overdraft up to [COIN 10] - @another - } - destination = @dest - ) - ` - - diagnostics := analysis.CheckSource(input).Diagnostics - require.Empty(t, diagnostics) -} diff --git a/internal/analysis/diagnostic_kind.go b/internal/analysis/diagnostic_kind.go deleted file mode 100644 index 7b875c9..0000000 --- a/internal/analysis/diagnostic_kind.go +++ /dev/null @@ -1,260 +0,0 @@ -package analysis - -import ( - "fmt" - "math/big" - - "github.com/PagoPlus/numscript-wasm/internal/ansi" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -type Severity = byte - -// !important! keep in sync with LSP specs -// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnosticSeverity -const ( - _ Severity = iota - ErrorSeverity - WarningSeverity - Information - Hint -) - -func SeverityToAnsiString(s Severity) string { - switch s { - case ErrorSeverity: - return ansi.ColorRed("Error") - case WarningSeverity: - return ansi.ColorYellow("Warning") - case Information: - return "Info" - case Hint: - return "Hint" - default: - return utils.NonExhaustiveMatchPanic[string](s) - } -} - -type DiagnosticKind interface { - Message() string - Severity() Severity -} - -// ###### Diagnostics - -type Parsing struct { - Description string -} - -func (e *Parsing) Message() string { - return e.Description -} - -func (*Parsing) Severity() Severity { - return ErrorSeverity -} - -type InvalidType struct { - Name string -} - -// TODO evaluate suggestion using Levenshtein distance -func (e *InvalidType) Message() string { - allowedTypeList := "" - for index, t := range AllowedTypes { - if index != 0 { - allowedTypeList += ", " - } - allowedTypeList += t - } - - return fmt.Sprintf("'%s' is not a valid type. Allowed types are: %s", e.Name, allowedTypeList) -} - -func (*InvalidType) Severity() Severity { - return ErrorSeverity -} - -type DuplicateVariable struct { - Name string -} - -func (e *DuplicateVariable) Message() string { - return fmt.Sprintf("A variable with the name '$%s' was already declared", e.Name) -} - -func (*DuplicateVariable) Severity() Severity { - return ErrorSeverity -} - -type UnboundVariable struct { - Name string -} - -// TODO evaluate suggestion using Levenshtein distance -func (e *UnboundVariable) Message() string { - return fmt.Sprintf("The variable '$%s' was not declared", e.Name) -} - -func (*UnboundVariable) Severity() Severity { - return ErrorSeverity -} - -type UnusedVar struct { - Name string -} - -func (e *UnusedVar) Message() string { - return fmt.Sprintf("The variable '$%s' is never used", e.Name) -} - -func (*UnusedVar) Severity() Severity { - return WarningSeverity -} - -type TypeMismatch struct { - Expected string - Got string -} - -func (e *TypeMismatch) Message() string { - return fmt.Sprintf("Type mismatch (expected '%s', got '%s' instead)", e.Expected, e.Got) -} - -func (*TypeMismatch) Severity() Severity { - return ErrorSeverity -} - -type RemainingIsNotLast struct{} - -func (e *RemainingIsNotLast) Message() string { - return "A 'remaining' clause should be the last in an allotment expression" -} -func (*RemainingIsNotLast) Severity() Severity { - return ErrorSeverity -} - -type BadAllotmentSum struct { - Sum big.Rat -} - -func (e *BadAllotmentSum) Message() string { - one := big.NewRat(1, 1) - - switch e.Sum.Cmp(one) { - // sum > 1 - case 1: - return fmt.Sprintf("Allotment portions are greater than one (Got %s)", e.Sum.String()) - - // sum < 1 - case -1: - return fmt.Sprintf("Allotment portions are lesser than one (Got %s). Maybe try adding a 'remaining' clause?", e.Sum.String()) - } - - panic(fmt.Sprintf("unreachable state: allotment=%s", e.Sum.String())) -} -func (*BadAllotmentSum) Severity() Severity { - return ErrorSeverity -} - -type FixedPortionVariable struct { - Value big.Rat -} - -func (e *FixedPortionVariable) Message() string { - return fmt.Sprintf("This variable always has the same value (%s)", e.Value.String()) -} -func (*FixedPortionVariable) Severity() Severity { - return WarningSeverity -} - -type RedundantRemaining struct{} - -func (e *RedundantRemaining) Message() string { - return "Redundant 'remaining' clause (allotment already sums to 1)" -} -func (*RedundantRemaining) Severity() Severity { - return WarningSeverity -} - -type UnknownFunction struct { - Name string -} - -func (e *UnknownFunction) Message() string { - res, exists := Builtins[e.Name] - if exists { - return fmt.Sprintf("You cannot use this function here (try to use it in a %s context)", res.ContextName()) - } - // TODO suggest alternatives using Levenshtein distance - return fmt.Sprintf("The function '%s' does not exist", e.Name) -} - -func (*UnknownFunction) Severity() Severity { - return ErrorSeverity -} - -type BadArity struct { - Expected int - Actual int -} - -func (e *BadArity) Message() string { - return fmt.Sprintf("Wrong number of arguments (expected %d, got %d instead)", e.Expected, e.Actual) -} - -func (*BadArity) Severity() Severity { - return ErrorSeverity -} - -type InvalidWorldOverdraft struct{} - -func (e *InvalidWorldOverdraft) Message() string { - return "@world is already set to be ovedraft" -} - -func (*InvalidWorldOverdraft) Severity() Severity { - return WarningSeverity -} - -type NoAllotmentInSendAll struct{} - -func (e *NoAllotmentInSendAll) Message() string { - return "Cannot take all balance of an allotment source" -} - -func (*NoAllotmentInSendAll) Severity() Severity { - return WarningSeverity -} - -type InvalidUnboundedAccount struct{} - -func (e *InvalidUnboundedAccount) Message() string { - return "Cannot take all balance of an unbounded source" -} - -func (*InvalidUnboundedAccount) Severity() Severity { - return ErrorSeverity -} - -type EmptiedAccount struct { - Name string -} - -func (e *EmptiedAccount) Message() string { - return fmt.Sprintf("@%s is already empty at this point", e.Name) -} - -func (*EmptiedAccount) Severity() Severity { - return WarningSeverity -} - -type UnboundedAccountIsNotLast struct{} - -func (e *UnboundedAccountIsNotLast) Message() string { - return "Inorder sources after an unbounded overdraft are never reached" -} - -func (*UnboundedAccountIsNotLast) Severity() Severity { - return WarningSeverity -} diff --git a/internal/analysis/document_symbols.go b/internal/analysis/document_symbols.go deleted file mode 100644 index b538989..0000000 --- a/internal/analysis/document_symbols.go +++ /dev/null @@ -1,38 +0,0 @@ -package analysis - -import ( - "github.com/PagoPlus/numscript-wasm/internal/parser" -) - -type DocumentSymbolKind = float64 - -// !important! keep in sync with -// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol -const ( - DocumentSymbolVariable DocumentSymbolKind = 13 -) - -type DocumentSymbol struct { - Name string - Detail string - Range parser.Range - SelectionRange parser.Range - Kind DocumentSymbolKind -} - -// Note: Results are not sorted -func (r *CheckResult) GetSymbols() []DocumentSymbol { - var symbols []DocumentSymbol - for k, v := range r.declaredVars { - symbols = append(symbols, DocumentSymbol{ - Name: k, - Kind: DocumentSymbolVariable, - Detail: v.Type.Name, - Range: v.Name.Range, - SelectionRange: v.Name.Range, - }) - - } - - return symbols -} diff --git a/internal/analysis/document_symbols_test.go b/internal/analysis/document_symbols_test.go deleted file mode 100644 index 5e7b0e6..0000000 --- a/internal/analysis/document_symbols_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package analysis_test - -import ( - "slices" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/stretchr/testify/assert" -) - -func TestDocumentSymbolsWhenEmpty(t *testing.T) { - input := `set_tx_meta(@a, "k", 42)` - - program := parser.Parse(input).Value - checkResult := analysis.CheckProgram(program) - - symbols := checkResult.GetSymbols() - assert.Empty(t, symbols) -} - -func TestDocumentSymbols(t *testing.T) { - input := `vars { - monetary $mon - account $acc - }` - - program := parser.Parse(input).Value - checkResult := analysis.CheckProgram(program) - - symbols := checkResult.GetSymbols() - - assert.Len(t, symbols, 2) - - indexMon := slices.IndexFunc(symbols, func(s analysis.DocumentSymbol) bool { - return s.Name == "mon" - }) - assert.Equal(t, symbols[indexMon], analysis.DocumentSymbol{ - Name: "mon", - Detail: "monetary", - Range: parser.RangeOfIndexed(input, "$mon", 0), - SelectionRange: parser.RangeOfIndexed(input, "$mon", 0), - Kind: analysis.DocumentSymbolVariable, - }) - - indexSrc := slices.IndexFunc(symbols, func(s analysis.DocumentSymbol) bool { - return s.Name == "acc" - }) - assert.Equal(t, symbols[indexSrc], analysis.DocumentSymbol{ - Name: "acc", - Detail: "account", - Range: parser.RangeOfIndexed(input, "$acc", 0), - SelectionRange: parser.RangeOfIndexed(input, "$acc", 0), - Kind: analysis.DocumentSymbolVariable, - }) - -} diff --git a/internal/analysis/goto_definition.go b/internal/analysis/goto_definition.go deleted file mode 100644 index 630dbba..0000000 --- a/internal/analysis/goto_definition.go +++ /dev/null @@ -1,24 +0,0 @@ -package analysis - -import "github.com/PagoPlus/numscript-wasm/internal/parser" - -type GotoDefinitionResult struct { - Range parser.Range -} - -func GotoDefinition(program parser.Program, position parser.Position, checkResult CheckResult) *GotoDefinitionResult { - hover := HoverOn(program, position) - - if variableHover, ok := hover.(*VariableHover); ok { - resolvedVar := checkResult.ResolveVar(variableHover.Node) - if resolvedVar == nil { - return nil - } - - return &GotoDefinitionResult{ - Range: resolvedVar.Name.Range, - } - } - - return nil -} diff --git a/internal/analysis/goto_definition_test.go b/internal/analysis/goto_definition_test.go deleted file mode 100644 index 5954935..0000000 --- a/internal/analysis/goto_definition_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package analysis_test - -import ( - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestGotoDefinitionOnSendMonetaryVar(t *testing.T) { - input := `vars { monetary $amt } - -send $amt ( - source = @a - destination = @b -)` - - rng := parser.RangeOfIndexed(input, "$amt", 1) - - program := parser.Parse(input).Value - checkResult := analysis.CheckProgram(program) - - res := analysis.GotoDefinition(program, rng.Start, checkResult) - require.NotNil(t, res) - - assert.Equal(t, &analysis.GotoDefinitionResult{ - Range: parser.RangeOfIndexed(input, "$amt", 0), - }, res) - -} - -func TestGotoDefinitionOnNotFound(t *testing.T) { - input := `send $amt ( - source = @a - destination = @b -)` - - rng := parser.RangeOfIndexed(input, "$amt", 0) - - program := parser.Parse(input).Value - checkResult := analysis.CheckProgram(program) - - res := analysis.GotoDefinition(program, rng.Start, checkResult) - assert.Nil(t, res) -} diff --git a/internal/analysis/hover.go b/internal/analysis/hover.go deleted file mode 100644 index e751eb3..0000000 --- a/internal/analysis/hover.go +++ /dev/null @@ -1,347 +0,0 @@ -package analysis - -import ( - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -type Hover interface{ hover() } - -type VariableHover struct { - Range parser.Range - Node *parser.Variable -} - -func (*VariableHover) hover() {} - -type BuiltinFnHoverContext = uint - -const ( - OriginContext BuiltinFnHoverContext = iota - StatementContext -) - -type BuiltinFnHover struct { - Range parser.Range - Node *parser.FnCall - Context BuiltinFnHoverContext -} - -func (*BuiltinFnHover) hover() {} - -func HoverOn(program parser.Program, position parser.Position) Hover { - for _, varDecl := range program.Vars { - hover := hoverOnVar(varDecl, position) - if hover != nil { - return hover - } - } - - for _, statement := range program.Statements { - // TODO binary search into statements - if statement == nil || !statement.GetRange().Contains(position) { - continue - } - - switch statement := statement.(type) { - case *parser.SendStatement: - hover := hoverOnSendStatement(*statement, position) - if hover != nil { - return hover - } - - case *parser.SaveStatement: - hover := hoverOnSaveStatement(*statement, position) - if hover != nil { - return hover - } - - case *parser.FnCall: - hover := hoverOnFnCall(*statement, position) - if hover != nil { - return hover - } - } - - } - return nil -} - -func hoverOnVar(varDecl parser.VarDeclaration, position parser.Position) Hover { - if !varDecl.Range.Contains(position) { - return nil - } - - if varDecl.Origin != nil { - hover := hoverOnFnCall(*varDecl.Origin, position) - if hover != nil { - return hover - } - } - - return nil -} - -func hoverOnSentValue(sentValue parser.SentValue, position parser.Position) Hover { - switch sentValue := sentValue.(type) { - case nil: - return nil - - case *parser.SentValueAll: - return hoverOnExpression(sentValue.Asset, position) - - case *parser.SentValueLiteral: - return hoverOnExpression(sentValue.Monetary, position) - - default: - return utils.NonExhaustiveMatchPanic[Hover](sentValue) - } -} - -func hoverOnSaveStatement(saveStatement parser.SaveStatement, position parser.Position) Hover { - if !saveStatement.Range.Contains(position) { - return nil - } - - hover := hoverOnSentValue(saveStatement.SentValue, position) - if hover != nil { - return hover - } - - hover = hoverOnExpression(saveStatement.Amount, position) - if hover != nil { - return hover - } - - return nil -} - -func hoverOnSendStatement(sendStatement parser.SendStatement, position parser.Position) Hover { - if !sendStatement.Range.Contains(position) { - return nil - } - - hover := hoverOnSentValue(sendStatement.SentValue, position) - if hover != nil { - return hover - } - - hover = hoverOnSource(sendStatement.Source, position) - if hover != nil { - return hover - } - - hover = hoverOnDestination(sendStatement.Destination, position) - if hover != nil { - return hover - } - - return nil -} - -func hoverOnExpression(lit parser.ValueExpr, position parser.Position) Hover { - if lit == nil || !lit.GetRange().Contains(position) { - return nil - } - - switch lit := lit.(type) { - case *parser.Variable: - return &VariableHover{ - Range: lit.Range, - Node: lit, - } - case *parser.MonetaryLiteral: - hover := hoverOnExpression(lit.Amount, position) - if hover != nil { - return hover - } - - hover = hoverOnExpression(lit.Asset, position) - if hover != nil { - return hover - } - case *parser.BinaryInfix: - hover := hoverOnExpression(lit.Left, position) - if hover != nil { - return hover - } - - hover = hoverOnExpression(lit.Right, position) - if hover != nil { - return hover - } - - } - - return nil -} - -func hoverOnSource(source parser.Source, position parser.Position) Hover { - if source == nil || !source.GetRange().Contains(position) { - return nil - } - - switch source := source.(type) { - case *parser.SourceCapped: - hover := hoverOnExpression(source.Cap, position) - if hover != nil { - return hover - } - hover = hoverOnSource(source.From, position) - if hover != nil { - return hover - } - return nil - - case *parser.SourceOverdraft: - hover := hoverOnExpression(source.Address, position) - if hover != nil { - return hover - } - - if source.Bounded != nil { - hover := hoverOnExpression(*source.Bounded, position) - if hover != nil { - return hover - } - } - - return nil - - case *parser.SourceInorder: - for _, source := range source.Sources { - // TODO binary search - if source == nil || !source.GetRange().Contains(position) { - continue - } - - hover := hoverOnSource(source, position) - if hover != nil { - return hover - } - } - - case *parser.SourceAllotment: - for _, item := range source.Items { - // TODO binary search - if !item.Range.Contains(position) { - continue - } - - switch allot := item.Allotment.(type) { - case parser.ValueExpr: - hover := hoverOnExpression(allot, position) - if hover != nil { - return hover - } - } - - hover := hoverOnSource(item.From, position) - if hover != nil { - return hover - } - } - - case *parser.SourceAccount: - return hoverOnExpression(source.ValueExpr, position) - } - - return nil - -} - -func hoverOnKeptOrDestination(inorderClause parser.KeptOrDestination, position parser.Position) Hover { - switch inorderClause := inorderClause.(type) { - case nil, *parser.DestinationKept: - return nil - - case *parser.DestinationTo: - return hoverOnDestination(inorderClause.Destination, position) - - default: - return utils.NonExhaustiveMatchPanic[Hover](inorderClause) - } - -} - -func hoverOnDestination(destination parser.Destination, position parser.Position) Hover { - if destination == nil || !destination.GetRange().Contains(position) { - return nil - } - - switch source := destination.(type) { - case *parser.DestinationInorder: - for _, inorderClause := range source.Clauses { - // TODO binary search - if !inorderClause.Range.Contains(position) { - continue - } - - hover := hoverOnExpression(inorderClause.Cap, position) - if hover != nil { - return hover - } - - hover = hoverOnKeptOrDestination(inorderClause.To, position) - if hover != nil { - return hover - } - } - - hover := hoverOnKeptOrDestination(source.Remaining, position) - if hover != nil { - return hover - } - - case *parser.DestinationAllotment: - for _, item := range source.Items { - // TODO binary search - if !item.Range.Contains(position) { - continue - } - - switch allot := item.Allotment.(type) { - case parser.ValueExpr: - hover := hoverOnExpression(allot, position) - if hover != nil { - return hover - } - } - - hover := hoverOnKeptOrDestination(item.To, position) - if hover != nil { - return hover - } - } - - case *parser.DestinationAccount: - return hoverOnExpression(source.ValueExpr, position) - } - - return nil - -} - -func hoverOnFnCall(callStatement parser.FnCall, position parser.Position) Hover { - if !callStatement.Range.Contains(position) { - return nil - } - - if callStatement.Caller.Range.Contains(position) { - return &BuiltinFnHover{ - Range: callStatement.Caller.Range, - Node: &callStatement, - Context: StatementContext, - } - } - - for _, arg := range callStatement.Args { - hover := hoverOnExpression(arg, position) - if hover != nil { - return hover - } - } - - return nil - -} diff --git a/internal/analysis/hover_test.go b/internal/analysis/hover_test.go deleted file mode 100644 index 8d48fbe..0000000 --- a/internal/analysis/hover_test.go +++ /dev/null @@ -1,462 +0,0 @@ -package analysis_test - -import ( - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/stretchr/testify/require" -) - -func TestHoverOnSendMonetaryVar(t *testing.T) { - input := `vars { monetary $amt } - -send $amt ( - source = @a - destination = @b -)` - - rng := parser.RangeOfIndexed(input, "$amt", 1) - - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.NotNil(t, hover) - - variableHover, ok := hover.(*analysis.VariableHover) - require.True(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnSaveMonetaryVar(t *testing.T) { - input := `vars { monetary $amt } - -save $amt from @acc -` - - rng := parser.RangeOfIndexed(input, "$amt", 1) - - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.NotNil(t, hover) - - variableHover, ok := hover.(*analysis.VariableHover) - require.True(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnAccountVar(t *testing.T) { - input := `vars { account $acc } - -save [COIN 100] from $acc -` - - rng := parser.RangeOfIndexed(input, "$acc", 1) - - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.NotNil(t, hover) - - variableHover, ok := hover.(*analysis.VariableHover) - require.True(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnMonetaryVarAmt(t *testing.T) { - input := `vars { number $amt } - -send [COIN 10] + [COIN $amt] ( - source = @a - destination = @b -)` - - rng := parser.RangeOfIndexed(input, "$amt", 1) - - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.NotNil(t, hover) -} - -func TestHoverOnMonetaryVarAsset(t *testing.T) { - input := `vars { asset $asset } - -send [$asset 100] ( - source = @a - destination = @b -)` - - rng := parser.RangeOfIndexed(input, "$asset", 1) - - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.NotNil(t, hover) -} - -func TestHoverOnSource(t *testing.T) { - input := `vars { account $src } - -send [C 10] ( - source = { - 1/2 from { - @z - max [C 1] from $src - } - 1/2 from @b - } - destination = @dest -)` - - rng := parser.RangeOfIndexed(input, "$src", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNil(t, hover, "hover should not be nil") - - variableHover, ok := hover.(*analysis.VariableHover) - require.True(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnDestinationInorder(t *testing.T) { - input := `vars { account $dest } - -send [C 10] ( - source = @src - destination = { - 1/2 to { - max [C 10] to $dest - remaining to @x - } - 1/2 to @b - } -)` - - rng := parser.RangeOfIndexed(input, "$dest", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") - - variableHover, ok := hover.(*analysis.VariableHover) - require.Truef(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnDestinationInorderRemaining(t *testing.T) { - input := `vars { account $dest } - -send [C 10] ( - source = @src - destination = { - 1/2 to { - max [C 10] to @z - remaining to $dest - } - 1/2 to @b - } -)` - - rng := parser.RangeOfIndexed(input, "$dest", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") - - variableHover, ok := hover.(*analysis.VariableHover) - require.Truef(t, ok, "Expected VariableHover") - - require.Equal(t, rng, variableHover.Range) - - checkResult := analysis.CheckProgram(program) - require.NotNil(t, variableHover.Node) - - resolved := checkResult.ResolveVar(variableHover.Node) - require.NotNil(t, resolved) -} - -func TestHoverOnSrcVariableAllotment(t *testing.T) { - input := `vars { portion $portion } - -send [C 10] ( - source = { $portion from @a } - destination = @dest -)` - - rng := parser.RangeOfIndexed(input, "$portion", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnDestVariableAllotment(t *testing.T) { - input := `vars { portion $portion } - -send [C 10] ( - source = @s - destination = { $portion to @a } -)` - - rng := parser.RangeOfIndexed(input, "$portion", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnUnboundSrc(t *testing.T) { - input := `vars { account $acc } - -send [C 10] ( - source = $acc allowing unbounded overdraft - destination = @dest -)` - - rng := parser.RangeOfIndexed(input, "$acc", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnBoundedCap(t *testing.T) { - input := `vars { monetary $mon } - -send [C 10] ( - source = @s allowing overdraft up to $mon - destination = @dest -)` - - rng := parser.RangeOfIndexed(input, "$mon", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnFnCall(t *testing.T) { - input := `vars { string $str } -set_tx_meta($str, 42) -` - - rng := parser.RangeOfIndexed(input, "$str", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnOriginFnCall(t *testing.T) { - input := `vars { - string $arg - number $meta_variable = meta(@account, $arg) - }` - - rng := parser.RangeOfIndexed(input, "$arg", 1) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") -} - -func TestHoverOnFnCallDocs(t *testing.T) { - input := `set_tx_meta()` - - rng := parser.RangeOfIndexed(input, "set_tx_meta", 0) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") - - fnHover, ok := hover.(*analysis.BuiltinFnHover) - if !ok { - t.Fatalf("Expected a BuiltinFnHover") - } - - require.Equal(t, fnHover.Range, rng) - require.NotNil(t, fnHover.Node) - require.Equal(t, "set_tx_meta", fnHover.Node.Caller.Name) -} - -func TestHoverOnFnOriginDocs(t *testing.T) { - input := `vars { monetary $m = balance(@a, COIN) }` - - rng := parser.RangeOfIndexed(input, "balance", 0) - - program := parser.Parse(input).Value - - hover := analysis.HoverOn(program, rng.Start) - - require.NotNilf(t, hover, "hover should not be nil") - - fnHover, ok := hover.(*analysis.BuiltinFnHover) - if !ok { - t.Fatalf("Expected a BuiltinFnHover") - } - - require.Equal(t, fnHover.Range, rng) - require.NotNil(t, fnHover.Node) - require.Equal(t, "balance", fnHover.Node.Caller.Name) - - res := analysis.CheckProgram(program) - resolution := res.ResolveBuiltinFn(fnHover.Node.Caller) - require.NotNil(t, resolution) - - resolution, ok = resolution.(analysis.VarOriginFnCallResolution) - if !ok { - t.Fatalf("Expected a VarOriginFnCallResolution (got %v)", resolution) - } - -} - -func TestHoverFaultTolerance(t *testing.T) { - t.Run("missing lit", func(t *testing.T) { - input := ` - send [COIN 10] ( - source = max from @a - destination = @a - ) - ` - - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("missing source", func(t *testing.T) { - input := ` - send [COIN 10] ( - source = - destination = @a - ) - ` - - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("missing source in inorder", func(t *testing.T) { - input := ` - send [COIN 10] ( - source = { - @a - - } - destination = @a - ) - ` - - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("missing dest", func(t *testing.T) { - input := ` - send [COIN 10] ( - source = @a - destination = - ) - ` - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("invalid call arg", func(t *testing.T) { - input := ` - set_tx_meta() - ` - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("missing sent value", func(t *testing.T) { - input := ` - send ( - ) - ` - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) - - t.Run("missing inorder clause", func(t *testing.T) { - input := ` - send [COIN 10] ( - source = @a - destination = { - - remaining to - } - ) - ` - rng := parser.RangeOfIndexed(input, "", 0) - program := parser.Parse(input).Value - hover := analysis.HoverOn(program, rng.Start) - require.Nil(t, hover) - }) -} diff --git a/internal/ansi/ansi.go b/internal/ansi/ansi.go deleted file mode 100644 index 77eb617..0000000 --- a/internal/ansi/ansi.go +++ /dev/null @@ -1,22 +0,0 @@ -package ansi - -import "fmt" - -const resetCol = "\033[0m" - -func col(s string, code int) string { - c := fmt.Sprintf("\033[%dm", code) - return c + s + resetCol -} - -func ColorRed(s string) string { - return col(s, 31) -} - -func ColorYellow(s string) string { - return col(s, 33) -} - -func ColorCyan(s string) string { - return col(s, 36) -} diff --git a/internal/cmd/check.go b/internal/cmd/check.go deleted file mode 100644 index c90d432..0000000 --- a/internal/cmd/check.go +++ /dev/null @@ -1,66 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - "sort" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - - "github.com/spf13/cobra" -) - -func check(path string) { - dat, err := os.ReadFile(path) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - return - } - - res := analysis.CheckSource(string(dat)) - sort.Slice(res.Diagnostics, func(i, j int) bool { - p1 := res.Diagnostics[i].Range.Start - p2 := res.Diagnostics[j].Range.Start - - return p2.GtEq(p1) - }) - - for i, d := range res.Diagnostics { - if i != 0 { - fmt.Print("\n\n") - } - errType := analysis.SeverityToAnsiString(d.Kind.Severity()) - fmt.Printf("%s:%d:%d - %s\n%s\n", path, d.Range.Start.Line, d.Range.Start.Character, errType, d.Kind.Message()) - } - - if len(res.Diagnostics) != 0 { - fmt.Printf("\n\n") - } - - errorsCount := res.GetErrorsCount() - if errorsCount != 0 { - - var pluralizedError string - if errorsCount == 1 { - pluralizedError = "error" - } else { - pluralizedError = "errors" - - } - - fmt.Printf("\033[31mFound %d %s\033[0m\n", errorsCount, pluralizedError) - os.Exit(1) - } - - fmt.Printf("No errors found ✅\n") -} - -var checkCmd = &cobra.Command{ - Use: "check ", - Short: "Check a numscript file", - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - path := args[0] - check(path) - }, -} diff --git a/internal/cmd/lsp.go b/internal/cmd/lsp.go deleted file mode 100644 index 3aa72a5..0000000 --- a/internal/cmd/lsp.go +++ /dev/null @@ -1,20 +0,0 @@ -package cmd - -import ( - "github.com/PagoPlus/numscript-wasm/internal/lsp" - - "github.com/spf13/cobra" -) - -var lspCmd = &cobra.Command{ - Use: "lsp", - Short: "Run the lsp server", - Long: "Run the lsp server. This command is usually meant to be used for editors integration.", - Hidden: true, - Run: func(cmd *cobra.Command, args []string) { - lsp.RunServer(lsp.ServerArgs[lsp.State]{ - InitialState: lsp.InitialState(), - Handler: lsp.Handle, - }) - }, -} diff --git a/internal/cmd/root.go b/internal/cmd/root.go deleted file mode 100644 index b19ff0f..0000000 --- a/internal/cmd/root.go +++ /dev/null @@ -1,34 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" -) - -type CliOptions struct { - Version string -} - -var rootCmd = &cobra.Command{ - Use: "numscript", - Short: "Numscript cli", - Long: "Numscript cli", - CompletionOptions: cobra.CompletionOptions{ - DisableDefaultCmd: true, - }, -} - -func Execute(options CliOptions) { - rootCmd.Version = options.Version - - rootCmd.AddCommand(lspCmd) - rootCmd.AddCommand(checkCmd) - rootCmd.AddCommand(getRunCmd()) - - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/internal/cmd/run.go b/internal/cmd/run.go deleted file mode 100644 index f37c24f..0000000 --- a/internal/cmd/run.go +++ /dev/null @@ -1,199 +0,0 @@ -package cmd - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - - "github.com/PagoPlus/numscript-wasm/internal/ansi" - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/spf13/cobra" -) - -const ( - OutputFormatPretty = "pretty" - OutputFormatJson = "json" -) - -var runVariablesOpt string -var runBalancesOpt string -var runMetaOpt string -var runRawOpt string -var runStdinFlag bool -var runOutFormatOpt string - -type inputOpts struct { - Script string `json:"script"` - Variables map[string]string `json:"variables"` - Meta interpreter.AccountsMetadata `json:"metadata"` - Balances interpreter.Balances `json:"balances"` -} - -func (o *inputOpts) fromRaw() { - if runRawOpt == "" { - return - } - - err := json.Unmarshal([]byte(runRawOpt), o) - if err != nil { - panic(err) - } -} - -func (o *inputOpts) fromStdin() { - if !runStdinFlag { - return - } - - bytes, err := io.ReadAll(os.Stdin) - if err != nil { - panic(err) - } - - err = json.Unmarshal(bytes, o) - if err != nil { - panic(err) - } -} - -func (o *inputOpts) fromOptions(path string) { - if path != "" { - numscriptContent, err := os.ReadFile(path) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - return - } - o.Script = string(numscriptContent) - } - - if runBalancesOpt != "" { - content, err := os.ReadFile(runBalancesOpt) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - return - } - json.Unmarshal(content, &o.Balances) - } - - if runMetaOpt != "" { - content, err := os.ReadFile(runMetaOpt) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - return - } - json.Unmarshal(content, &o.Meta) - } - - if runVariablesOpt != "" { - content, err := os.ReadFile(runVariablesOpt) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - return - } - json.Unmarshal(content, &o.Variables) - } -} - -func run(path string) { - opt := inputOpts{ - Variables: make(map[string]string), - Meta: make(interpreter.AccountsMetadata), - Balances: make(interpreter.Balances), - } - - opt.fromRaw() - opt.fromOptions(path) - opt.fromStdin() - - parseResult := parser.Parse(opt.Script) - if len(parseResult.Errors) != 0 { - os.Stderr.Write([]byte(parser.ParseErrorsToString(parseResult.Errors, opt.Script))) - os.Exit(1) - } - - result, err := interpreter.RunProgram(context.Background(), parseResult.Value, opt.Variables, interpreter.StaticStore{ - Balances: opt.Balances, - Meta: opt.Meta, - }, nil) - - if err != nil { - rng := err.GetRange() - os.Stderr.Write([]byte(err.Error())) - if rng.Start != rng.End { - os.Stderr.Write([]byte("\n")) - os.Stderr.Write([]byte(err.GetRange().ShowOnSource(parseResult.Source))) - } - os.Exit(1) - return - } - - switch runOutFormatOpt { - case OutputFormatJson: - showJson(result) - case OutputFormatPretty: - showPretty(result) - default: - // TODO handle err - panic("Invalid option: " + runBalancesOpt) - } - -} - -func showJson(result *interpreter.ExecutionResult) { - out, err := json.Marshal(result) - if err != nil { - // TODO handle err - panic(err) - } - - os.Stdout.Write(out) -} - -func showPretty(result *interpreter.ExecutionResult) { - fmt.Println(ansi.ColorCyan("Postings:")) - postingsJson, err := json.MarshalIndent(result.Postings, "", " ") - if err != nil { - panic(err) - } - fmt.Println(string(postingsJson)) - - fmt.Println() - - fmt.Println(ansi.ColorCyan("Meta:")) - txMetaJson, err := json.MarshalIndent(result.Metadata, "", " ") - if err != nil { - panic(err) - } - fmt.Println(string(txMetaJson)) -} - -func getRunCmd() *cobra.Command { - cmd := cobra.Command{ - Use: "run", - Short: "Evaluate a numscript file", - Long: "Evaluate a numscript file, using the balances, the current metadata and the variables values as input.", - Run: func(cmd *cobra.Command, args []string) { - var path string - if len(args) > 0 { - path = args[0] - } - run(path) - }, - } - - // Input args - cmd.Flags().StringVarP(&runVariablesOpt, "variables", "v", "", "Path of a json file containing the variables") - cmd.Flags().StringVarP(&runBalancesOpt, "balances", "b", "", "Path of a json file containing the balances") - cmd.Flags().StringVarP(&runMetaOpt, "meta", "m", "", "Path of a json file containing the accounts metadata") - cmd.Flags().StringVarP(&runRawOpt, "raw", "r", "", "Raw json input containing script, variables, balances, metadata") - cmd.Flags().BoolVar(&runStdinFlag, "stdin", false, "Take input from stdin (same format as the --raw option)") - - // Output options - cmd.Flags().StringVar(&runOutFormatOpt, "output-format", OutputFormatPretty, "Set the output format. Available options: pretty, json.") - - return &cmd -} diff --git a/internal/interpreter/__snapshots__/interpreter_errors_test.snap b/internal/interpreter/__snapshots__/interpreter_errors_test.snap deleted file mode 100755 index 32e7b99..0000000 --- a/internal/interpreter/__snapshots__/interpreter_errors_test.snap +++ /dev/null @@ -1,75 +0,0 @@ - -[TestShowUnboundVar - 1] - 0 | send [COIN 10] ( - 1 | source = $unbound_var - | ~~~~~~~~~~~~ - 2 | destination = @dest - ---- - -[TestShowMissingFundsSingleAccount - 1] - 0 | send [COIN 10] ( - 1 | source = @a - | ~~ - 2 | destination = @dest - ---- - -[TestShowMissingFundsInorder - 1] - 0 | send [COIN 10] ( - 1 | source = { - | ~ - 2 | @a - | ~~~~~~ - 3 | @b - | ~~~~~~ - 4 | } - | ~~ - 5 | destination = @dest - ---- - -[TestShowMissingFundsAllotment - 1] - 1 | source = { - 2 | 1/2 from @a - | ~~ - 3 | remaining from @world - ---- - -[TestShowMissingFundsMax - 1] - 0 | send [COIN 10] ( - 1 | source = max [COIN 2] from { - | ~~~~~~~~~~~~~~~~~~~ - 2 | 1/2 from @world - | ~~~~~~~~~~~~~~~~~~~ - 3 | remaining from @world - | ~~~~~~~~~~~~~~~~~~~~~~~~~ - 4 | } - | ~~~ - 5 | destination = @dest - ---- - -[TestShowMetadataNotFound - 1] - 0 | vars { - 1 | number $my_var = meta(@acc, "key") - | ~~~~~~~~~~~~~~~~~ - 2 | } - ---- - -[TestShowTypeError - 1] - 0 | send 42 ( - | ~~ - 1 | source = @a - ---- - -[TestShowInvalidTypeErr - 1] - 0 | vars { - 1 | invalid_t $x - | ~~~~~~~~~ - 2 | } - ---- diff --git a/internal/interpreter/args_parser.go b/internal/interpreter/args_parser.go deleted file mode 100644 index 7ba0cd8..0000000 --- a/internal/interpreter/args_parser.go +++ /dev/null @@ -1,43 +0,0 @@ -package interpreter - -import "github.com/PagoPlus/numscript-wasm/internal/parser" - -type argsParser struct { - parsedArgsCount int - args []Value - err InterpreterError -} - -func NewArgsParser(args []Value) *argsParser { - return &argsParser{ - args: args, - } -} - -func parseArg[T any](p *argsParser, r parser.Range, expect func(Value, parser.Range) (*T, InterpreterError)) *T { - index := p.parsedArgsCount - p.parsedArgsCount++ - - if p.err != nil || index >= len(p.args) { - return nil - } - - arg := p.args[index] - parsed, err := expect(arg, r) - if err != nil { - p.err = err - return nil - } - return parsed -} - -func (p *argsParser) parse() InterpreterError { - if len(p.args) != p.parsedArgsCount { - p.err = BadArityErr{ - ExpectedArity: p.parsedArgsCount, - GivenArguments: len(p.args), - } - } - - return p.err -} diff --git a/internal/interpreter/args_parser_test.go b/internal/interpreter/args_parser_test.go deleted file mode 100644 index 17d0d64..0000000 --- a/internal/interpreter/args_parser_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package interpreter - -import ( - "math/big" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/stretchr/testify/require" -) - -func TestParseEmptyArgsValidArity(t *testing.T) { - t.Parallel() - - p := NewArgsParser([]Value{}) - err := p.parse() - require.Nil(t, err) -} - -func TestParseInvalidArity(t *testing.T) { - t.Parallel() - - p := NewArgsParser([]Value{}) - parseArg(p, parser.Range{}, expectAccount) - parseArg(p, parser.Range{}, expectAsset) - - err := p.parse() - - require.Equal(t, err, BadArityErr{ - ExpectedArity: 2, - GivenArguments: 0, - }) -} - -func TestParseValid(t *testing.T) { - t.Parallel() - - p := NewArgsParser([]Value{ - NewMonetaryInt(42), - AccountAddress("user:001"), - }) - a1 := parseArg(p, parser.Range{}, expectNumber) - a2 := parseArg(p, parser.Range{}, expectAccount) - err := p.parse() - - require.Nil(t, err) - - require.NotNil(t, a1, "a1 should not be nil") - require.NotNil(t, a2, "a2 should not be nil") - - require.Equal(t, *a1, *big.NewInt(42)) - require.Equal(t, *a2, "user:001") -} - -func TestParseBadType(t *testing.T) { - t.Parallel() - - p := NewArgsParser([]Value{ - NewMonetaryInt(42), - AccountAddress("user:001"), - }) - parseArg(p, parser.Range{}, expectMonetary) - parseArg(p, parser.Range{}, expectAccount) - err := p.parse() - - require.Equal(t, err, TypeError{ - Expected: "monetary", - Value: NewMonetaryInt(42), - }) -} diff --git a/internal/interpreter/batch_balances_query.go b/internal/interpreter/batch_balances_query.go deleted file mode 100644 index 8a730a0..0000000 --- a/internal/interpreter/batch_balances_query.go +++ /dev/null @@ -1,148 +0,0 @@ -package interpreter - -import ( - "slices" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" - "golang.org/x/exp/maps" -) - -// traverse the script to batch in advance required balance queries - -func (st *programState) findBalancesQueriesInStatement(statement parser.Statement) InterpreterError { - switch statement := statement.(type) { - case *parser.FnCall: - return nil - - case *parser.SaveStatement: - asset, _, err := st.evaluateSentAmt(statement.SentValue) - if err != nil { - return err - } - - // Although we don't technically need this account's balance rn, - // having access to the balance simplifies the "save" statement implementation - // this means that we would have a needless query in the case in which the account - // which is selected in the "save" statement never actually appears as source - // - // this would mean that the "save" statement was not needed in the first place, - // so preventing this query would hardly be an useful optimization - account, err := evaluateExprAs(st, statement.Amount, expectAccount) - if err != nil { - return err - } - st.batchQuery(*account, *asset) - return nil - - case *parser.SendStatement: - asset, _, err := st.evaluateSentAmt(statement.SentValue) - if err != nil { - return err - } - st.CurrentAsset = *asset - - // traverse source - return st.findBalancesQueries(statement.Source) - - default: - utils.NonExhaustiveMatchPanic[any](statement) - return nil - } -} - -func (st *programState) batchQuery(account string, asset string) { - if account == "world" { - return - } - - previousValues := st.CurrentBalanceQuery[account] - if !slices.Contains[[]string, string](previousValues, asset) { - st.CurrentBalanceQuery[account] = append(previousValues, asset) - } -} - -func (st *programState) runBalancesQuery() error { - filteredQuery := BalanceQuery{} - for accountName, queriedCurrencies := range st.CurrentBalanceQuery { - - cachedCurrenciesForAccount := defaultMapGet(st.CachedBalances, accountName, func() AccountBalance { - return AccountBalance{} - }) - - for _, queriedCurrency := range queriedCurrencies { - isAlreadyCached := slices.Contains(maps.Keys(cachedCurrenciesForAccount), queriedCurrency) - if !isAlreadyCached { - filteredQuery[accountName] = queriedCurrencies - } - } - - } - - // avoid updating balances if we don't need to fetch new data - if len(filteredQuery) == 0 { - return nil - } - - balances, err := st.Store.GetBalances(st.ctx, filteredQuery) - if err != nil { - return err - } - // reset batch query - st.CurrentBalanceQuery = BalanceQuery{} - - st.CachedBalances = balances - return nil -} - -func (st *programState) findBalancesQueries(source parser.Source) InterpreterError { - switch source := source.(type) { - case *parser.SourceAccount: - account, err := evaluateExprAs(st, source.ValueExpr, expectAccount) - if err != nil { - return err - } - - st.batchQuery(*account, st.CurrentAsset) - return nil - - case *parser.SourceOverdraft: - // Skip balance tracking when balance is overdraft - if source.Bounded == nil { - return nil - } - - account, err := evaluateExprAs(st, source.Address, expectAccount) - if err != nil { - return err - } - st.batchQuery(*account, st.CurrentAsset) - return nil - - case *parser.SourceInorder: - for _, subSource := range source.Sources { - err := st.findBalancesQueries(subSource) - if err != nil { - return err - } - } - return nil - - case *parser.SourceCapped: - // TODO can this be optimized in some cases? - return st.findBalancesQueries(source.From) - - case *parser.SourceAllotment: - for _, item := range source.Items { - err := st.findBalancesQueries(item.From) - if err != nil { - return err - } - } - return nil - - default: - utils.NonExhaustiveMatchPanic[error](source) - return nil - } -} diff --git a/internal/interpreter/evaluate_expr.go b/internal/interpreter/evaluate_expr.go deleted file mode 100644 index fac988d..0000000 --- a/internal/interpreter/evaluate_expr.go +++ /dev/null @@ -1,126 +0,0 @@ -package interpreter - -import ( - "math/big" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -func (st *programState) evaluateExpr(expr parser.ValueExpr) (Value, InterpreterError) { - switch expr := expr.(type) { - case *parser.AssetLiteral: - return Asset(expr.Asset), nil - case *parser.AccountLiteral: - return AccountAddress(expr.Name), nil - case *parser.StringLiteral: - return String(expr.String), nil - case *parser.RatioLiteral: - return Portion(*expr.ToRatio()), nil - case *parser.NumberLiteral: - return MonetaryInt(*big.NewInt(int64(expr.Number))), nil - case *parser.MonetaryLiteral: - asset, err := evaluateExprAs(st, expr.Asset, expectAsset) - if err != nil { - return nil, err - } - - amount, err := evaluateExprAs(st, expr.Amount, expectNumber) - if err != nil { - return nil, err - } - - return Monetary{Asset: Asset(*asset), Amount: MonetaryInt(*amount)}, nil - - case *parser.Variable: - value, ok := st.ParsedVars[expr.Name] - if !ok { - return nil, UnboundVariableErr{ - Name: expr.Name, - Range: expr.Range, - } - } - return value, nil - - // TypeError - case *parser.BinaryInfix: - - switch expr.Operator { - case parser.InfixOperatorPlus: - return st.plusOp(expr.Left, expr.Right) - - case parser.InfixOperatorMinus: - return st.subOp(expr.Left, expr.Right) - - default: - utils.NonExhaustiveMatchPanic[any](expr.Operator) - return nil, nil - } - - default: - utils.NonExhaustiveMatchPanic[any](expr) - return nil, nil - } -} - -func evaluateExprAs[T any](st *programState, expr parser.ValueExpr, expect func(Value, parser.Range) (*T, InterpreterError)) (*T, InterpreterError) { - value, err := st.evaluateExpr(expr) - if err != nil { - return nil, err - } - - res, err := expect(value, expr.GetRange()) - if err != nil { - return nil, err - } - - return res, nil -} - -func (st *programState) evaluateExpressions(literals []parser.ValueExpr) ([]Value, InterpreterError) { - var values []Value - for _, argLit := range literals { - value, err := st.evaluateExpr(argLit) - if err != nil { - return nil, err - } - values = append(values, value) - } - return values, nil -} - -func (st *programState) plusOp(left parser.ValueExpr, right parser.ValueExpr) (Value, InterpreterError) { - leftValue, err := evaluateExprAs(st, left, expectOneOf( - expectMapped(expectMonetary, func(m Monetary) opAdd { - return m - }), - - // while "x.map(identity)" is the same as "x", just writing "expectNumber" would't typecheck - expectMapped(expectNumber, func(bi big.Int) opAdd { - return MonetaryInt(bi) - }), - )) - - if err != nil { - return nil, err - } - - return (*leftValue).evalAdd(st, right) -} - -func (st *programState) subOp(left parser.ValueExpr, right parser.ValueExpr) (Value, InterpreterError) { - leftValue, err := evaluateExprAs(st, left, expectOneOf( - expectMapped(expectMonetary, func(m Monetary) opSub { - return m - }), - expectMapped(expectNumber, func(bi big.Int) opSub { - return MonetaryInt(bi) - }), - )) - - if err != nil { - return nil, err - } - - return (*leftValue).evalSub(st, right) -} diff --git a/internal/interpreter/infix.go b/internal/interpreter/infix.go deleted file mode 100644 index b601625..0000000 --- a/internal/interpreter/infix.go +++ /dev/null @@ -1,82 +0,0 @@ -package interpreter - -import ( - "math/big" - - "github.com/PagoPlus/numscript-wasm/internal/parser" -) - -type opAdd interface { - evalAdd(st *programState, other parser.ValueExpr) (Value, InterpreterError) -} - -var _ opAdd = (*MonetaryInt)(nil) -var _ opAdd = (*Monetary)(nil) - -func (m MonetaryInt) evalAdd(st *programState, other parser.ValueExpr) (Value, InterpreterError) { - m1 := big.Int(m) - m2, err := evaluateExprAs(st, other, expectNumber) - if err != nil { - return nil, err - } - - sum := new(big.Int).Add(&m1, m2) - return MonetaryInt(*sum), nil -} - -func (m Monetary) evalAdd(st *programState, other parser.ValueExpr) (Value, InterpreterError) { - m2, err := evaluateExprAs(st, other, expectMonetary) - if err != nil { - return nil, err - } - - if m.Asset != m2.Asset { - return nil, MismatchedCurrencyError{ - Expected: m.Asset.String(), - Got: m2.Asset.String(), - } - } - - return Monetary{ - Asset: m.Asset, - Amount: m.Amount.Add(m2.Amount), - }, nil - -} - -type opSub interface { - evalSub(st *programState, other parser.ValueExpr) (Value, InterpreterError) -} - -var _ opSub = (*MonetaryInt)(nil) -var _ opSub = (*Monetary)(nil) - -func (m MonetaryInt) evalSub(st *programState, other parser.ValueExpr) (Value, InterpreterError) { - m1 := big.Int(m) - m2, err := evaluateExprAs(st, other, expectNumber) - if err != nil { - return nil, err - } - sum := new(big.Int).Sub(&m1, m2) - return MonetaryInt(*sum), nil -} - -func (m Monetary) evalSub(st *programState, other parser.ValueExpr) (Value, InterpreterError) { - m2, err := evaluateExprAs(st, other, expectMonetary) - if err != nil { - return nil, err - } - - if m.Asset != m2.Asset { - return nil, MismatchedCurrencyError{ - Expected: m.Asset.String(), - Got: m2.Asset.String(), - } - } - - return Monetary{ - Asset: m.Asset, - Amount: m.Amount.Sub(m2.Amount), - }, nil - -} diff --git a/internal/interpreter/interpreter.go b/internal/interpreter/interpreter.go deleted file mode 100644 index bb11a89..0000000 --- a/internal/interpreter/interpreter.go +++ /dev/null @@ -1,906 +0,0 @@ -package interpreter - -import ( - "context" - "math/big" - "regexp" - "strings" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -type VariablesMap map[string]string - -// For each account, list of the needed assets -type BalanceQuery map[string][]string - -// For each account, list of the needed keys -type MetadataQuery map[string][]string - -type AccountBalance = map[string]*big.Int -type Balances map[string]AccountBalance - -type AccountMetadata = map[string]string -type AccountsMetadata map[string]AccountMetadata - -type Store interface { - GetBalances(context.Context, BalanceQuery) (Balances, error) - GetAccountsMetadata(context.Context, MetadataQuery) (AccountsMetadata, error) -} - -type StaticStore struct { - Balances Balances - Meta AccountsMetadata -} - -func (s StaticStore) GetBalances(context.Context, BalanceQuery) (Balances, error) { - if s.Balances == nil { - s.Balances = Balances{} - } - return s.Balances, nil -} -func (s StaticStore) GetAccountsMetadata(context.Context, MetadataQuery) (AccountsMetadata, error) { - if s.Meta == nil { - s.Meta = AccountsMetadata{} - } - return s.Meta, nil -} - -type InterpreterError interface { - error - parser.Ranged -} - -type Metadata = map[string]Value - -type ExecutionResult struct { - Postings []Posting `json:"postings"` - - Metadata Metadata `json:"txMeta"` - - AccountsMetadata AccountsMetadata `json:"accountsMeta"` -} - -func parseMonetary(source string) (Monetary, InterpreterError) { - parts := strings.Split(source, " ") - if len(parts) != 2 { - return Monetary{}, InvalidMonetaryLiteral{Source: source} - } - - asset := parts[0] - - rawAmount := parts[1] - n, ok := new(big.Int).SetString(rawAmount, 10) - if !ok { - return Monetary{}, InvalidNumberLiteral{Source: rawAmount} - } - mon := Monetary{ - Asset: Asset(asset), - Amount: MonetaryInt(*n), - } - return mon, nil -} - -func parseVar(type_ string, rawValue string, r parser.Range) (Value, InterpreterError) { - switch type_ { - // TODO why should the runtime depend on the static analysis module? - case analysis.TypeMonetary: - return parseMonetary(rawValue) - case analysis.TypeAccount: - return AccountAddress(rawValue), nil - case analysis.TypePortion: - bi, err := ParsePortionSpecific(rawValue) - if err != nil { - return nil, err - } - - return Portion(*bi), nil - case analysis.TypeAsset: - return Asset(rawValue), nil - case analysis.TypeNumber: - n, ok := new(big.Int).SetString(rawValue, 10) - if !ok { - return nil, InvalidNumberLiteral{Source: rawValue} - } - return MonetaryInt(*n), nil - case analysis.TypeString: - return String(rawValue), nil - default: - return nil, InvalidTypeErr{Name: type_, Range: r} - } - -} - -func (s *programState) handleOrigin(type_ string, fnCall parser.FnCall) (Value, InterpreterError) { - args, err := s.evaluateExpressions(fnCall.Args) - if err != nil { - return nil, err - } - - switch fnCall.Caller.Name { - case analysis.FnVarOriginMeta: - rawValue, err := meta(s, fnCall.Range, args) - if err != nil { - return nil, err - } - - parsed, err := parseVar(type_, rawValue, fnCall.Range) - if err != nil { - return nil, err - } - - return parsed, nil - - case analysis.FnVarOriginBalance: - monetary, err := balance(s, fnCall.Range, args) - if err != nil { - return nil, err - } - return *monetary, nil - - default: - return nil, UnboundFunctionErr{Name: fnCall.Caller.Name} - } - -} - -func (s *programState) parseVars(varDeclrs []parser.VarDeclaration, rawVars map[string]string) InterpreterError { - for _, varsDecl := range varDeclrs { - if varsDecl.Origin == nil { - raw, ok := rawVars[varsDecl.Name.Name] - if !ok { - return MissingVariableErr{Name: varsDecl.Name.Name} - } - - parsed, err := parseVar(varsDecl.Type.Name, raw, varsDecl.Type.Range) - if err != nil { - return err - } - s.ParsedVars[varsDecl.Name.Name] = parsed - } else { - value, err := s.handleOrigin(varsDecl.Type.Name, *varsDecl.Origin) - if err != nil { - return err - } - s.ParsedVars[varsDecl.Name.Name] = value - } - } - return nil -} - -func RunProgram( - ctx context.Context, - program parser.Program, - vars map[string]string, - store Store, - featureFlags map[string]struct{}, -) (*ExecutionResult, InterpreterError) { - st := programState{ - ParsedVars: make(map[string]Value), - TxMeta: make(map[string]Value), - CachedAccountsMeta: AccountsMetadata{}, - CachedBalances: Balances{}, - SetAccountsMeta: AccountsMetadata{}, - Store: store, - - CurrentBalanceQuery: BalanceQuery{}, - ctx: ctx, - } - - err := st.parseVars(program.Vars, vars) - if err != nil { - return nil, err - } - - // preload balances before executing the script - for _, statement := range program.Statements { - err := st.findBalancesQueriesInStatement(statement) - if err != nil { - return nil, err - } - } - - genericErr := st.runBalancesQuery() - if genericErr != nil { - return nil, QueryBalanceError{WrappedError: genericErr} - } - - postings := make([]Posting, 0) - for _, statement := range program.Statements { - statementPostings, err := st.runStatement(statement) - if err != nil { - return nil, err - } - postings = append(postings, statementPostings...) - } - - res := &ExecutionResult{ - Postings: postings, - Metadata: st.TxMeta, - AccountsMetadata: st.SetAccountsMeta, - } - return res, nil -} - -type programState struct { - ctx context.Context - - // Asset of the send statement currently being executed. - // - // it's value is undefined outside of send statements execution - CurrentAsset string - - ParsedVars map[string]Value - TxMeta map[string]Value - Senders []Sender - Receivers []Receiver - - Store Store - - SetAccountsMeta AccountsMetadata - - CachedAccountsMeta AccountsMetadata - CachedBalances Balances - - CurrentBalanceQuery BalanceQuery -} - -func (st *programState) runStatement(statement parser.Statement) ([]Posting, InterpreterError) { - st.Senders = nil - st.Receivers = nil - - switch statement := statement.(type) { - case *parser.FnCall: - args, err := st.evaluateExpressions(statement.Args) - if err != nil { - return nil, err - } - - switch statement.Caller.Name { - case analysis.FnSetTxMeta: - err := setTxMeta(st, statement.Caller.Range, args) - if err != nil { - return nil, err - } - case analysis.FnSetAccountMeta: - err := setAccountMeta(st, statement.Caller.Range, args) - if err != nil { - return nil, err - } - default: - return nil, UnboundFunctionErr{Name: statement.Caller.Name} - } - return nil, nil - - case *parser.SendStatement: - return st.runSendStatement(*statement) - - case *parser.SaveStatement: - return st.runSaveStatement(*statement) - - default: - utils.NonExhaustiveMatchPanic[any](statement) - return nil, nil - } -} - -func (st *programState) getPostings() ([]Posting, InterpreterError) { - postings, err := Reconcile(st.CurrentAsset, st.Senders, st.Receivers) - if err != nil { - return nil, err - } - - for _, posting := range postings { - srcBalance := st.getCachedBalance(posting.Source, posting.Asset) - srcBalance.Sub(srcBalance, posting.Amount) - - destBalance := st.getCachedBalance(posting.Destination, posting.Asset) - destBalance.Add(destBalance, posting.Amount) - } - return postings, nil -} - -func (st *programState) runSaveStatement(saveStatement parser.SaveStatement) ([]Posting, InterpreterError) { - asset, amt, err := st.evaluateSentAmt(saveStatement.SentValue) - if err != nil { - return nil, err - } - - account, err := evaluateExprAs(st, saveStatement.Amount, expectAccount) - if err != nil { - return nil, err - } - - balance := st.getCachedBalance(*account, *asset) - - if amt == nil { - balance.Set(big.NewInt(0)) - } else { - // Do not allow negative saves - if amt.Cmp(big.NewInt(0)) == -1 { - return nil, NegativeAmountErr{ - Range: saveStatement.SentValue.GetRange(), - Amount: MonetaryInt(*amt), - } - } - - // we decrease the balance by "amt" - balance.Sub(balance, amt) - // without going under 0 - if balance.Cmp(big.NewInt(0)) == -1 { - balance.Set(big.NewInt(0)) - } - } - - return nil, nil -} - -func (st *programState) runSendStatement(statement parser.SendStatement) ([]Posting, InterpreterError) { - switch sentValue := statement.SentValue.(type) { - case *parser.SentValueAll: - asset, err := evaluateExprAs(st, sentValue.Asset, expectAsset) - if err != nil { - return nil, err - } - st.CurrentAsset = *asset - sentAmt, err := st.sendAll(statement.Source) - if err != nil { - return nil, err - } - err = st.receiveFrom(statement.Destination, sentAmt) - if err != nil { - return nil, err - } - return st.getPostings() - - case *parser.SentValueLiteral: - monetary, err := evaluateExprAs(st, sentValue.Monetary, expectMonetary) - if err != nil { - return nil, err - } - st.CurrentAsset = string(monetary.Asset) - - monetaryAmt := (*big.Int)(&monetary.Amount) - if monetaryAmt.Cmp(big.NewInt(0)) == -1 { - return nil, NegativeAmountErr{Amount: monetary.Amount} - } - - err = st.trySendingExact(statement.Source, monetaryAmt) - if err != nil { - return nil, err - } - - // TODO simplify pointers - amt := big.Int(monetary.Amount) - err = st.receiveFrom(statement.Destination, &amt) - if err != nil { - return nil, err - } - - return st.getPostings() - default: - utils.NonExhaustiveMatchPanic[any](sentValue) - return nil, nil - } - -} - -func (s *programState) getCachedBalance(account string, asset string) *big.Int { - balance := defaultMapGet(s.CachedBalances, account, func() AccountBalance { - return AccountBalance{} - }) - assetBalance := defaultMapGet(balance, asset, func() *big.Int { - return big.NewInt(0) - }) - return assetBalance -} - -func (s *programState) sendAllToAccount(accountLiteral parser.ValueExpr, ovedraft *big.Int) (*big.Int, InterpreterError) { - account, err := evaluateExprAs(s, accountLiteral, expectAccount) - if err != nil { - return nil, err - } - - if *account == "world" || ovedraft == nil { - return nil, InvalidUnboundedInSendAll{ - Name: *account, - } - } - - balance := s.getCachedBalance(*account, s.CurrentAsset) - - // we sent balance+overdraft - sentAmt := new(big.Int).Add(balance, ovedraft) - s.Senders = append(s.Senders, Sender{ - Name: *account, - Monetary: sentAmt, - }) - return sentAmt, nil -} - -// Send as much as possible (and return the sent amt) -func (s *programState) sendAll(source parser.Source) (*big.Int, InterpreterError) { - switch source := source.(type) { - case *parser.SourceAccount: - return s.sendAllToAccount(source.ValueExpr, big.NewInt(0)) - - case *parser.SourceOverdraft: - var cap *big.Int - if source.Bounded != nil { - bounded, err := evaluateExprAs(s, *source.Bounded, expectMonetaryOfAsset(s.CurrentAsset)) - if err != nil { - return nil, err - } - cap = bounded - } - return s.sendAllToAccount(source.Address, cap) - - case *parser.SourceInorder: - totalSent := big.NewInt(0) - for _, subSource := range source.Sources { - sent, err := s.sendAll(subSource) - if err != nil { - return nil, err - } - totalSent.Add(totalSent, sent) - } - return totalSent, nil - - case *parser.SourceCapped: - monetary, err := evaluateExprAs(s, source.Cap, expectMonetaryOfAsset(s.CurrentAsset)) - if err != nil { - return nil, err - } - if monetary.Cmp(big.NewInt(0)) == -1 { - monetary.Set(big.NewInt(0)) - } - // We switch to the default sending evaluation for this subsource - return s.trySendingUpTo(source.From, monetary) - - case *parser.SourceAllotment: - return nil, InvalidAllotmentInSendAll{} - - default: - utils.NonExhaustiveMatchPanic[error](source) - return nil, nil - } -} - -// Fails if it doesn't manage to send exactly "amount" -func (s *programState) trySendingExact(source parser.Source, amount *big.Int) InterpreterError { - sentAmt, err := s.trySendingUpTo(source, amount) - if err != nil { - return err - } - if sentAmt.Cmp(amount) != 0 { - return MissingFundsErr{ - Asset: s.CurrentAsset, - Needed: *amount, - Available: *sentAmt, - Range: source.GetRange(), - } - } - return nil -} - -func (s *programState) trySendingToAccount(accountLiteral parser.ValueExpr, amount *big.Int, overdraft *big.Int) (*big.Int, InterpreterError) { - account, err := evaluateExprAs(s, accountLiteral, expectAccount) - if err != nil { - return nil, err - } - if *account == "world" { - overdraft = nil - } - - var actuallySentAmt *big.Int - if overdraft == nil { - // unbounded overdraft: we send the required amount - actuallySentAmt = new(big.Int).Set(amount) - } else { - balance := s.getCachedBalance(*account, s.CurrentAsset) - - // that's the amount we are allowed to send (balance + overdraft) - safeSendAmt := new(big.Int).Add(balance, overdraft) - actuallySentAmt = utils.MinBigInt(safeSendAmt, amount) - } - - s.Senders = append(s.Senders, Sender{ - Name: *account, - Monetary: actuallySentAmt, - }) - return actuallySentAmt, nil -} - -// Tries sending "amount" and returns the actually sent amt. -// Doesn't fail (unless nested sources fail) -func (s *programState) trySendingUpTo(source parser.Source, amount *big.Int) (*big.Int, InterpreterError) { - switch source := source.(type) { - case *parser.SourceAccount: - return s.trySendingToAccount(source.ValueExpr, amount, big.NewInt(0)) - - case *parser.SourceOverdraft: - var cap *big.Int - if source.Bounded != nil { - upTo, err := evaluateExprAs(s, *source.Bounded, expectMonetaryOfAsset(s.CurrentAsset)) - if err != nil { - return nil, err - } - cap = upTo - } - return s.trySendingToAccount(source.Address, amount, cap) - - case *parser.SourceInorder: - totalLeft := new(big.Int).Set(amount) - for _, source := range source.Sources { - sentAmt, err := s.trySendingUpTo(source, totalLeft) - if err != nil { - return nil, err - } - totalLeft.Sub(totalLeft, sentAmt) - } - return new(big.Int).Sub(amount, totalLeft), nil - - case *parser.SourceAllotment: - var items []parser.AllotmentValue - for _, i := range source.Items { - items = append(items, i.Allotment) - } - allot, err := s.makeAllotment(amount, items) - if err != nil { - return nil, err - } - for i, allotmentItem := range source.Items { - err := s.trySendingExact(allotmentItem.From, allot[i]) - if err != nil { - return nil, err - } - } - return amount, nil - - case *parser.SourceCapped: - cap, err := evaluateExprAs(s, source.Cap, expectMonetaryOfAsset(s.CurrentAsset)) - if err != nil { - return nil, err - } - cappedAmount := utils.MinBigInt(amount, cap) - if cappedAmount.Cmp(big.NewInt(0)) == -1 { - cappedAmount.Set(big.NewInt(0)) - } - return s.trySendingUpTo(source.From, cappedAmount) - - default: - utils.NonExhaustiveMatchPanic[any](source) - return nil, nil - - } - -} - -func (s *programState) receiveFrom(destination parser.Destination, amount *big.Int) InterpreterError { - switch destination := destination.(type) { - case *parser.DestinationAccount: - account, err := evaluateExprAs(s, destination.ValueExpr, expectAccount) - if err != nil { - return err - } - s.Receivers = append(s.Receivers, Receiver{ - Name: *account, - Monetary: amount, - }) - return nil - - case *parser.DestinationAllotment: - var items []parser.AllotmentValue - for _, i := range destination.Items { - items = append(items, i.Allotment) - } - - allot, err := s.makeAllotment(amount, items) - if err != nil { - return err - } - - receivedTotal := big.NewInt(0) - for i, allotmentItem := range destination.Items { - amtToReceive := allot[i] - err := s.receiveFromKeptOrDest(allotmentItem.To, amtToReceive) - if err != nil { - return err - } - - receivedTotal.Add(receivedTotal, amtToReceive) - } - return nil - - case *parser.DestinationInorder: - remainingAmount := new(big.Int).Set(amount) - - handler := func(keptOrDest parser.KeptOrDestination, amountToReceive *big.Int) InterpreterError { - err := s.receiveFromKeptOrDest(keptOrDest, amountToReceive) - if err != nil { - return err - } - remainingAmount.Sub(remainingAmount, amountToReceive) - return err - } - - for _, destinationClause := range destination.Clauses { - - cap, err := evaluateExprAs(s, destinationClause.Cap, expectMonetaryOfAsset(s.CurrentAsset)) - if err != nil { - return err - } - - // If the remaining amt is zero, let's ignore the posting - if remainingAmount.Cmp(big.NewInt(0)) == 0 { - break - } - - err = handler(destinationClause.To, utils.MinBigInt(cap, remainingAmount)) - if err != nil { - return err - } - - } - - remainingAmountCopy := new(big.Int).Set(remainingAmount) - // passing "remainingAmount" directly breaks the code - return handler(destination.Remaining, remainingAmountCopy) - - default: - utils.NonExhaustiveMatchPanic[any](destination) - return nil - } -} - -func (s *programState) receiveFromKeptOrDest(keptOrDest parser.KeptOrDestination, amount *big.Int) InterpreterError { - switch destinationTarget := keptOrDest.(type) { - case *parser.DestinationKept: - s.Receivers = append(s.Receivers, Receiver{ - Name: "", - Monetary: amount, - }) - return nil - - case *parser.DestinationTo: - return s.receiveFrom(destinationTarget.Destination, amount) - - default: - utils.NonExhaustiveMatchPanic[any](destinationTarget) - return nil - } - -} - -func (s *programState) makeAllotment(monetary *big.Int, items []parser.AllotmentValue) ([]*big.Int, InterpreterError) { - totalAllotment := big.NewRat(0, 1) - var allotments []*big.Rat - - remainingAllotmentIndex := -1 - - for i, item := range items { - switch allotment := item.(type) { - case *parser.RatioLiteral: - rat := allotment.ToRatio() - totalAllotment.Add(totalAllotment, rat) - allotments = append(allotments, rat) - case *parser.Variable: - rat, err := evaluateExprAs(s, allotment, expectPortion) - if err != nil { - return nil, err - } - - totalAllotment.Add(totalAllotment, rat) - allotments = append(allotments, rat) - - case *parser.RemainingAllotment: - remainingAllotmentIndex = i - allotments = append(allotments, new(big.Rat)) - // TODO check there are not duplicate remaining clause - } - } - - if remainingAllotmentIndex != -1 { - allotments[remainingAllotmentIndex] = new(big.Rat).Sub(big.NewRat(1, 1), totalAllotment) - } else if totalAllotment.Cmp(big.NewRat(1, 1)) != 0 { - return nil, InvalidAllotmentSum{ActualSum: *totalAllotment} - } - - parts := make([]*big.Int, len(allotments)) - - totalAllocated := big.NewInt(0) - - for i, allot := range allotments { - monetaryRat := new(big.Rat).SetInt(monetary) - product := new(big.Rat).Mul(allot, monetaryRat) - - floored := new(big.Int).Div(product.Num(), product.Denom()) - - parts[i] = floored - totalAllocated.Add(totalAllocated, floored) - - } - - for i := range parts { - if /* totalAllocated >= monetary */ totalAllocated.Cmp(monetary) != -1 { - break - } - - parts[i].Add(parts[i], big.NewInt(1)) - // totalAllocated++ - totalAllocated.Add(totalAllocated, big.NewInt(1)) - } - - return parts, nil -} - -// Builtins -func meta( - s *programState, - rng parser.Range, - args []Value, -) (string, InterpreterError) { - // TODO more precise location - p := NewArgsParser(args) - account := parseArg(p, rng, expectAccount) - key := parseArg(p, rng, expectString) - err := p.parse() - if err != nil { - return "", err - } - - meta, fetchMetaErr := s.Store.GetAccountsMetadata(s.ctx, MetadataQuery{ - *account: []string{*key}, - }) - if fetchMetaErr != nil { - return "", QueryMetadataError{WrappedError: fetchMetaErr} - } - s.CachedAccountsMeta = meta - - // body - accountMeta := s.CachedAccountsMeta[*account] - value, ok := accountMeta[*key] - - if !ok { - return "", MetadataNotFound{Account: *account, Key: *key, Range: rng} - } - - return value, nil -} - -func balance( - s *programState, - r parser.Range, - args []Value, -) (*Monetary, InterpreterError) { - // TODO more precise args range location - p := NewArgsParser(args) - account := parseArg(p, r, expectAccount) - asset := parseArg(p, r, expectAsset) - err := p.parse() - if err != nil { - return nil, err - } - - // body - s.batchQuery(*account, *asset) - fetchBalanceErr := s.runBalancesQuery() - if fetchBalanceErr != nil { - return nil, QueryBalanceError{WrappedError: fetchBalanceErr} - } - - balance := s.getCachedBalance(*account, *asset) - if balance.Cmp(big.NewInt(0)) == -1 { - return nil, NegativeBalanceError{ - Account: *account, - Amount: *balance, - } - } - - balanceCopy := new(big.Int).Set(balance) - - m := Monetary{ - Asset: Asset(*asset), - Amount: MonetaryInt(*balanceCopy), - } - return &m, nil -} - -func setTxMeta(st *programState, r parser.Range, args []Value) InterpreterError { - p := NewArgsParser(args) - key := parseArg(p, r, expectString) - meta := parseArg(p, r, expectAnything) - err := p.parse() - if err != nil { - return err - } - - st.TxMeta[*key] = *meta - return nil -} - -func setAccountMeta(st *programState, r parser.Range, args []Value) InterpreterError { - p := NewArgsParser(args) - account := parseArg(p, r, expectAccount) - key := parseArg(p, r, expectString) - meta := parseArg(p, r, expectAnything) - err := p.parse() - if err != nil { - return err - } - - accountMeta := defaultMapGet(st.SetAccountsMeta, *account, func() AccountMetadata { - return AccountMetadata{} - }) - - accountMeta[*key] = (*meta).String() - - return nil -} - -func (st *programState) evaluateSentAmt(sentValue parser.SentValue) (*string, *big.Int, InterpreterError) { - switch sentValue := sentValue.(type) { - case *parser.SentValueAll: - asset, err := evaluateExprAs(st, sentValue.Asset, expectAsset) - if err != nil { - return nil, nil, err - } - return asset, nil, nil - - case *parser.SentValueLiteral: - monetary, err := evaluateExprAs(st, sentValue.Monetary, expectMonetary) - if err != nil { - return nil, nil, err - } - s := string(monetary.Asset) - bi := big.Int(monetary.Amount) - return &s, &bi, nil - - default: - utils.NonExhaustiveMatchPanic[any](sentValue) - return nil, nil, nil - } -} - -var percentRegex = regexp.MustCompile(`^([0-9]+)(?:[.]([0-9]+))?[%]$`) -var fractionRegex = regexp.MustCompile(`^([0-9]+)\s?[/]\s?([0-9]+)$`) - -// slightly edited copy-paste from: -// https://github.com/formancehq/ledger/blob/b188d0c80eadaab5024d74edc967c7005e155f7c/internal/machine/portion.go#L57 - -func ParsePortionSpecific(input string) (*big.Rat, InterpreterError) { - var res *big.Rat - var ok bool - - percentMatch := percentRegex.FindStringSubmatch(input) - if len(percentMatch) != 0 { - integral := percentMatch[1] - fractional := percentMatch[2] - res, ok = new(big.Rat).SetString(integral + "." + fractional) - if !ok { - return nil, BadPortionParsingErr{Reason: "invalid percent format", Source: input} - } - res.Mul(res, big.NewRat(1, 100)) - } else { - fractionMatch := fractionRegex.FindStringSubmatch(input) - if len(fractionMatch) != 0 { - numerator := fractionMatch[1] - denominator := fractionMatch[2] - res, ok = new(big.Rat).SetString(numerator + "/" + denominator) - if !ok { - return nil, BadPortionParsingErr{Reason: "invalid fractional format", Source: input} - } - } - } - if res == nil { - return nil, BadPortionParsingErr{Reason: "invalid format", Source: input} - } - - if res.Cmp(big.NewRat(0, 1)) == -1 || res.Cmp(big.NewRat(1, 1)) == 1 { - return nil, BadPortionParsingErr{Reason: "portion must be between 0% and 100% inclusive", Source: input} - } - - return res, nil -} diff --git a/internal/interpreter/interpreter_error.go b/internal/interpreter/interpreter_error.go deleted file mode 100644 index 8be2b07..0000000 --- a/internal/interpreter/interpreter_error.go +++ /dev/null @@ -1,186 +0,0 @@ -package interpreter - -import ( - "fmt" - "math/big" - - "github.com/PagoPlus/numscript-wasm/internal/parser" -) - -type MissingFundsErr struct { - parser.Range - Asset string - Needed big.Int - Available big.Int -} - -func (e MissingFundsErr) Error() string { - return fmt.Sprintf("Not enough funds. Needed [%s %s] (only [%s %s] available)", e.Asset, e.Needed.String(), e.Asset, e.Available.String()) -} - -type InvalidMonetaryLiteral struct { - parser.Range - Source string -} - -func (e InvalidMonetaryLiteral) Error() string { - return fmt.Sprintf("invalid monetary literal: '%s'", e.Source) -} - -type InvalidNumberLiteral struct { - parser.Range - Source string -} - -func (e InvalidNumberLiteral) Error() string { - return fmt.Sprintf("invalid number literal: '%s'", e.Source) -} - -type MetadataNotFound struct { - parser.Range - Account string - Key string -} - -func (e MetadataNotFound) Error() string { - return fmt.Sprintf("account '@%s' doesn't have metadata associated to the '%s' key", e.Account, e.Key) -} - -type TypeError struct { - parser.Range - Expected string - Value Value -} - -func (e TypeError) Error() string { - return fmt.Sprintf("Invalid value received. Expecting value of type %s (got %s instead)", e.Expected, e.Value.String()) -} - -type UnboundVariableErr struct { - parser.Range - Name string -} - -func (e UnboundVariableErr) Error() string { - return fmt.Sprintf("Unbound variable: $%s", e.Name) -} - -type BadPortionParsingErr struct { - parser.Range - Source string - Reason string -} - -func (e BadPortionParsingErr) Error() string { - return fmt.Sprintf("Bad portion: %s", e.Reason) -} - -type MissingVariableErr struct { - parser.Range - Name string -} - -func (e MissingVariableErr) Error() string { - return fmt.Sprintf("Variable is missing in json: %s", e.Name) -} - -type UnboundFunctionErr struct { - parser.Range - Name string -} - -func (e UnboundFunctionErr) Error() string { - return fmt.Sprintf("Invalid function: %s", e.Name) -} - -type BadArityErr struct { - parser.Range - ExpectedArity int - GivenArguments int -} - -func (e BadArityErr) Error() string { - return fmt.Sprintf("Bad arity: expected %d arguments (got %d instead)", e.ExpectedArity, e.GivenArguments) -} - -type InvalidTypeErr struct { - parser.Range - Name string -} - -func (e InvalidTypeErr) Error() string { - return fmt.Sprintf("This type does not exist: %s", e.Name) -} - -type NegativeBalanceError struct { - parser.Range - Account string - Amount big.Int -} - -func (e NegativeBalanceError) Error() string { - return fmt.Sprintf("Cannot fetch negative balance from account @%s", e.Account) -} - -type NegativeAmountErr struct { - parser.Range - Amount MonetaryInt -} - -func (e NegativeAmountErr) Error() string { - return fmt.Sprintf("Cannot send negative amount: %s", e.Amount.String()) -} - -type InvalidAllotmentInSendAll struct { - parser.Range -} - -func (e InvalidAllotmentInSendAll) Error() string { - return "cannot take all balance of an allotment source" -} - -type InvalidUnboundedInSendAll struct { - parser.Range - Name string -} - -func (e InvalidUnboundedInSendAll) Error() string { - return "cannot take all balance from an unbounded source" -} - -type MismatchedCurrencyError struct { - parser.Range - Expected string - Got string -} - -func (e MismatchedCurrencyError) Error() string { - return fmt.Sprintf("Mismatched currency (expected '%s', got '%s' instead)", e.Expected, e.Got) -} - -type InvalidAllotmentSum struct { - parser.Range - ActualSum big.Rat -} - -func (e InvalidAllotmentSum) Error() string { - return fmt.Sprintf("Invalid allotment: portions sum should be 1 (got %s instead)", e.ActualSum.String()) -} - -type QueryBalanceError struct { - parser.Range - WrappedError error -} - -func (e QueryBalanceError) Error() string { - return e.WrappedError.Error() -} - -type QueryMetadataError struct { - parser.Range - WrappedError error -} - -func (e QueryMetadataError) Error() string { - return e.WrappedError.Error() -} diff --git a/internal/interpreter/interpreter_errors_test.go b/internal/interpreter/interpreter_errors_test.go deleted file mode 100644 index db271ce..0000000 --- a/internal/interpreter/interpreter_errors_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package interpreter_test - -import ( - "context" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/gkampitakis/go-snaps/snaps" - "github.com/stretchr/testify/require" -) - -func matchErrWithSnapshots(t *testing.T, src string, vars map[string]string, runOpt interpreter.StaticStore) { - parsed := parser.Parse(src) - _, err := interpreter.RunProgram(context.Background(), parsed.Value, vars, runOpt, nil) - require.NotNil(t, err) - snaps.MatchSnapshot(t, err.GetRange().ShowOnSource(parsed.Source)) -} - -func TestShowUnboundVar(t *testing.T) { - matchErrWithSnapshots(t, `send [COIN 10] ( - source = $unbound_var - destination = @dest -)`, nil, interpreter.StaticStore{}) - -} - -func TestShowMissingFundsSingleAccount(t *testing.T) { - matchErrWithSnapshots(t, `send [COIN 10] ( - source = @a - destination = @dest -)`, nil, interpreter.StaticStore{}) - -} - -func TestShowMissingFundsInorder(t *testing.T) { - matchErrWithSnapshots(t, `send [COIN 10] ( - source = { - @a - @b - } - destination = @dest -)`, nil, interpreter.StaticStore{}) -} - -func TestShowMissingFundsAllotment(t *testing.T) { - matchErrWithSnapshots(t, `send [COIN 10] ( - source = { - 1/2 from @a - remaining from @world - } - destination = @dest -)`, nil, interpreter.StaticStore{}) -} - -func TestShowMissingFundsMax(t *testing.T) { - matchErrWithSnapshots(t, `send [COIN 10] ( - source = max [COIN 2] from { - 1/2 from @world - remaining from @world - } - destination = @dest -)`, nil, interpreter.StaticStore{}) -} - -func TestShowMetadataNotFound(t *testing.T) { - matchErrWithSnapshots(t, `vars { - number $my_var = meta(@acc, "key") -} -`, nil, interpreter.StaticStore{}) -} - -func TestShowTypeError(t *testing.T) { - matchErrWithSnapshots(t, `send 42 ( - source = @a - destination = @b -) -`, nil, interpreter.StaticStore{}) -} - -func TestShowInvalidTypeErr(t *testing.T) { - matchErrWithSnapshots(t, `vars { - invalid_t $x -} -`, map[string]string{"x": "42"}, - interpreter.StaticStore{}, - ) -} diff --git a/internal/interpreter/interpreter_test.go b/internal/interpreter/interpreter_test.go deleted file mode 100644 index 80dca1d..0000000 --- a/internal/interpreter/interpreter_test.go +++ /dev/null @@ -1,3341 +0,0 @@ -package interpreter_test - -import ( - "context" - "encoding/json" - "math/big" - - machine "github.com/PagoPlus/numscript-wasm/internal/interpreter" - - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type TestCase struct { - source string - program *parser.Program - vars map[string]string - meta machine.AccountsMetadata - balances map[string]map[string]*big.Int - expected CaseResult -} - -func NewTestCase() TestCase { - return TestCase{ - vars: make(map[string]string), - meta: machine.AccountsMetadata{}, - balances: make(map[string]map[string]*big.Int), - expected: CaseResult{ - Postings: []machine.Posting{}, - TxMetadata: make(map[string]machine.Value), - Error: nil, - }, - } -} - -// returns a version of the error in which the range is normalized -// to golang's default value -func removeRange(e machine.InterpreterError) machine.InterpreterError { - switch e := e.(type) { - case machine.MissingFundsErr: - e.Range = parser.Range{} - return e - case machine.TypeError: - e.Range = parser.Range{} - return e - case machine.InvalidTypeErr: - e.Range = parser.Range{} - return e - case machine.NegativeAmountErr: - e.Range = parser.Range{} - return e - default: - return e - } -} - -func (c *TestCase) setVarsFromJSON(t *testing.T, str string) { - var jsonVars map[string]string - err := json.Unmarshal([]byte(str), &jsonVars) - require.NoError(t, err) - c.vars = jsonVars -} - -func (tc *TestCase) compile(t *testing.T, src string) { - tc.source = src - parsed := parser.Parse(src) - if len(parsed.Errors) != 0 { - t.Errorf("Got parsing errors: %v\n", parsed.Errors) - } - tc.program = &parsed.Value -} - -func (c *TestCase) setBalance(account string, asset string, amount int64) { - if _, ok := c.balances[account]; !ok { - c.balances[account] = make(map[string]*big.Int) - } - c.balances[account][asset] = big.NewInt(amount) -} - -func test(t *testing.T, testCase TestCase) { - t.Parallel() - - prog := testCase.program - - require.NotNil(t, prog) - - execResult, err := machine.RunProgram(context.Background(), *prog, testCase.vars, machine.StaticStore{ - testCase.balances, - testCase.meta, - }, nil) - - expected := testCase.expected - if expected.Error != nil { - require.Equal(t, removeRange(expected.Error), removeRange(err)) - } else { - require.NoError(t, err) - } - if err != nil { - return - } - - if expected.Postings == nil { - expected.Postings = make([]Posting, 0) - } - if expected.TxMetadata == nil { - expected.TxMetadata = make(map[string]machine.Value) - } - if expected.AccountMetadata == nil { - expected.AccountMetadata = machine.AccountsMetadata{} - } - - assert.Equal(t, expected.Postings, execResult.Postings) - assert.Equal(t, expected.TxMetadata, execResult.Metadata) - assert.Equal(t, expected.AccountMetadata, execResult.AccountsMetadata) -} - -type CaseResult struct { - Postings []machine.Posting - TxMetadata map[string]machine.Value - AccountMetadata machine.AccountsMetadata - Error machine.InterpreterError -} - -type Posting = machine.Posting - -func TestSend(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [EUR/2 100] ( - source=@alice - destination=@bob - )`) - tc.setBalance("alice", "EUR/2", 100) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "EUR/2", - Amount: big.NewInt(100), - Source: "alice", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSetTxMeta(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - set_tx_meta("num", 42) - set_tx_meta("str", "abc") - set_tx_meta("asset", COIN) - set_tx_meta("account", @acc) - set_tx_meta("portion", 12%) - `) - - tc.expected = CaseResult{ - TxMetadata: map[string]machine.Value{ - "num": machine.NewMonetaryInt(42), - "str": machine.String("abc"), - "asset": machine.Asset("COIN"), - "account": machine.AccountAddress("acc"), - "portion": machine.Portion(*big.NewRat(12, 100)), - }, - Error: nil, - } - test(t, tc) -} - -func TestSetAccountMeta(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - set_account_meta(@acc, "num", 42) - set_account_meta(@acc, "str", "abc") - set_account_meta(@acc, "asset", COIN) - set_account_meta(@acc, "account", @acc) - set_account_meta(@acc, "portion", 2/7) - set_account_meta(@acc, "portion-perc", 1%) - `) - - tc.expected = CaseResult{ - AccountMetadata: machine.AccountsMetadata{ - "acc": { - "num": "42", - "str": "abc", - "asset": "COIN", - "account": "acc", - "portion": "2/7", - "portion-perc": "1/100", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestOverrideAccountMeta(t *testing.T) { - tc := NewTestCase() - tc.meta = machine.AccountsMetadata{ - "acc": { - "initial": "0", - "overridden": "1", - }, - } - tc.compile(t, ` - set_account_meta(@acc, "overridden", 100) - set_account_meta(@acc, "new", 2) - `) - tc.expected = CaseResult{ - AccountMetadata: machine.AccountsMetadata{ - "acc": { - "overridden": "100", - "new": "2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestVariables(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $rider - account $driver - string $description - number $nb - asset $ass - } - send [$ass 999] ( - source=$rider - destination=$driver - ) - set_tx_meta("description", $description) - set_tx_meta("ride", $nb)`) - tc.vars = map[string]string{ - "rider": "users:001", - "driver": "users:002", - "description": "midnight ride", - "nb": "1", - "ass": "EUR/2", - } - tc.setBalance("users:001", "EUR/2", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "EUR/2", - Amount: big.NewInt(999), - Source: "users:001", - Destination: "users:002", - }, - }, - TxMetadata: map[string]machine.Value{ - "description": machine.String("midnight ride"), - "ride": machine.NewMonetaryInt(1), - }, - Error: nil, - } - test(t, tc) -} - -func TestVariablesJSON(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $rider - account $driver - string $description - number $nb - asset $ass - portion $por - } - send [$ass 999] ( - source=$rider - destination=$driver - ) - set_tx_meta("description", $description) - set_tx_meta("ride", $nb) - set_tx_meta("por", $por)`) - tc.setVarsFromJSON(t, `{ - "por": "42%", - "rider": "users:001", - "driver": "users:002", - "description": "midnight ride", - "nb": "1", - "ass": "EUR/2" - }`) - tc.setBalance("users:001", "EUR/2", 1000) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "EUR/2", - Amount: big.NewInt(999), - Source: "users:001", - Destination: "users:002", - }, - }, - TxMetadata: map[string]machine.Value{ - "description": machine.String("midnight ride"), - "ride": machine.NewMonetaryInt(1), - "por": machine.Portion(*big.NewRat(42, 100)), - }, - Error: nil, - } - test(t, tc) -} - -func TestPortionSyntax(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - portion $por - } - send [COIN 3] ( - source = @world - destination = { - $por to @a - remaining kept - } - ) - `) - tc.setVarsFromJSON(t, `{ - "por": "1/3" - }`) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(1), - Source: "world", - Destination: "a", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestBadPortionSyntax(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - portion $por - } - send [COIN 3] ( - source = @world - destination = { - $por to @a - remaining kept - } - ) - `) - tc.setVarsFromJSON(t, `{ - "por": "not a portion" - }`) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.BadPortionParsingErr{ - Source: "not a portion", - Reason: "invalid format", - }, - } - test(t, tc) -} - -func TestSource(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $balance - account $payment - account $seller - } - send [GEM 15] ( - source = { - $balance - $payment - } - destination = $seller - )`) - tc.setVarsFromJSON(t, `{ - "balance": "users:001", - "payment": "payments:001", - "seller": "users:002" - }`) - tc.setBalance("users:001", "GEM", 3) - tc.setBalance("payments:001", "GEM", 12) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "GEM", - Amount: big.NewInt(3), - Source: "users:001", - Destination: "users:002", - }, - { - Asset: "GEM", - Amount: big.NewInt(12), - Source: "payments:001", - Destination: "users:002", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestAllocation(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $rider - account $driver - } - send [GEM 15] ( - source = $rider - destination = { - 80% to $driver - 8% to @a - 12% to @b - } - )`) - tc.setVarsFromJSON(t, `{ - "rider": "users:001", - "driver": "users:002" - }`) - tc.setBalance("users:001", "GEM", 15) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "GEM", - Amount: big.NewInt(13), - Source: "users:001", - Destination: "users:002", - }, - { - Asset: "GEM", - Amount: big.NewInt(1), - Source: "users:001", - Destination: "a", - }, - { - Asset: "GEM", - Amount: big.NewInt(1), - Source: "users:001", - Destination: "b", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestDynamicAllocation(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - portion $p - } - send [GEM 15] ( - source = @a - destination = { - 80% to @b - $p to @c - remaining to @d - } - )`) - tc.setVarsFromJSON(t, `{ - "p": "15%" - }`) - tc.setBalance("a", "GEM", 15) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "GEM", - Amount: big.NewInt(13), - Source: "a", - Destination: "b", - }, - { - Asset: "GEM", - Amount: big.NewInt(2), - Source: "a", - Destination: "c", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @users:001 - destination = @platform - )`) - tc.setBalance("users:001", "USD/2", 17) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(17), - Source: "users:001", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAllVariable(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - account $src - account $dest - } - - send [USD/2 *] ( - source = $src - destination = $dest - )`) - tc.setVarsFromJSON(t, `{ - "src": "users:001", - "dest": "platform" - }`) - tc.setBalance("users:001", "USD/2", 17) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(17), - Source: "users:001", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAlltMaxWhenNoAmount(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = max [USD/2 5] from @src - destination = @dest - ) - `) - tc.setBalance("src1", "USD/2", 0) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: nil, - } - test(t, tc) -} - -func TestNegativeMaxSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = max [USD/2 -50] from @src - destination = @dest - ) - `) - tc.setBalance("src", "USD/2", 0) - tc.expected = CaseResult{ - Postings: []Posting{ - // Posting omitted - // { - // Asset: "USD/2", - // Amount: big.NewInt(0), - // Source: "src", - // Destination: "dest", - // }, - }, - Error: nil, - } - test(t, tc) -} - -func TestNegativeMax(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 100] ( - source = { - max [USD/2 -50] from @src - @world - } - destination = @dest - ) - `) - tc.setBalance("src", "USD/2", 0) - tc.expected = CaseResult{ - Postings: []Posting{ - - { - Asset: "USD/2", - Amount: big.NewInt(100), - Source: "world", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAllDestinatioAllot(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @users:001 - destination = { - 1/3 to @d1 - 2/3 to @d2 - } - )`) - tc.setBalance("users:001", "USD/2", 30) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(10), - Source: "users:001", - Destination: "d1", - }, - { - Asset: "USD/2", - Amount: big.NewInt(20), - Source: "users:001", - Destination: "d2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAllDestinatioAllotComplex(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = { - @users:001 - @users:002 - } - destination = { - 1/3 to @d1 - 2/3 to @d2 - } - )`) - tc.setBalance("users:001", "USD/2", 15) - tc.setBalance("users:002", "USD/2", 15) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(10), - Source: "users:001", - Destination: "d1", - }, - { - Asset: "USD/2", - Amount: big.NewInt(5), - Source: "users:001", - Destination: "d2", - }, - { - Asset: "USD/2", - Amount: big.NewInt(15), - Source: "users:002", - Destination: "d2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestInvalidAllotInSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = { - 1/2 from @a - 2/3 from @b - } - destination = @dest - )`) - tc.expected = CaseResult{ - Error: machine.InvalidAllotmentInSendAll{}, - } - test(t, tc) -} - -func TestInvalidUnboundedWorldInSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @world - destination = @dest - )`) - tc.expected = CaseResult{ - Error: machine.InvalidUnboundedInSendAll{Name: "world"}, - } - test(t, tc) -} - -func TestInvalidUnboundedInSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @a allowing unbounded overdraft - destination = @dest - )`) - tc.expected = CaseResult{ - Error: machine.InvalidUnboundedInSendAll{Name: "a"}, - } - test(t, tc) -} - -func TestOverdraftInSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @src allowing overdraft up to [USD/2 10] - destination = @dest - )`) - tc.setBalance("src", "USD/2", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(1010), - Source: "src", - Destination: "dest", - }, - }, - } - test(t, tc) -} - -func TestOverdraftInSendAllWhenNoop(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @src allowing overdraft up to [USD/2 10] - destination = @dest - )`) - tc.setBalance("src", "USD/2", 1) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(11), - Source: "src", - Destination: "dest", - }, - }, - } - test(t, tc) -} - -func TestSendAlltMaxInSrc(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = { - max [USD/2 5] from @src1 - @src2 - } - destination = @dest - ) - `) - tc.setBalance("src1", "USD/2", 100) - tc.setBalance("src2", "USD/2", 200) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(5), - Source: "src1", - Destination: "dest", - }, - { - Asset: "USD/2", - Amount: big.NewInt(200), - Source: "src2", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAlltMaxInDest(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @src - destination = { - max [USD/2 10] to @d1 - remaining to @d2 - } - ) - `) - tc.setBalance("src", "USD/2", 100) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(10), - Source: "src", - Destination: "d1", - }, - { - Asset: "USD/2", - Amount: big.NewInt(90), - Source: "src", - Destination: "d2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestManyMaxDest(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 100] ( - source = @world - destination = { - max [USD/2 10] to @d1 - max [USD/2 12] to @d2 - remaining to @rem - } - ) - `) - tc.setBalance("src", "USD/2", 100) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(10), - Source: "world", - Destination: "d1", - }, - { - Asset: "USD/2", - Amount: big.NewInt(12), - Source: "world", - Destination: "d2", - }, - { - Asset: "USD/2", - Amount: big.NewInt(100 - 10 - 12), - Source: "world", - Destination: "rem", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestManyKeptDest(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 100] ( - source = @world - destination = { - max [USD/2 10] kept - max [USD/2 12] to @d2 - remaining to @rem - } - ) - `) - tc.setBalance("src", "USD/2", 100) - tc.expected = CaseResult{ - Postings: []Posting{ - // { - // Asset: "USD/2", - // Amount: big.NewInt(10), - // Source: "world", - // Destination: "", - // }, - { - Asset: "USD/2", - Amount: big.NewInt(12), - Source: "world", - Destination: "d2", - }, - { - Asset: "USD/2", - Amount: big.NewInt(100 - 10 - 12), - Source: "world", - Destination: "rem", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAllManyMaxInDest(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = @src - destination = { - max [USD/2 10] to @d1 - max [USD/2 20] to @d2 - remaining to @d3 - } - ) - `) - tc.setBalance("src", "USD/2", 15) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(10), - Source: "src", - Destination: "d1", - }, - { - Asset: "USD/2", - Amount: big.NewInt(5), - Source: "src", - Destination: "d2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSendAllMulti(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [USD/2 *] ( - source = { - @users:001:wallet - @users:001:credit - } - destination = @platform - ) - `) - tc.setBalance("users:001:wallet", "USD/2", 19) - tc.setBalance("users:001:credit", "USD/2", 22) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(19), - Source: "users:001:wallet", - Destination: "platform", - }, - { - Asset: "USD/2", - Amount: big.NewInt(22), - Source: "users:001:credit", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestInsufficientFunds(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $balance - account $payment - account $seller - } - send [GEM 16] ( - source = { - $balance - $payment - } - destination = $seller - )`) - tc.setVarsFromJSON(t, `{ - "balance": "users:001", - "payment": "payments:001", - "seller": "users:002" - }`) - tc.setBalance("users:001", "GEM", 3) - tc.setBalance("payments:001", "GEM", 12) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.MissingFundsErr{ - Asset: "GEM", - Needed: *big.NewInt(16), - Available: *big.NewInt(15), - }, - } - test(t, tc) -} - -func TestWorldSource(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [GEM 15] ( - source = { - @a - @world - } - destination = @b - )`) - tc.setBalance("a", "GEM", 1) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "GEM", - Amount: big.NewInt(1), - Source: "a", - Destination: "b", - }, - { - Asset: "GEM", - Amount: big.NewInt(14), - Source: "world", - Destination: "b", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestNoEmptyPostings(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [GEM 2] ( - source = @world - destination = { - 90% to @a - 10% to @b - } - )`) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "GEM", - Amount: big.NewInt(2), - Source: "world", - Destination: "a", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestEmptyPostings(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [GEM *] ( - source = @foo - destination = @bar - )`) - tc.setBalance("foo", "GEM", 0) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: nil, - } - test(t, tc) -} - -func TestAllocateDontTakeTooMuch(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [CREDIT 200] ( - source = { - @users:001 - @users:002 - } - destination = { - 1/2 to @foo - 1/2 to @bar - } - )`) - tc.setBalance("users:001", "CREDIT", 100) - tc.setBalance("users:002", "CREDIT", 110) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "CREDIT", - Amount: big.NewInt(100), - Source: "users:001", - Destination: "foo", - }, - { - Asset: "CREDIT", - Amount: big.NewInt(100), - Source: "users:002", - Destination: "bar", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestMetadata(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $sale - account $seller = meta($sale, "seller") - portion $commission = meta($seller, "commission") - } - send [EUR/2 100] ( - source = $sale - destination = { - remaining to $seller - $commission to @platform - } - )`) - tc.setVarsFromJSON(t, `{ - "sale": "sales:042" - }`) - tc.meta = machine.AccountsMetadata{ - "sales:042": { - "seller": "users:053", - }, - "users:053": { - "commission": "12.5%", - }, - } - tc.setBalance("sales:042", "EUR/2", 2500) - tc.setBalance("users:053", "EUR/2", 500) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "EUR/2", - Amount: big.NewInt(88), - Source: "sales:042", - Destination: "users:053", - }, - { - Asset: "EUR/2", - Amount: big.NewInt(12), - Source: "sales:042", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestTrackBalances(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [COIN 50] ( - source = @world - destination = @a - ) - send [COIN 100] ( - source = @a - destination = @b - )`) - tc.setBalance("a", "COIN", 50) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(50), - Source: "world", - Destination: "a", - }, - { - Asset: "COIN", - Amount: big.NewInt(100), - Source: "a", - Destination: "b", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestTrackBalances2(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [COIN 50] ( - source = @a - destination = @z - ) - send [COIN 50] ( - source = @a - destination = @z - )`) - tc.setBalance("a", "COIN", 60) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.MissingFundsErr{ - Asset: "COIN", - Needed: *big.NewInt(50), - Available: *big.NewInt(10), - }, - } - test(t, tc) -} - -func TestKeptInSendAllInorder(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN *] ( - source = @src - destination = { - max [COIN 1] kept - remaining to @dest - } - )`) - - tc.setBalance("src", "COIN", 10) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(9), - Source: "src", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestRemainingKeptInSendAllInorder(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN *] ( - source = @src - destination = { - max [COIN 1] to @dest - remaining kept - } - )`) - - tc.setBalance("src", "COIN", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(1), - Source: "src", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestTrackBalancesSendAll(t *testing.T) { - // TODO double check - tc := NewTestCase() - tc.compile(t, ` - send [COIN *] ( - source = @src - destination = @dest1 - ) - send [COIN *] ( - source = @src - destination = @dest2 - )`) - tc.setBalance("src", "COIN", 42) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(42), - Source: "src", - Destination: "dest1", - }, - // { - // Asset: "COIN", - // Amount: big.NewInt(0), - // Source: "src", - // Destination: "dest2", - // }, - }, - Error: nil, - } - test(t, tc) -} - -func TestTrackBalances3(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN *] ( - source = @foo - destination = { - max [COIN 1000] to @bar - remaining kept - } - ) - send [COIN *] ( - source = @foo - destination = @bar - )`) - tc.setBalance("foo", "COIN", 2000) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(1000), - Source: "foo", - Destination: "bar", - }, - { - Asset: "COIN", - Amount: big.NewInt(1000), - Source: "foo", - Destination: "bar", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSourceAllotment(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = { - 60% from @a - 35.5% from @b - 4.5% from @c - } - destination = @d - )`) - tc.setBalance("a", "COIN", 100) - tc.setBalance("b", "COIN", 100) - tc.setBalance("c", "COIN", 100) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(61), - Source: "a", - Destination: "d", - }, - { - Asset: "COIN", - Amount: big.NewInt(35), - Source: "b", - Destination: "d", - }, - { - Asset: "COIN", - Amount: big.NewInt(4), - Source: "c", - Destination: "d", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestInvalidSourceAllotmentSum(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = { - 42% from @world - } - destination = @dest - )`) - - tc.expected = CaseResult{ - Error: machine.InvalidAllotmentSum{ - ActualSum: *big.NewRat(42, 100), - }, - } - test(t, tc) -} - -func TestInvalidDestinationAllotmentSum(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @world - destination = { - 1/4 to @x - } - )`) - - tc.expected = CaseResult{ - Error: machine.InvalidAllotmentSum{ - ActualSum: *big.NewRat(1, 4), - }, - } - test(t, tc) -} - -func TestSourceAllotmentInvalidAmt(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = { - // a doesn't have enough amount - 10% from @a - - // world has, but the computation has already failed - remaining from @world - } - destination = @d - )`) - tc.setBalance("a", "COIN", 1) - tc.expected = CaseResult{ - Error: machine.MissingFundsErr{ - Asset: "COIN", - Needed: *big.NewInt(10), - Available: *big.NewInt(1), - }, - } - test(t, tc) -} - -func TestSourceOverlapping(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 99] ( - source = { - 15% from { - @b - @a - } - 30% from @a - remaining from @a - } - destination = @world - )`) - tc.setBalance("a", "COIN", 99) - tc.setBalance("b", "COIN", 3) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(3), - Source: "b", - Destination: "world", - }, - { - Asset: "COIN", - Amount: big.NewInt(96), - Source: "a", - Destination: "world", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestCappedWhenMoreThanBalance(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [COIN 100] ( - source = { - max [COIN 200] from @world - @src - } - destination = @platform - ) - `) - tc.setBalance("src", "COIN", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(100), - Source: "world", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestCappedWhenLessThanNeeded(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [COIN 100] ( - source = { - max [COIN 40] from @src1 - @src2 - } - destination = @platform - ) - `) - tc.setBalance("src1", "COIN", 1000) - tc.setBalance("src2", "COIN", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(40), - Source: "src1", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(60), - Source: "src2", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSourceComplex(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - monetary $max - } - send [COIN 200] ( - source = { - 50% from { - max [COIN 4] from @a - @b - @c - } - remaining from max $max from @d - } - destination = @platform - )`) - tc.setVarsFromJSON(t, `{ - "max": "COIN 120" - }`) - tc.setBalance("a", "COIN", 1000) - tc.setBalance("b", "COIN", 40) - tc.setBalance("c", "COIN", 1000) - tc.setBalance("d", "COIN", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(4), - Source: "a", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(40), - Source: "b", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(56), - Source: "c", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(100), - Source: "d", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestKeptInorder(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @world - destination = { - max [COIN 10] kept - remaining to @dest - } - )`) - - tc.expected = CaseResult{ - Postings: []Posting{ - // 10 COIN are kept - { - Asset: "COIN", - Amount: big.NewInt(90), - Source: "world", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) - -} - -func TestRemainingKeptInorder(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @world - destination = { - max [COIN 1] to @a - remaining kept - } - )`) - - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(1), - Source: "world", - Destination: "a", - }, - }, - Error: nil, - } - test(t, tc) - -} - -func TestKeptWithBalance(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @src - destination = { - max [COIN 10] kept - remaining to @dest - } - )`) - - tc.setBalance("src", "COIN", 1000) - - tc.expected = CaseResult{ - Postings: []Posting{ - // 10 COIN are kept - { - Asset: "COIN", - Amount: big.NewInt(90), - Source: "src", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) - -} - -func TestRemainingNone(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 10] ( - source = @world - destination = { - max [COIN 10] to @a - remaining to @b - } - )`) - - tc.expected = CaseResult{ - Postings: []Posting{ - // 10 COIN are kept - { - Asset: "COIN", - Amount: big.NewInt(10), - Source: "world", - Destination: "a", - }, - }, - Error: nil, - } - test(t, tc) - -} - -func TestRemainingNoneInSendAll(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN *] ( - source = @src - destination = { - max [COIN 10] to @a - remaining to @b - } - )`) - - tc.setBalance("src", "COIN", 10) - tc.expected = CaseResult{ - Postings: []Posting{ - // 10 COIN are kept - { - Asset: "COIN", - Amount: big.NewInt(10), - Source: "src", - Destination: "a", - }, - }, - Error: nil, - } - test(t, tc) - -} - -func TestDestinationComplex(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @world - destination = { - 20% to @a - 20% kept - 60% to { - max [COIN 10] to @b - remaining to @c - } - } - )`) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(20), - Source: "world", - Destination: "a", - }, - { - Asset: "COIN", - Amount: big.NewInt(10), - Source: "world", - Destination: "b", - }, - { - Asset: "COIN", - Amount: big.NewInt(50), - Source: "world", - Destination: "c", - }, - }, - Error: nil, - } - test(t, tc) -} - -// TODO TestNeededBalances, TestSetTxMeta, TestSetAccountMeta - -func TestSendZero(t *testing.T) { - // TODO double check - tc := NewTestCase() - tc.compile(t, ` - send [COIN 0] ( - source = @src - destination = @dest - )`) - tc.expected = CaseResult{ - Postings: []Posting{ - // { - // Asset: "COIN", - // Amount: big.NewInt(0), - // Source: "src", - // Destination: "dest", - // }, - }, - Error: nil, - } - test(t, tc) -} - -func TestBalance(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - monetary $balance = balance(@a, EUR/2) - } - - send $balance ( - source = @world - destination = @dest - )`) - tc.setBalance("a", "EUR/2", 123) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "EUR/2", - Amount: big.NewInt(123), - Source: "world", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestNegativeBalance(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - monetary $balance = balance(@a, EUR/2) - } - - send $balance ( - source = @world - destination = @dest - )`) - tc.setBalance("a", "EUR/2", -100) - tc.expected = CaseResult{ - Error: machine.NegativeBalanceError{ - Account: "a", - Amount: *big.NewInt(-100), - }, - } - test(t, tc) -} - -func TestNegativeBalanceLiteral(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [EUR/2 -100] ( - source = @world - destination = @dest - )`) - tc.expected = CaseResult{ - Error: machine.NegativeAmountErr{ - Amount: machine.MonetaryInt(*big.NewInt(-100)), - }, - } - test(t, tc) -} - -func TestBalanceNotFound(t *testing.T) { - // TODO double check - tc := NewTestCase() - tc.compile(t, ` - vars { - monetary $balance = balance(@a, EUR/2) - } - - send $balance ( - source = @world - destination = @dest - )`) - tc.expected = CaseResult{ - Postings: []Posting{ - // { - // Asset: "EUR/2", - // Amount: big.NewInt(0), - // Source: "world", - // Destination: "dest", - // }, - }, - Error: nil, - } - test(t, tc) -} - -func TestInoderDestination(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `send [COIN 100] ( - source = @world - destination = { - max [COIN 20] to @dest1 - remaining to @dest2 - } - )`) - tc.setBalance("a", "COIN", 123) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(20), - Source: "world", - Destination: "dest1", - }, - { - Asset: "COIN", - Amount: big.NewInt(80), - Source: "world", - Destination: "dest2", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestVariableBalance(t *testing.T) { - script := ` - vars { - monetary $initial = balance(@A, USD/2) - } - send [USD/2 100] ( - source = { - @A - @C - } - destination = { - max $initial to @B - remaining to @D - } - )` - - t.Run("1", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("A", "USD/2", 40) - tc.setBalance("C", "USD/2", 90) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(40), - Source: "A", - Destination: "B", - }, - { - Asset: "USD/2", - Amount: big.NewInt(60), - Source: "C", - Destination: "D", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("2", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("A", "USD/2", 400) - tc.setBalance("C", "USD/2", 90) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(100), - Source: "A", - Destination: "B", - }, - }, - Error: nil, - } - test(t, tc) - }) - - script = ` - vars { - account $acc - monetary $initial = balance($acc, USD/2) - } - send [USD/2 100] ( - source = { - $acc - @C - } - destination = { - max $initial to @B - remaining to @D - } - )` - - t.Run("3", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("A", "USD/2", 40) - tc.setBalance("C", "USD/2", 90) - tc.setVarsFromJSON(t, `{"acc": "A"}`) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(40), - Source: "A", - Destination: "B", - }, - { - Asset: "USD/2", - Amount: big.NewInt(60), - Source: "C", - Destination: "D", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("4", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("A", "USD/2", 400) - tc.setBalance("C", "USD/2", 90) - tc.setVarsFromJSON(t, `{"acc": "A"}`) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: big.NewInt(100), - Source: "A", - Destination: "B", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("5", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - monetary $max = balance(@maxAcc, COIN) - } - send [COIN 200] ( - source = { - 50% from { - max [COIN 4] from @a - @b - @c - } - remaining from max $max from @d - } - destination = @platform - )`) - tc.setBalance("maxAcc", "COIN", 120) - tc.setBalance("a", "COIN", 1000) - tc.setBalance("b", "COIN", 40) - tc.setBalance("c", "COIN", 1000) - tc.setBalance("d", "COIN", 1000) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(4), - Source: "a", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(40), - Source: "b", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(56), - Source: "c", - Destination: "platform", - }, - { - Asset: "COIN", - Amount: big.NewInt(100), - Source: "d", - Destination: "platform", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("send negative monetary", func(t *testing.T) { - tc := NewTestCase() - script = ` - vars { - monetary $amount = balance(@src, USD/2) - } - send $amount ( - source = @A - destination = @B - )` - tc.compile(t, script) - tc.setBalance("src", "USD/2", -40) - tc.expected = CaseResult{ - Error: machine.NegativeBalanceError{ - Account: "src", - Amount: *big.NewInt(-40), - }, - } - test(t, tc) - }) -} - -// TODO TestVariablesParsing, TestSetVarsFromJSON, TestResolveResources, TestResolveBalances, TestMachine - -// TODO -// func TestVariablesErrors(t *testing.T) { -// tc := NewTestCase() -// tc.compile(t, `vars { -// monetary $mon -// } -// send $mon ( -// source = @alice -// destination = @bob -// )`) -// tc.setBalance("alice", "COIN", 10) -// tc.vars = map[string]string{ -// "mon": "COIN -1", -// } -// tc.expected = CaseResult{ -// Postings: []Posting{}, -// Error: &machine.ErrInvalidVars{}, -// ErrorContains: "negative amount", -// } -// test(t, tc) -// } - -func TestVariableAsset(t *testing.T) { - script := ` - vars { - asset $ass - monetary $bal = balance(@alice, $ass) - } - - send [$ass 15] ( - source = { - @alice - @bob - } - destination = @swap - ) - - send [$ass *] ( - source = @swap - destination = { - max $bal to @alice_2 - remaining to @bob_2 - } - )` - - tc := NewTestCase() - tc.compile(t, script) - tc.vars = map[string]string{ - "ass": "USD", - } - tc.setBalance("alice", "USD", 10) - tc.setBalance("bob", "USD", 10) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "alice", - Destination: "swap", - }, - { - Asset: "USD", - Amount: big.NewInt(5), - Source: "bob", - Destination: "swap", - }, - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "swap", - Destination: "alice_2", - }, - { - Asset: "USD", - Amount: big.NewInt(5), - Source: "swap", - Destination: "bob_2", - }, - }, - Error: nil, - } - test(t, tc) -} - -// TODO TestSaveFromAccount - -func TestUseDifferentAssetsWithSameSourceAccount(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `vars { - account $a_account -} -send [A 100] ( - source = $a_account allowing unbounded overdraft - destination = @account1 -) -send [B 100] ( - source = @world - destination = @account2 -)`) - tc.setBalance("account1", "A", 100) - tc.setBalance("account2", "B", 100) - tc.setVarsFromJSON(t, `{"a_account": "world"}`) - tc.expected = CaseResult{ - - Postings: []Posting{{ - Source: "world", - Destination: "account1", - Amount: big.NewInt(100), - Asset: "A", - }, { - Source: "world", - Destination: "account2", - Amount: big.NewInt(100), - Asset: "B", - }}, - } - test(t, tc) -} - -func TestMaxWithUnboundedOverdraft(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` -send [COIN 100] ( - source = { - max [COIN 10] from @account1 allowing unbounded overdraft - @account2 - } - destination = @world -)`) - tc.setBalance("account1", "COIN", 10000) - tc.setBalance("account2", "COIN", 10000) - tc.expected = CaseResult{ - Postings: []Posting{{ - Source: "account1", - Destination: "world", - Amount: big.NewInt(10), - Asset: "COIN", - }, { - Source: "account2", - Destination: "world", - Amount: big.NewInt(90), - Asset: "COIN", - }}, - } - test(t, tc) -} - -func TestOverdraftWhenEnoughFunds(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` -send [COIN 100] ( - source = @users:1234 allowing overdraft up to [COIN 100] - destination = @dest -) -`) - tc.expected = CaseResult{ - Postings: []Posting{{ - Source: "users:1234", - Destination: "dest", - Amount: big.NewInt(100), - Asset: "COIN", - }}, - } - test(t, tc) -} - -func TestOverdraftNotEnoughFunds(t *testing.T) { - tc := NewTestCase() - tc.setBalance("users:2345:main", "USD/2", 8000) - tc.compile(t, ` - send [USD/2 2200] ( - source = { - // let the user pay with their credit account first, - @users:2345:credit allowing overdraft up to [USD/2 1000] - // then, use their main balance - @users:2345:main - } - destination = @payments:4567 - ) - `) - - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "users:2345:credit", - "payments:4567", - big.NewInt(1000), - "USD/2", - }, - { - "users:2345:main", - "payments:4567", - big.NewInt(1200), - "USD/2", - }, - }, - } - test(t, tc) -} - -func TestOverdraftBadCurrency(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` -send [COIN 100] ( - source = @users:1234 allowing overdraft up to [WRONGCURR 100] - destination = @dest -) -`) - tc.expected = CaseResult{ - Error: machine.MismatchedCurrencyError{ - Expected: "COIN", - Got: "WRONGCURR", - }, - } - test(t, tc) -} - -func TestOverdraftWhenNotEnoughFunds(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` -send [COIN 100] ( - source = @users:1234 allowing overdraft up to [COIN 10] - destination = @dest -) -`) - - tc.setBalance("users:1234", "COIN", 1) - - tc.expected = CaseResult{ - Error: machine.MissingFundsErr{ - Asset: "COIN", - Needed: *big.NewInt(100), - Available: *big.NewInt(11), - }, - } - test(t, tc) -} - -func TestErrors(t *testing.T) { - t.Run("wrong type for send literal", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send @bad:type ( - source = @a - destination = @b - )`) - tc.expected = CaseResult{ - Error: machine.TypeError{ - Expected: "monetary", - Value: machine.AccountAddress("bad:type"), - }, - } - test(t, tc) - }) - - t.Run("wrong type for account literal", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - number $var_src - } - - send [COIN 10] ( - source = { - 1/2 from @world - remaining from { - @empty - max [COIN 100] from $var_src - } - } - destination = @b - )`) - tc.setVarsFromJSON(t, `{"var_src": "42"}`) - - tc.expected = CaseResult{ - Error: machine.TypeError{ - Expected: "account", - Value: machine.NewMonetaryInt(42), - }, - } - test(t, tc) - }) - - t.Run("wrong type for account cap", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - string $v - } - - send [COIN 10] ( - source = max $v from @src - destination = @b - )`) - tc.setVarsFromJSON(t, `{"v": "abc"}`) - - tc.expected = CaseResult{ - Error: machine.TypeError{ - Expected: "monetary", - Value: machine.String("abc"), - }, - } - test(t, tc) - }) - - t.Run("unbound variable", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send $unbound_var ( - source = @a - destination = @b - )`) - - tc.expected = CaseResult{ - Error: machine.UnboundVariableErr{ - Name: "unbound_var", - Range: parser.RangeOfIndexed(tc.source, "$unbound_var", 0), - }, - } - test(t, tc) - }) - - t.Run("missing variable from json", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - monetary $x - } - - send $x ( - source = @a - destination = @b - )`) - - tc.expected = CaseResult{ - Error: machine.MissingVariableErr{ - Name: "x", - }, - } - test(t, tc) - }) - - t.Run("unbound fn", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `unbound_fn(1, 2)`) - - tc.expected = CaseResult{ - Error: machine.UnboundFunctionErr{ - Name: "unbound_fn", - }, - } - test(t, tc) - }) - - t.Run("unbound fn (origin)", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - number $x = unbound_fn(1, 2) - } - `) - - tc.expected = CaseResult{ - Error: machine.UnboundFunctionErr{ - Name: "unbound_fn", - }, - } - test(t, tc) - }) - - t.Run("wrong fn arity", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `set_tx_meta()`) - - tc.expected = CaseResult{ - Error: machine.BadArityErr{ - ExpectedArity: 2, - GivenArguments: 0, - }, - } - test(t, tc) - }) - - t.Run("wrong fn type", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, `set_tx_meta(@key_wrong_type, "value")`) - tc.expected = CaseResult{ - Error: machine.TypeError{ - Expected: "string", - Value: machine.AccountAddress("key_wrong_type"), - }, - } - test(t, tc) - }) - - t.Run("invalid variable type", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { - invalidt $x - } - `) - tc.setVarsFromJSON(t, `{"x": "42"}`) - tc.expected = CaseResult{ - Error: machine.InvalidTypeErr{ - Name: "invalidt", - }, - } - test(t, tc) - }) - - t.Run("bad currency type in max (source)", func(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [EUR/2 1] ( - source = max [USD/2 10] from @world - destination = @b - ) - `) - tc.expected = CaseResult{ - Error: machine.MismatchedCurrencyError{ - Expected: "EUR/2", - Got: "USD/2", - }, - } - test(t, tc) - }) -} - -func TestNestedRemaining(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [GEM 100] ( - source = @world - destination = { - 10% to { - remaining to { - 100% to { - max [GEM 1] to @dest1 - remaining kept - } - } - } - remaining to @dest2 - } - ) - `) - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "world", - "dest1", - big.NewInt(1), - "GEM", - }, - { - "world", - "dest2", - big.NewInt(90), // the 90% of 100GEM - "GEM", - }, - }, - } - test(t, tc) -} - -func TestNestedRemainingComplex(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [EUR/2 10000] ( - source = @orders:1234 - destination = { - 15% to { - 20% to @platform:commission:sales_tax - remaining to { - 5% to { - // users - max [EUR/2 1000] to @users:1234:cashback - remaining kept - } - remaining to @platform:commission:revenue - } - } - remaining to @merchants:6789 - } - ) - `) - tc.setBalance("orders:1234", "EUR/2", 10000) - - tc.expected = CaseResult{ - Postings: []machine.Posting{ - // 15% of 10000 == 1500 - - // inside the 20% branch: - { - "orders:1234", - "platform:commission:sales_tax", - big.NewInt(300), - "EUR/2", - }, - - // 5% of 1200 is 60 - { - "orders:1234", - "users:1234:cashback", - big.NewInt(60), // cap doesn't apply here - "EUR/2", - }, - - // 95% of 1200 is 1140 - { - "orders:1234", - "platform:commission:revenue", - big.NewInt(1140), // cap doesn't apply here - "EUR/2", - }, - - // we are left with 85% of 10000 == 8500 - { - "orders:1234", - "merchants:6789", - big.NewInt(8500), - "EUR/2", - }, - }, - } - test(t, tc) -} - -func TestTrackBalancesTricky(t *testing.T) { - t.Skip() - - tc := NewTestCase() - tc.setBalance("src", "COIN", 5) - tc.compile(t, ` - send [COIN 25] ( // send 10 + 15 - source= { - max [COIN 10] from @world - @src // src only has 5 before the program starts - } - destination = { - max [COIN 10] to @src - remaining to @dest // but @src needs to send 15 here - } - ) - `) - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "world", - "src", - big.NewInt(10), - "GEM", - }, - { - "src", - "dest", - big.NewInt(15), - "GEM", - }, - }, - } - test(t, tc) -} - -func TestZeroPostings(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - send [COIN 100] ( - source = { - @a - @world - } - destination = @dest - ) - `) - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "world", - "dest", - big.NewInt(100), - "COIN", - }, - }, - } - test(t, tc) -} - -func TestUnboundedOverdraftWhenNotEnoughFunds(t *testing.T) { - tc := NewTestCase() - tc.setBalance("users:2345:main", "USD/2", 8000) - tc.compile(t, ` - send [USD/2 100] ( - source = @empty allowing unbounded overdraft - destination = @dest - ) - `) - - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "empty", - "dest", - big.NewInt(100), - "USD/2", - }, - }, - } - test(t, tc) -} - -// Numscript playground examples -func TestOvedraftsPlaygroundExample(t *testing.T) { - tc := NewTestCase() - tc.setBalance("users:2345:main", "USD/2", 8000) - tc.compile(t, ` - send [USD/2 100] ( - source = @users:1234 allowing unbounded overdraft - destination = @payments:4567 - ) - - send [USD/2 6000] ( - source = { - // let the user pay with their credit account first, - @users:2345:credit allowing overdraft up to [USD/2 1000] - // then, use their main balance - @users:2345:main - } - destination = @payments:4567 - ) - `) - - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "users:1234", - "payments:4567", - big.NewInt(100), - "USD/2", - }, - - { - "users:2345:credit", - "payments:4567", - big.NewInt(1000), - "USD/2", - }, - { - "users:2345:main", - "payments:4567", - big.NewInt(5000), - "USD/2", - }, - }, - } - test(t, tc) -} - -func TestCascadingSources(t *testing.T) { - tc := NewTestCase() - tc.setBalance("users:1234:main", "USD/2", 5000) - tc.setBalance("users:1234:vouchers:2024-01-31", "USD/2", 1000) - tc.setBalance("users:1234:vouchers:2024-02-17", "USD/2", 3000) - tc.setBalance("users:1234:vouchers:2024-03-22", "USD/2", 10000) - - tc.compile(t, ` - send [USD/2 10000] ( - source = { - // first, pull from the user balance - @users:1234:main - // then, pull from the user's vouchers, - // fairly using the ones that expire first - @users:1234:vouchers:2024-01-31 - @users:1234:vouchers:2024-02-17 - @users:1234:vouchers:2024-03-22 - } - destination = @orders:4567:payment - ) - `) - - tc.expected = CaseResult{ - Postings: []machine.Posting{ - { - "users:1234:main", - "orders:4567:payment", - big.NewInt(5000), - "USD/2", - }, - { - "users:1234:vouchers:2024-01-31", - "orders:4567:payment", - big.NewInt(1000), - "USD/2", - }, - { - "users:1234:vouchers:2024-02-17", - "orders:4567:payment", - big.NewInt(3000), - "USD/2", - }, - { - "users:1234:vouchers:2024-03-22", - "orders:4567:payment", - big.NewInt(1000), - "USD/2", - }, - }, - } - test(t, tc) -} - -func TestUseBalanceTwice(t *testing.T) { - tc := NewTestCase() - tc.compile(t, ` - vars { monetary $v = balance(@src, COIN) } - - send $v ( - source = @src - destination = @dest - )`) - - tc.setBalance("src", "COIN", 50) - tc.expected = CaseResult{ - - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(50), - Source: "src", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestBigInt(t *testing.T) { - script := ` - vars { number $amt } - - send [USD/2 $amt] ( - source = @world - destination = { - 100% to @dest - remaining kept - } - ) - - ` - - tc := NewTestCase() - tc.compile(t, script) - - // max safe int is 9223372036854775807 - // this number is 99999223372036854775807 - - amt, ok := new(big.Int).SetString("99999223372036854775807", 10) - if !ok { - panic("Invalid number") - } - tc.vars = map[string]string{ - "amt": amt.String(), - } - - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/2", - Amount: amt, - Source: "world", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestInvalidNumberLiteral(t *testing.T) { - script := ` - vars { number $amt } - - send [$amt USD/2] ( - source = @world - destination = @dest - ) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.vars = map[string]string{ - "amt": "not a number", - } - - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.InvalidNumberLiteral{Range: parser.Range{}, Source: "not a number"}, - } - test(t, tc) -} - -func TestBigIntMonetary(t *testing.T) { - script := ` - vars { monetary $amt } - - send $amt ( - source = @world - destination = { - 100% to @dest - remaining kept - } - ) - - ` - - tc := NewTestCase() - tc.compile(t, script) - - amt, ok := new(big.Int).SetString("99999223372036854775807", 10) - if !ok { - panic("Invalid number") - } - tc.vars = map[string]string{ - "amt": "USD/123 " + amt.String(), - } - - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD/123", - Amount: amt, - Source: "world", - Destination: "dest", - }, - }, - Error: nil, - } - test(t, tc) -} - -func TestSaveFromAccount(t *testing.T) { - - t.Run("simple", func(t *testing.T) { - script := ` - save [USD 10] from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(20), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("save causes failure", func(t *testing.T) { - script := ` - save [USD/2 1] from @alice - - send [USD/2 30] ( - source = @alice - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "USD/2", 30) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.MissingFundsErr{ - Asset: "USD/2", - Needed: *big.NewInt(30), - Available: *big.NewInt(29), - }, - } - test(t, tc) - }) - - t.Run("save all", func(t *testing.T) { - script := ` - save [USD *] from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - // 0-posting omitted - { - Asset: "USD", - Amount: big.NewInt(30), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("save more than balance", func(t *testing.T) { - script := ` - save [USD 30] from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - // 0-posting omitted - { - Asset: "USD", - Amount: big.NewInt(30), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("with asset var", func(t *testing.T) { - script := ` - vars { - asset $ass - } - save [$ass 10] from @alice - - send [$ass 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.vars = map[string]string{ - "ass": "USD", - } - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(20), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("with monetary var", func(t *testing.T) { - script := ` - vars { - monetary $mon - } - - save $mon from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.vars = map[string]string{ - "mon": "USD 10", - } - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(20), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("multi postings", func(t *testing.T) { - script := ` - send [USD 10] ( - source = @alice - destination = @bob - ) - - save [USD 5] from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(5), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(25), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("save a different asset", func(t *testing.T) { - script := ` - save [COIN 100] from @alice - - send [USD 30] ( - source = { - @alice - @world - } - destination = @bob - )` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("alice", "COIN", 100) - tc.setBalance("alice", "USD", 20) - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "USD", - Amount: big.NewInt(20), - Source: "alice", - Destination: "bob", - }, - { - Asset: "USD", - Amount: big.NewInt(10), - Source: "world", - Destination: "bob", - }, - }, - Error: nil, - } - test(t, tc) - }) - - t.Run("negative amount", func(t *testing.T) { - script := ` - - save [USD -100] from @A` - tc := NewTestCase() - tc.compile(t, script) - tc.setBalance("A", "USD", -100) - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.NegativeAmountErr{ - Amount: machine.NewMonetaryInt(-100), - }, - } - test(t, tc) - }) -} - -func TestAddMonetariesSameCurrency(t *testing.T) { - script := ` - send [COIN 1] + [COIN 2] ( - source = @world - destination = @dest - ) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Postings: []Posting{ - { - Asset: "COIN", - Amount: big.NewInt(1 + 2), - Source: "world", - Destination: "dest", - }, - }, - } - test(t, tc) -} - -func TestAddNumbers(t *testing.T) { - script := ` - set_tx_meta("k", 1 + 2) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - TxMetadata: map[string]machine.Value{ - "k": machine.NewMonetaryInt(1 + 2), - }, - } - test(t, tc) -} - -func TestAddNumbersInvalidRightType(t *testing.T) { - script := ` - set_tx_meta("k", 1 + "not a number") - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Error: machine.TypeError{ - Expected: "number", - Value: machine.String("not a number"), - }, - } - test(t, tc) -} - -func TestAddMonetariesDifferentCurrencies(t *testing.T) { - script := ` - send [USD/2 1] + [EUR/2 2] ( - source = @world - destination = @dest - ) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.MismatchedCurrencyError{ - Expected: "USD/2", - Got: "EUR/2", - }, - } - test(t, tc) -} - -func TestAddInvalidLeftType(t *testing.T) { - script := ` - set_tx_meta("k", EUR/2 + EUR/3) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Postings: []Posting{}, - Error: machine.TypeError{ - Expected: "monetary|number", - Value: machine.Asset("EUR/2"), - }, - } - test(t, tc) -} - -func TestSubNumbers(t *testing.T) { - script := ` - set_tx_meta("k", 10 - 1) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Postings: []Posting{}, - TxMetadata: map[string]machine.Value{ - "k": machine.NewMonetaryInt(10 - 1), - }, - } - test(t, tc) -} - -func TestSubMonetaries(t *testing.T) { - script := ` - set_tx_meta("k", [USD/2 10] - [USD/2 3]) - ` - - tc := NewTestCase() - tc.compile(t, script) - - tc.expected = CaseResult{ - Postings: []Posting{}, - TxMetadata: map[string]machine.Value{ - "k": machine.Monetary{ - Amount: machine.NewMonetaryInt(10 - 3), - Asset: "USD/2", - }, - }, - } - test(t, tc) -} diff --git a/internal/interpreter/portion_test.go b/internal/interpreter/portion_test.go deleted file mode 100644 index 37879b6..0000000 --- a/internal/interpreter/portion_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package interpreter_test - -import ( - "math/big" - "strings" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/interpreter" -) - -func TestBetween0And1Inclusive(t *testing.T) { - tests := []struct { - in string - want *big.Rat - wantErr bool - }{ - { - in: "0%", - want: big.NewRat(0, 1), - }, - { - in: "0.0%", - want: big.NewRat(0, 1), - }, - { - in: "0/1", - want: big.NewRat(0, 1), - }, - { - in: "0/25", - want: big.NewRat(0, 1), - }, - { - in: "0/100", - want: big.NewRat(0, 1), - }, - { - in: "1%", - want: big.NewRat(1, 100), - }, - { - in: "1/100", - want: big.NewRat(1, 100), - }, - { - in: "10/1000", - want: big.NewRat(1, 100), - }, - { - in: "50/100", - want: big.NewRat(50, 100), - }, - { - in: "50%", - want: big.NewRat(50, 100), - }, - { - in: "50.0%", - want: big.NewRat(50, 100), - }, - { - in: "1/1", - want: big.NewRat(1, 1), - }, - { - in: "100/100", - want: big.NewRat(1, 1), - }, - { - in: "100.0%", - want: big.NewRat(1, 1), - }, - { - in: "100%", - want: big.NewRat(1, 1), - }, - // Now for the failures. We don't check negative numbers in this test because - // those are a parsing failure, not a range failure. - { - in: "100.1%", - wantErr: true, - }, - { - in: "101%", - wantErr: true, - }, - { - in: "101/100", - wantErr: true, - }, - { - in: "2/1", - wantErr: true, - }, - { - in: "3/2", - wantErr: true, - }, - } - - for _, test := range tests { - t.Run(test.in, func(t *testing.T) { - got, err := interpreter.ParsePortionSpecific(test.in) - if test.wantErr { - if err == nil { - t.Fatal("should have errored") - } - if !strings.Contains(err.Error(), "between") { - t.Fatal("wrong error") - } - return - } - if err != nil { - t.Fatalf("ParsePortionSpecific(%q): %v", test.in, err) - } - if test.want.Cmp(got) != 0 { - t.Fatalf("ParsePortionSpecific(%q) = %q, want %q", test.in, got, test.want) - } - }) - } -} - -func TestInvalidFormat(t *testing.T) { - _, err := interpreter.ParsePortionSpecific("this is not a portion") - if err == nil { - t.Fatal("should have errored") - } - if !strings.Contains(err.Error(), "format") { - t.Fatal("wrong error") - } -} diff --git a/internal/interpreter/reconciler.go b/internal/interpreter/reconciler.go deleted file mode 100644 index 49ab8e4..0000000 --- a/internal/interpreter/reconciler.go +++ /dev/null @@ -1,136 +0,0 @@ -package interpreter - -import ( - "fmt" - "math/big" - "slices" -) - -type Posting struct { - Source string `json:"source"` - Destination string `json:"destination"` - Amount *big.Int `json:"amount"` - Asset string `json:"asset"` -} - -type ReconcileError struct { - Receiver Receiver - Receivers []Receiver -} - -func (e ReconcileError) Error() string { - return fmt.Sprintf("Error reconciling senders and getters (receiver = %#v ; receivers = %v)", e.Receiver, e.Receivers) -} - -type Sender struct { - Name string - Monetary *big.Int -} - -type Receiver struct { - Name string - Monetary *big.Int -} - -func Reconcile(asset string, senders []Sender, receivers []Receiver) ([]Posting, InterpreterError) { - var sendersFiltered []Sender - for _, e := range senders { - if e.Monetary.Cmp(big.NewInt(0)) != 0 { - sendersFiltered = append(sendersFiltered, e) - } - } - senders = sendersFiltered - - // We reverse senders and receivers once so that we can - // treat them as stack and push/pop in O(1) - slices.Reverse(senders) - slices.Reverse(receivers) - var postings []Posting - - for { - receiver, empty := popStack(&receivers) - if empty { - break - } - - // Ugly workaround - if receiver.Name == "" { - sender, empty := popStack(&senders) - if !empty { - var newMon big.Int - newMon.Sub(sender.Monetary, receiver.Monetary) - senders = append(senders, Sender{ - Name: sender.Name, - Monetary: &newMon, - }) - } - continue - } - - sender, empty := popStack(&senders) - if empty { - isReceivedAmtZero := receiver.Monetary.Cmp(big.NewInt(0)) == 0 - if isReceivedAmtZero { - return postings, nil - } - - return postings, nil - } - - snd := (*big.Int)(sender.Monetary) - - var postingAmount big.Int - switch snd.Cmp(receiver.Monetary) { - case 0: /* sender.Monetary == receiver.Monetary */ - postingAmount = *sender.Monetary - case -1: /* sender.Monetary < receiver.Monetary */ - var monetary big.Int - receivers = append(receivers, Receiver{ - Name: receiver.Name, - Monetary: monetary.Sub(receiver.Monetary, sender.Monetary), - }) - postingAmount = *sender.Monetary - case 1: /* sender.Monetary > receiver.Monetary */ - var monetary big.Int - senders = append(senders, Sender{ - Name: sender.Name, - Monetary: monetary.Sub(sender.Monetary, receiver.Monetary), - }) - postingAmount = *receiver.Monetary - } - - var postingToMerge *Posting - if len(postings) != 0 { - posting := &postings[len(postings)-1] - if posting.Source == sender.Name && posting.Destination == receiver.Name { - postingToMerge = posting - } - } - - if postingToMerge == nil { - postings = append(postings, Posting{ - Source: sender.Name, - Destination: receiver.Name, - Amount: &postingAmount, - Asset: asset, - }) - } else { - // postingToMerge.Amount += postingAmount - postingToMerge.Amount.Add(postingToMerge.Amount, &postingAmount) - } - } - - return postings, nil -} - -func popStack[T any](stack *[]T) (T, bool) { - l := len(*stack) - if l == 0 { - var t T - return t, true - } - - popped := (*stack)[l-1] - *stack = (*stack)[:l-1] - return popped, false -} diff --git a/internal/interpreter/reconciler_test.go b/internal/interpreter/reconciler_test.go deleted file mode 100644 index d4b41dc..0000000 --- a/internal/interpreter/reconciler_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package interpreter - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type ReconcileTestCase struct { - Currency string - - Senders []Sender - Receivers []Receiver - Expected []Posting - ExpectedErr error -} - -func runReconcileTestCase(t *testing.T, tc ReconcileTestCase) { - t.Parallel() - if tc.Currency == "" { - tc.Currency = "COIN" - } - - got, err := Reconcile(tc.Currency, tc.Senders, tc.Receivers) - - require.Equal(t, tc.ExpectedErr, err) - assert.Equal(t, tc.Expected, got) -} - -func TestReconcileEmpty(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{}) -} - -func TestReconcileSingletonExactMatch(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "COIN", - Senders: []Sender{{"src", big.NewInt(10)}}, - Receivers: []Receiver{{"dest", big.NewInt(10)}}, - Expected: []Posting{{"src", "dest", big.NewInt(10), "COIN"}}, - }) -} - -func TestReconcileZero(t *testing.T) { - // TODO double check - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "COIN", - Senders: []Sender{{"src", big.NewInt(0)}}, - Receivers: []Receiver{{"dest", big.NewInt(0)}}, - Expected: nil, - // []Posting{ - // // {"src", "dest", big.NewInt(0), "COIN"} - // }, - }) -} - -func TestNoReceiversLeft(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Senders: []Sender{{ - "src", - big.NewInt(10), - }}, - }) -} - -func TestReconcileSendersRemainder(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "EUR", - Senders: []Sender{{"src", big.NewInt(100)}}, - Receivers: []Receiver{ - { - "d1", - big.NewInt(70), - }, - { - "d2", - big.NewInt(30), - }}, - Expected: []Posting{ - {"src", "d1", big.NewInt(70), "EUR"}, - {"src", "d2", big.NewInt(30), "EUR"}, - }, - }) -} - -func TestReconcileWhenSendersAreSplit(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "EUR", - Senders: []Sender{ - {"s1", big.NewInt(20)}, - {"s2", big.NewInt(30)}, - }, - Receivers: []Receiver{{"d", big.NewInt(50)}}, - Expected: []Posting{ - {"s1", "d", big.NewInt(20), "EUR"}, - {"s2", "d", big.NewInt(30), "EUR"}, - }, - }) -} - -func TestMany(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "EUR", - Senders: []Sender{ - {"s1", big.NewInt(80 + 20)}, - {"s2", big.NewInt(1000)}, - }, - Receivers: []Receiver{ - {"d1", big.NewInt(80)}, - {"d2", big.NewInt(20 + 123)}, - }, - Expected: []Posting{ - {"s1", "d1", big.NewInt(80), "EUR"}, - {"s1", "d2", big.NewInt(20), "EUR"}, - {"s2", "d2", big.NewInt(123), "EUR"}, - }, - }) -} - -func TestReconcileManySendersManyReceivers(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "EUR", - Senders: []Sender{ - {"s1", big.NewInt(80 + 20)}, - {"s2", big.NewInt(1000)}, - }, - Receivers: []Receiver{ - {"d1", big.NewInt(80)}, - {"d2", big.NewInt(20 + 123)}, - }, - Expected: []Posting{ - {"s1", "d1", big.NewInt(80), "EUR"}, - {"s1", "d2", big.NewInt(20), "EUR"}, - {"s2", "d2", big.NewInt(123), "EUR"}, - }, - }) -} - -func TestReconcileOverlapping(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "EUR", - Senders: []Sender{ - {"src1", big.NewInt(1)}, - {"src2", big.NewInt(10)}, - {"src2", big.NewInt(20)}, - }, - Receivers: []Receiver{{"d", big.NewInt(31)}}, - Expected: []Posting{ - {"src1", "d", big.NewInt(1), "EUR"}, - {"src2", "d", big.NewInt(30), "EUR"}, - }, - }) -} - -func TestReconcileKept(t *testing.T) { - runReconcileTestCase(t, ReconcileTestCase{ - Currency: "GEM", - Senders: []Sender{ - {"src", big.NewInt(100)}, - }, - Receivers: []Receiver{ - {"dest", big.NewInt(50)}, - {"", big.NewInt(50)}}, - Expected: []Posting{ - {"src", "dest", big.NewInt(50), "GEM"}, - }, - }) -} diff --git a/internal/interpreter/utils.go b/internal/interpreter/utils.go deleted file mode 100644 index a32bf66..0000000 --- a/internal/interpreter/utils.go +++ /dev/null @@ -1,11 +0,0 @@ -package interpreter - -func defaultMapGet[T any](m map[string]T, key string, getDefault func() T) T { - lookup, ok := m[key] - if !ok { - default_ := getDefault() - m[key] = default_ - return default_ - } - return lookup -} diff --git a/internal/interpreter/value.go b/internal/interpreter/value.go deleted file mode 100644 index a481ff0..0000000 --- a/internal/interpreter/value.go +++ /dev/null @@ -1,229 +0,0 @@ -package interpreter - -import ( - "fmt" - "math/big" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" -) - -type Value interface { - value() - String() string -} - -type String string -type Asset string -type Portion big.Rat -type AccountAddress string -type MonetaryInt big.Int -type Monetary struct { - Amount MonetaryInt - Asset Asset -} - -func (String) value() {} -func (AccountAddress) value() {} -func (MonetaryInt) value() {} -func (Monetary) value() {} -func (Portion) value() {} -func (Asset) value() {} - -func (v MonetaryInt) MarshalJSON() ([]byte, error) { - bigInt := big.Int(v) - s := fmt.Sprintf(`"%s"`, bigInt.String()) - return []byte(s), nil -} - -func (v Portion) MarshalJSON() ([]byte, error) { - r := big.Rat(v) - s := fmt.Sprintf(`"%s"`, r.String()) - return []byte(s), nil -} - -func (v Monetary) MarshalJSON() ([]byte, error) { - m := fmt.Sprintf("\"%s %s\"", v.Asset, v.Amount.String()) - return []byte(m), nil -} - -func (v String) String() string { - return string(v) -} - -func (v AccountAddress) String() string { - return string(v) -} - -func (v MonetaryInt) String() string { - i := big.Int(v) - return i.String() -} - -func (v Monetary) String() string { - return fmt.Sprintf("%s %s", v.Asset, v.Amount) -} - -func (p Portion) String() string { - r := big.Rat(p) - return r.String() -} - -func (v Asset) String() string { - return string(v) -} - -func expectMonetary(v Value, r parser.Range) (*Monetary, InterpreterError) { - switch v := v.(type) { - case Monetary: - return &v, nil - - default: - return nil, TypeError{Expected: analysis.TypeMonetary, Value: v, Range: r} - } -} - -func expectMonetaryOfAsset(expectedAsset string) func(Value, parser.Range) (*big.Int, InterpreterError) { - return func(v Value, r parser.Range) (*big.Int, InterpreterError) { - m, err := expectMonetary(v, r) - if err != nil { - return nil, err - } - - asset := string(m.Asset) - - if asset != expectedAsset { - return nil, MismatchedCurrencyError{Expected: expectedAsset, Got: asset} - } - - i := big.Int(m.Amount) - return &i, nil - } -} - -func expectNumber(v Value, r parser.Range) (*big.Int, InterpreterError) { - switch v := v.(type) { - case MonetaryInt: - return (*big.Int)(&v), nil - - default: - return nil, TypeError{Expected: analysis.TypeNumber, Value: v, Range: r} - } -} - -func expectString(v Value, r parser.Range) (*string, InterpreterError) { - switch v := v.(type) { - case String: - return (*string)(&v), nil - - default: - return nil, TypeError{Expected: analysis.TypeString, Value: v, Range: r} - } -} - -func expectAsset(v Value, r parser.Range) (*string, InterpreterError) { - switch v := v.(type) { - case Asset: - return (*string)(&v), nil - - default: - return nil, TypeError{Expected: analysis.TypeAsset, Value: v, Range: r} - } -} - -func expectAccount(v Value, r parser.Range) (*string, InterpreterError) { - switch v := v.(type) { - case AccountAddress: - return (*string)(&v), nil - - default: - return nil, TypeError{Expected: analysis.TypeAccount, Value: v, Range: r} - } -} - -func expectPortion(v Value, r parser.Range) (*big.Rat, InterpreterError) { - switch v := v.(type) { - case Portion: - return (*big.Rat)(&v), nil - - default: - return nil, TypeError{Expected: analysis.TypePortion, Value: v, Range: r} - } -} - -func expectAnything(v Value, _ parser.Range) (*Value, InterpreterError) { - return &v, nil -} - -func expectOneOf[T any](combinators ...func(v Value, r parser.Range) (*T, InterpreterError)) func(v Value, r parser.Range) (*T, InterpreterError) { - return func(v Value, r parser.Range) (*T, InterpreterError) { - if len(combinators) == 0 { - // this should be unreachable - panic("Invalid argument: no combinators given") - } - - var errs []TypeError - for _, combinator := range combinators { - out, err := combinator(v, r) - if err == nil { - return out, nil - } - - typeErr, ok := err.(TypeError) - if !ok { - return nil, err - } - errs = append(errs, typeErr) - } - - // e.g. typeErr.map(e => e.Expected).join("|") - expected := "" - for index, typeErr := range errs { - if index != 0 { - expected += "|" - } - expected += typeErr.Expected - } - - return nil, TypeError{ - Range: r, - Value: v, - Expected: expected, - } - } -} - -func expectMapped[T any, U any]( - combinator func(v Value, r parser.Range) (*T, InterpreterError), - mapper func(value T) U, -) func(v Value, r parser.Range) (*U, InterpreterError) { - return func(v Value, r parser.Range) (*U, InterpreterError) { - out, err := combinator(v, r) - if err != nil { - return nil, err - } - mapped := mapper(*out) - return &mapped, nil - } -} - -func NewMonetaryInt(n int64) MonetaryInt { - bi := big.NewInt(n) - return MonetaryInt(*bi) -} - -func (m MonetaryInt) Add(other MonetaryInt) MonetaryInt { - bi := big.Int(m) - otherBi := big.Int(other) - - sum := new(big.Int).Add(&bi, &otherBi) - return MonetaryInt(*sum) -} - -func (m MonetaryInt) Sub(other MonetaryInt) MonetaryInt { - bi := big.Int(m) - otherBi := big.Int(other) - - sum := new(big.Int).Sub(&bi, &otherBi) - return MonetaryInt(*sum) -} diff --git a/internal/interpreter/value_test.go b/internal/interpreter/value_test.go deleted file mode 100644 index 2d47921..0000000 --- a/internal/interpreter/value_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package interpreter_test - -import ( - "encoding/json" - "math/big" - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - - "github.com/stretchr/testify/require" -) - -func TestMarshalMonetaryInt(t *testing.T) { - t.Parallel() - - x := interpreter.NewMonetaryInt(42) - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"42"`) -} - -func TestMarshalString(t *testing.T) { - t.Parallel() - - x := interpreter.String("abc") - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"abc"`) -} - -func TestMarshalAsset(t *testing.T) { - t.Parallel() - - x := interpreter.Asset("EUR/2") - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"EUR/2"`) -} - -func TestMarshalAddress(t *testing.T) { - t.Parallel() - - x := interpreter.AccountAddress("abc") - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"abc"`) -} - -func TestMarshalPortion(t *testing.T) { - t.Parallel() - - x := interpreter.Portion(*big.NewRat(2, 3)) - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"2/3"`) -} - -func TestMarshalMonetary(t *testing.T) { - t.Parallel() - - x := interpreter.Monetary{ - Asset: interpreter.Asset("USD/2"), - Amount: interpreter.NewMonetaryInt(100), - } - - j, err := json.Marshal(x) - require.Nil(t, err) - require.Equal(t, string(j), `"USD/2 100"`) -} diff --git a/internal/lsp/bindings.go b/internal/lsp/bindings.go deleted file mode 100644 index 1abcd21..0000000 --- a/internal/lsp/bindings.go +++ /dev/null @@ -1,5670 +0,0 @@ -package lsp - -// Taken from gopls internal lsp package -// and fixed to make omitempty work - -// Copyright (c) 2009 The Go Authors. All rights reserved. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: - -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. - -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Package protocol contains data types and code for LSP jsonrpcs -// generated automatically from vscode-languageserver-node -// commit: 0cb3812e7d540ef3a904e96df795bc37a21de9b0 -// last fetched Mon Aug 02 2021 10:08:19 GMT-0400 (Eastern Daylight Time) - - -// Code generated (see typescript/README.md) DO NOT EDIT. - -import "encoding/json" - -/** - * A special text edit with an additional change annotation. - * - * @since 3.16.0. - */ -type AnnotatedTextEdit struct { - /** - * The actual identifier of the change annotation - */ - AnnotationID ChangeAnnotationIdentifier `json:"annotationId"` - TextEdit -} - -/** - * The parameters passed via a apply workspace edit request. - */ -type ApplyWorkspaceEditParams struct { - /** - * An optional label of the workspace edit. This label is - * presented in the user interface for example on an undo - * stack to undo the workspace edit. - */ - Label string `json:"label,omitempty"` - /** - * The edits to apply. - */ - Edit WorkspaceEdit `json:"edit"` -} - -/** - * A response returned from the apply workspace edit request. - */ -type ApplyWorkspaceEditResponse struct { - /** - * Indicates whether the edit was applied or not. - */ - Applied bool `json:"applied"` - /** - * An optional textual description for why the edit was not applied. - * This may be used by the server for diagnostic logging or to provide - * a suitable error for a request that triggered the edit. - */ - FailureReason string `json:"failureReason,omitempty"` - /** - * Depending on the client's failure handling strategy `failedChange` might - * contain the index of the change that failed. This property is only available - * if the client signals a `failureHandlingStrategy` in its client capabilities. - */ - FailedChange uint32 `json:"failedChange,omitempty"` -} - -/** - * @since 3.16.0 - */ -type CallHierarchyClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` - * return value for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Represents an incoming call, e.g. a caller of a method or constructor. - * - * @since 3.16.0 - */ -type CallHierarchyIncomingCall struct { - /** - * The item that makes the call. - */ - From CallHierarchyItem `json:"from"` - /** - * The ranges at which the calls appear. This is relative to the caller - * denoted by [`this.from`](#CallHierarchyIncomingCall.from). - */ - FromRanges []Range `json:"fromRanges"` -} - -/** - * The parameter of a `callHierarchy/incomingCalls` request. - * - * @since 3.16.0 - */ -type CallHierarchyIncomingCallsParams struct { - Item CallHierarchyItem `json:"item"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * Represents programming constructs like functions or constructors in the context - * of call hierarchy. - * - * @since 3.16.0 - */ -type CallHierarchyItem struct { - /** - * The name of this item. - */ - Name string `json:"name"` - /** - * The kind of this item. - */ - Kind SymbolKind `json:"kind"` - /** - * Tags for this item. - */ - Tags []SymbolTag `json:"tags,omitempty"` - /** - * More detail for this item, e.g. the signature of a function. - */ - Detail string `json:"detail,omitempty"` - /** - * The resource identifier of this item. - */ - URI DocumentURI `json:"uri"` - /** - * The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. - */ - Range Range `json:"range"` - /** - * The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. - * Must be contained by the [`range`](#CallHierarchyItem.range). - */ - SelectionRange Range `json:"selectionRange"` - /** - * A data entry field that is preserved between a call hierarchy prepare and - * incoming calls or outgoing calls requests. - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * Call hierarchy options used during static registration. - * - * @since 3.16.0 - */ -type CallHierarchyOptions struct { - WorkDoneProgressOptions -} - -/** - * Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. - * - * @since 3.16.0 - */ -type CallHierarchyOutgoingCall struct { - /** - * The item that is called. - */ - To CallHierarchyItem `json:"to"` - /** - * The range at which this item is called. This is the range relative to the caller, e.g the item - * passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls) - * and not [`this.to`](#CallHierarchyOutgoingCall.to). - */ - FromRanges []Range `json:"fromRanges"` -} - -/** - * The parameter of a `callHierarchy/outgoingCalls` request. - * - * @since 3.16.0 - */ -type CallHierarchyOutgoingCallsParams struct { - Item CallHierarchyItem `json:"item"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * The parameter of a `textDocument/prepareCallHierarchy` request. - * - * @since 3.16.0 - */ -type CallHierarchyPrepareParams struct { - TextDocumentPositionParams - WorkDoneProgressParams -} - -/** - * Call hierarchy options used during static or dynamic registration. - * - * @since 3.16.0 - */ -type CallHierarchyRegistrationOptions struct { - TextDocumentRegistrationOptions - CallHierarchyOptions - StaticRegistrationOptions -} - -type CancelParams struct { - /** - * The request id to cancel. - */ - ID interface{} /*number | string*/ `json:"id"` -} - -/** - * Additional information that describes document changes. - * - * @since 3.16.0 - */ -type ChangeAnnotation struct { - /** - * A human-readable string describing the actual change. The string - * is rendered prominent in the user interface. - */ - Label string `json:"label"` - /** - * A flag which indicates that user confirmation is needed - * before applying the change. - */ - NeedsConfirmation bool `json:"needsConfirmation,omitempty"` - /** - * A human-readable string which is rendered less prominent in - * the user interface. - */ - Description string `json:"description,omitempty"` -} - -/** - * An identifier to refer to a change annotation stored with a workspace edit. - */ -type ChangeAnnotationIdentifier = string - -type ClientCapabilities struct { - /** - * The workspace client capabilities - */ - Workspace Workspace2Gn `json:"workspace,omitempty"` - /** - * Text document specific client capabilities. - */ - TextDocument TextDocumentClientCapabilities `json:"textDocument,omitempty"` - /** - * Window specific client capabilities. - */ - Window struct { - /** - * Whether client supports server initiated progress using the - * `window/workDoneProgress/create` request. - * - * Since 3.15.0 - */ - WorkDoneProgress bool `json:"workDoneProgress,omitempty"` - /** - * Capabilities specific to the showMessage request. - * - * @since 3.16.0 - */ - ShowMessage ShowMessageRequestClientCapabilities `json:"showMessage,omitempty"` - /** - * Capabilities specific to the showDocument request. - * - * @since 3.16.0 - */ - ShowDocument ShowDocumentClientCapabilities `json:"showDocument,omitempty"` - } `json:"window,omitempty"` - /** - * General client capabilities. - * - * @since 3.16.0 - */ - General GeneralClientCapabilities `json:"general,omitempty"` - /** - * Experimental client capabilities. - */ - Experimental interface{} `json:"experimental,omitempty"` -} - -/** - * A code action represents a change that can be performed in code, e.g. to fix a problem or - * to refactor code. - * - * A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. - */ -type CodeAction struct { - /** - * A short, human-readable, title for this code action. - */ - Title string `json:"title"` - /** - * The kind of the code action. - * - * Used to filter code actions. - */ - Kind CodeActionKind `json:"kind,omitempty"` - /** - * The diagnostics that this code action resolves. - */ - Diagnostics []Diagnostic `json:"diagnostics,omitempty"` - /** - * Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted - * by keybindings. - * - * A quick fix should be marked preferred if it properly addresses the underlying error. - * A refactoring should be marked preferred if it is the most reasonable choice of actions to take. - * - * @since 3.15.0 - */ - IsPreferred bool `json:"isPreferred,omitempty"` - /** - * Marks that the code action cannot currently be applied. - * - * Clients should follow the following guidelines regarding disabled code actions: - * - * - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) - * code action menu. - * - * - Disabled actions are shown as faded out in the code action menu when the user request a more specific type - * of code action, such as refactorings. - * - * - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) - * that auto applies a code action and only a disabled code actions are returned, the client should show the user an - * error message with `reason` in the editor. - * - * @since 3.16.0 - */ - Disabled *struct { - /** - * Human readable description of why the code action is currently disabled. - * - * This is displayed in the code actions UI. - */ - Reason string `json:"reason"` - } `json:"disabled,omitempty"` - /** - * The workspace edit this code action performs. - */ - Edit WorkspaceEdit `json:"edit,omitempty"` - /** - * A command this code action executes. If a code action - * provides a edit and a command, first the edit is - * executed and then the command. - */ - Command *Command `json:"command,omitempty"` - /** - * A data entry field that is preserved on a code action between - * a `textDocument/codeAction` and a `codeAction/resolve` request. - * - * @since 3.16.0 - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * The Client Capabilities of a [CodeActionRequest](#CodeActionRequest). - */ -type CodeActionClientCapabilities struct { - /** - * Whether code action supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client support code action literals of type `CodeAction` as a valid - * response of the `textDocument/codeAction` request. If the property is not - * set the request can only return `Command` literals. - * - * @since 3.8.0 - */ - CodeActionLiteralSupport struct { - /** - * The code action kind is support with the following value - * set. - */ - CodeActionKind struct { - /** - * The code action kind values the client supports. When this - * property exists the client also guarantees that it will - * handle values outside its set gracefully and falls back - * to a default value when unknown. - */ - ValueSet []CodeActionKind `json:"valueSet"` - } `json:"codeActionKind"` - } `json:"codeActionLiteralSupport,omitempty"` - /** - * Whether code action supports the `isPreferred` property. - * - * @since 3.15.0 - */ - IsPreferredSupport bool `json:"isPreferredSupport,omitempty"` - /** - * Whether code action supports the `disabled` property. - * - * @since 3.16.0 - */ - DisabledSupport bool `json:"disabledSupport,omitempty"` - /** - * Whether code action supports the `data` property which is - * preserved between a `textDocument/codeAction` and a - * `codeAction/resolve` request. - * - * @since 3.16.0 - */ - DataSupport bool `json:"dataSupport,omitempty"` - /** - * Whether the client support resolving additional code action - * properties via a separate `codeAction/resolve` request. - * - * @since 3.16.0 - */ - ResolveSupport struct { - /** - * The properties that a client can resolve lazily. - */ - Properties []string `json:"properties"` - } `json:"resolveSupport,omitempty"` - /** - * Whether th client honors the change annotations in - * text edits and resource operations returned via the - * `CodeAction#edit` property by for example presenting - * the workspace edit in the user interface and asking - * for confirmation. - * - * @since 3.16.0 - */ - HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitempty"` -} - -/** - * Contains additional diagnostic information about the context in which - * a [code action](#CodeActionProvider.provideCodeActions) is run. - */ -type CodeActionContext struct { - /** - * An array of diagnostics known on the client side overlapping the range provided to the - * `textDocument/codeAction` request. They are provided so that the server knows which - * errors are currently presented to the user for the given range. There is no guarantee - * that these accurately reflect the error state of the resource. The primary parameter - * to compute code actions is the provided range. - */ - Diagnostics []Diagnostic `json:"diagnostics"` - /** - * Requested kind of actions to return. - * - * Actions not of this kind are filtered out by the client before being shown. So servers - * can omit computing them. - */ - Only []CodeActionKind `json:"only,omitempty"` -} - -/** - * A set of predefined code action kinds - */ -type CodeActionKind string - -/** - * Provider options for a [CodeActionRequest](#CodeActionRequest). - */ -type CodeActionOptions struct { - /** - * CodeActionKinds that this server may return. - * - * The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server - * may list out every specific kind they provide. - */ - CodeActionKinds []CodeActionKind `json:"codeActionKinds,omitempty"` - /** - * The server provides support to resolve additional - * information for a code action. - * - * @since 3.16.0 - */ - ResolveProvider bool `json:"resolveProvider,omitempty"` - WorkDoneProgressOptions -} - -/** - * The parameters of a [CodeActionRequest](#CodeActionRequest). - */ -type CodeActionParams struct { - /** - * The document in which the command was invoked. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The range for which the command was invoked. - */ - Range Range `json:"range"` - /** - * Context carrying additional information. - */ - Context CodeActionContext `json:"context"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * Structure to capture a description for an error code. - * - * @since 3.16.0 - */ -type CodeDescription struct { - /** - * An URI to open with more information about the diagnostic error. - */ - Href URI `json:"href"` -} - -/** - * A code lens represents a [command](#Command) that should be shown along with - * source text, like the number of references, a way to run tests, etc. - * - * A code lens is _unresolved_ when no command is associated to it. For performance - * reasons the creation of a code lens and resolving should be done to two stages. - */ -type CodeLens struct { - /** - * The range in which this code lens is valid. Should only span a single line. - */ - Range Range `json:"range"` - /** - * The command this code lens represents. - */ - Command Command `json:"command,omitempty"` - /** - * A data entry field that is preserved on a code lens item between - * a [CodeLensRequest](#CodeLensRequest) and a [CodeLensResolveRequest] - * (#CodeLensResolveRequest) - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * The client capabilities of a [CodeLensRequest](#CodeLensRequest). - */ -type CodeLensClientCapabilities struct { - /** - * Whether code lens supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Code Lens provider options of a [CodeLensRequest](#CodeLensRequest). - */ -type CodeLensOptions struct { - /** - * Code lens has a resolve provider as well. - */ - ResolveProvider bool `json:"resolveProvider,omitempty"` - WorkDoneProgressOptions -} - -/** - * The parameters of a [CodeLensRequest](#CodeLensRequest). - */ -type CodeLensParams struct { - /** - * The document to request code lens for. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * @since 3.16.0 - */ -type CodeLensWorkspaceClientCapabilities struct { - /** - * Whether the client implementation supports a refresh request sent from the - * server to the client. - * - * Note that this event is global and will force the client to refresh all - * code lenses currently shown. It should be used with absolute care and is - * useful for situation where a server for example detect a project wide - * change that requires such a calculation. - */ - RefreshSupport bool `json:"refreshSupport,omitempty"` -} - -/** - * Represents a color in RGBA space. - */ -type Color struct { - /** - * The red component of this color in the range [0-1]. - */ - Red Decimal `json:"red"` - /** - * The green component of this color in the range [0-1]. - */ - Green Decimal `json:"green"` - /** - * The blue component of this color in the range [0-1]. - */ - Blue Decimal `json:"blue"` - /** - * The alpha component of this color in the range [0-1]. - */ - Alpha Decimal `json:"alpha"` -} - -/** - * Represents a color range from a document. - */ -type ColorInformation struct { - /** - * The range in the document where this color appears. - */ - Range Range `json:"range"` - /** - * The actual color value for this color range. - */ - Color Color `json:"color"` -} - -type ColorPresentation struct { - /** - * The label of this color presentation. It will be shown on the color - * picker header. By default this is also the text that is inserted when selecting - * this color presentation. - */ - Label string `json:"label"` - /** - * An [edit](#TextEdit) which is applied to a document when selecting - * this presentation for the color. When `falsy` the [label](#ColorPresentation.label) - * is used. - */ - TextEdit TextEdit `json:"textEdit,omitempty"` - /** - * An optional array of additional [text edits](#TextEdit) that are applied when - * selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves. - */ - AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"` -} - -/** - * Parameters for a [ColorPresentationRequest](#ColorPresentationRequest). - */ -type ColorPresentationParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The color to request presentations for. - */ - Color Color `json:"color"` - /** - * The range where the color would be inserted. Serves as a context. - */ - Range Range `json:"range"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * Represents a reference to a command. Provides a title which - * will be used to represent a command in the UI and, optionally, - * an array of arguments which will be passed to the command handler - * function when invoked. - */ -type Command struct { - /** - * Title of the command, like `save`. - */ - Title string `json:"title"` - /** - * The identifier of the actual command handler. - */ - Command string `json:"command"` - /** - * Arguments that the command handler should be - * invoked with. - */ - Arguments []json.RawMessage `json:"arguments,omitempty"` -} - -/** - * Completion client capabilities - */ -type CompletionClientCapabilities struct { - /** - * Whether completion supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports the following `CompletionItem` specific - * capabilities. - */ - CompletionItem struct { - /** - * Client supports snippets as insert text. - * - * A snippet can define tab stops and placeholders with `$1`, `$2` - * and `${3:foo}`. `$0` defines the final tab stop, it defaults to - * the end of the snippet. Placeholders with equal identifiers are linked, - * that is typing in one will update others too. - */ - SnippetSupport bool `json:"snippetSupport,omitempty"` - /** - * Client supports commit characters on a completion item. - */ - CommitCharactersSupport bool `json:"commitCharactersSupport,omitempty"` - /** - * Client supports the follow content formats for the documentation - * property. The order describes the preferred format of the client. - */ - DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"` - /** - * Client supports the deprecated property on a completion item. - */ - DeprecatedSupport bool `json:"deprecatedSupport,omitempty"` - /** - * Client supports the preselect property on a completion item. - */ - PreselectSupport bool `json:"preselectSupport,omitempty"` - /** - * Client supports to kee - */ - - /** - * Client supports the tag property on a completion item. Clients supporting - * tags have to handle unknown tags gracefully. Clients especially need to - * preserve unknown tags when sending a completion item back to the server in - * a resolve call. - * - * @since 3.15.0 - */ - TagSupport struct { - /** - * The tags supported by the client. - */ - ValueSet []CompletionItemTag `json:"valueSet"` - } `json:"tagSupport,omitempty"` - /** - * Client support insert replace edit to control different behavior if a - * completion item is inserted in the text or should replace text. - * - * @since 3.16.0 - */ - InsertReplaceSupport bool `json:"insertReplaceSupport,omitempty"` - /** - * Indicates which properties a client can resolve lazily on a completion - * item. Before version 3.16.0 only the predefined properties `documentation` - * and `details` could be resolved lazily. - * - * @since 3.16.0 - */ - ResolveSupport struct { - /** - * The properties that a client can resolve lazily. - */ - Properties []string `json:"properties"` - } `json:"resolveSupport,omitempty"` - /** - * The client supports the `insertTextMode` property on - * a completion item to override the whitespace handling mode - * as defined by the client (see `insertTextMode`). - * - * @since 3.16.0 - */ - InsertTextModeSupport struct { - ValueSet []InsertTextMode `json:"valueSet"` - } `json:"insertTextModeSupport,omitempty"` - /** - * The client has support for completion item label - * details (see also `CompletionItemLabelDetails`). - * - * @since 3.17.0 - proposed state - */ - LabelDetailsSupport bool `json:"labelDetailsSupport,omitempty"` - } `json:"completionItem,omitempty"` - CompletionItemKind struct { - /** - * The completion item kind values the client supports. When this - * property exists the client also guarantees that it will - * handle values outside its set gracefully and falls back - * to a default value when unknown. - * - * If this property is not present the client only supports - * the completion items kinds from `Text` to `Reference` as defined in - * the initial version of the protocol. - */ - ValueSet []CompletionItemKind `json:"valueSet,omitempty"` - } `json:"completionItemKind,omitempty"` - /** - * Defines how the client handles whitespace and indentation - * when accepting a completion item that uses multi line - * text in either `insertText` or `textEdit`. - * - * @since 3.17.0 - */ - InsertTextMode InsertTextMode `json:"insertTextMode,omitempty"` - /** - * The client supports to send additional context information for a - * `textDocument/completion` request. - */ - ContextSupport bool `json:"contextSupport,omitempty"` -} - -/** - * Contains additional information about the context in which a completion request is triggered. - */ -type CompletionContext struct { - /** - * How the completion was triggered. - */ - TriggerKind CompletionTriggerKind `json:"triggerKind"` - /** - * The trigger character (a single character) that has trigger code complete. - * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` - */ - TriggerCharacter string `json:"triggerCharacter,omitempty"` -} - -/** - * A completion item represents a text snippet that is - * proposed to complete text that is being typed. - */ -type CompletionItem struct { - /** - * The label of this completion item. - * - * The label property is also by default the text that - * is inserted when selecting this completion. - * - * If label details are provided the label itself should - * be an unqualified name of the completion item. - */ - Label string `json:"label"` - /** - * Additional details for the label - * - * @since 3.17.0 - proposed state - */ - LabelDetails CompletionItemLabelDetails `json:"labelDetails,omitempty"` - /** - * The kind of this completion item. Based of the kind - * an icon is chosen by the editor. - */ - Kind CompletionItemKind `json:"kind,omitempty"` - /** - * Tags for this completion item. - * - * @since 3.15.0 - */ - Tags []CompletionItemTag `json:"tags,omitempty"` - /** - * A human-readable string with additional information - * about this item, like type or symbol information. - */ - Detail string `json:"detail,omitempty"` - /** - * A human-readable string that represents a doc-comment. - */ - Documentation string/*string | MarkupContent*/ `json:"documentation,omitempty"` - /** - * Indicates if this item is deprecated. - * @deprecated Use `tags` instead. - */ - Deprecated bool `json:"deprecated,omitempty"` - /** - * Select this item when showing. - * - * *Note* that only one completion item can be selected and that the - * tool / client decides which item that is. The rule is that the *first* - * item of those that match best is selected. - */ - Preselect bool `json:"preselect,omitempty"` - /** - * A string that should be used when comparing this item - * with other items. When `falsy` the [label](#CompletionItem.label) - * is used. - */ - SortText string `json:"sortText,omitempty"` - /** - * A string that should be used when filtering a set of - * completion items. When `falsy` the [label](#CompletionItem.label) - * is used. - */ - FilterText string `json:"filterText,omitempty"` - /** - * A string that should be inserted into a document when selecting - * this completion. When `falsy` the [label](#CompletionItem.label) - * is used. - * - * The `insertText` is subject to interpretation by the client side. - * Some tools might not take the string literally. For example - * VS Code when code complete is requested in this example `con` - * and a completion item with an `insertText` of `console` is provided it - * will only insert `sole`. Therefore it is recommended to use `textEdit` instead - * since it avoids additional client side interpretation. - */ - InsertText string `json:"insertText,omitempty"` - /** - * The format of the insert text. The format applies to both the `insertText` property - * and the `newText` property of a provided `textEdit`. If omitted defaults to - * `InsertTextFormat.PlainText`. - */ - InsertTextFormat InsertTextFormat `json:"insertTextFormat,omitempty"` - /** - * How whitespace and indentation is handled during completion - * item insertion. If ignored the clients default value depends on - * the `textDocument.completion.insertTextMode` client capability. - * - * @since 3.16.0 - */ - InsertTextMode InsertTextMode `json:"insertTextMode,omitempty"` - /** - * An [edit](#TextEdit) which is applied to a document when selecting - * this completion. When an edit is provided the value of - * [insertText](#CompletionItem.insertText) is ignored. - * - * Most editors support two different operation when accepting a completion item. One is to insert a - * completion text and the other is to replace an existing text with a completion text. Since this can - * usually not predetermined by a server it can report both ranges. Clients need to signal support for - * `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability - * property. - * - * *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a - * [single line] and they must contain the position at which completion has been requested. - * *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of - * the edit's replace range, that means it must be contained and starting at the same position. - * - * @since 3.16.0 additional type `InsertReplaceEdit` - */ - TextEdit *TextEdit/*TextEdit | InsertReplaceEdit*/ `json:"textEdit,omitempty"` - /** - * An optional array of additional [text edits](#TextEdit) that are applied when - * selecting this completion. Edits must not overlap (including the same insert position) - * with the main [edit](#CompletionItem.textEdit) nor with themselves. - * - * Additional text edits should be used to change text unrelated to the current cursor position - * (for example adding an import statement at the top of the file if the completion item will - * insert an unqualified type). - */ - AdditionalTextEdits []TextEdit `json:"additionalTextEdits,omitempty"` - /** - * An optional set of characters that when pressed while this completion is active will accept it first and - * then type that character. *Note* that all commit characters should have `length=1` and that superfluous - * characters will be ignored. - */ - CommitCharacters []string `json:"commitCharacters,omitempty"` - /** - * An optional [command](#Command) that is executed *after* inserting this completion. *Note* that - * additional modifications to the current document should be described with the - * [additionalTextEdits](#CompletionItem.additionalTextEdits)-property. - */ - Command *Command `json:"command,omitempty"` - /** - * A data entry field that is preserved on a completion item between a - * [CompletionRequest](#CompletionRequest) and a [CompletionResolveRequest](#CompletionResolveRequest). - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * The kind of a completion entry. - */ -type CompletionItemKind float64 - -/** - * Additional details for a completion item label. - * - * @since 3.17.0 - proposed state - */ -type CompletionItemLabelDetails struct { - /** - * An optional string which is rendered less prominently directly after {@link CompletionItemLabel.label label}, - * without any spacing. Should be used for function signatures or type annotations. - */ - Detail string `json:"detail,omitempty"` - /** - * An optional string which is rendered less prominently after {@link CompletionItemLabel.detail}. Should be used - * for fully qualified names or file path. - */ - Description string `json:"description,omitempty"` -} - -/** - * Completion item tags are extra annotations that tweak the rendering of a completion - * item. - * - * @since 3.15.0 - */ -type CompletionItemTag float64 - -/** - * Represents a collection of [completion items](#CompletionItem) to be presented - * in the editor. - */ -type CompletionList struct { - /** - * This list it not complete. Further typing results in recomputing this list. - */ - IsIncomplete bool `json:"isIncomplete"` - /** - * The completion items. - */ - Items []CompletionItem `json:"items"` -} - -/** - * Completion options. - */ -type CompletionOptions struct { - /** - * Most tools trigger completion request automatically without explicitly requesting - * it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user - * starts to type an identifier. For example if the user types `c` in a JavaScript file - * code complete will automatically pop up present `console` besides others as a - * completion item. Characters that make up identifiers don't need to be listed here. - * - * If code complete should automatically be trigger on characters not being valid inside - * an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. - */ - TriggerCharacters []string `json:"triggerCharacters,omitempty"` - /** - * The list of all possible characters that commit a completion. This field can be used - * if clients don't support individual commit characters per completion item. See - * `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` - * - * If a server provides both `allCommitCharacters` and commit characters on an individual - * completion item the ones on the completion item win. - * - * @since 3.2.0 - */ - AllCommitCharacters []string `json:"allCommitCharacters,omitempty"` - /** - * The server provides support to resolve additional - * information for a completion item. - */ - ResolveProvider bool `json:"resolveProvider,omitempty"` - /** - * The server supports the following `CompletionItem` specific - * capabilities. - * - * @since 3.17.0 - proposed state - */ - CompletionItem struct { - /** - * The server has support for completion item label - * details (see also `CompletionItemLabelDetails`) when - * receiving a completion item in a resolve call. - * - * @since 3.17.0 - proposed state - */ - LabelDetailsSupport bool `json:"labelDetailsSupport,omitempty"` - } `json:"completionItem,omitempty"` - WorkDoneProgressOptions -} - -/** - * Completion parameters - */ -type CompletionParams struct { - /** - * The completion context. This is only available it the client specifies - * to send this using the client capability `textDocument.completion.contextSupport === true` - */ - Context CompletionContext `json:"context,omitempty"` - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -/** - * How a completion was triggered - */ -type CompletionTriggerKind float64 - -type ConfigurationClientCapabilities struct { - /** - * The workspace client capabilities - */ - Workspace Workspace3Gn `json:"workspace,omitempty"` -} - -type ConfigurationItem struct { - /** - * The scope to get the configuration section for. - */ - ScopeURI string `json:"scopeUri,omitempty"` - /** - * The configuration section asked for. - */ - Section string `json:"section,omitempty"` -} - -/** - * The parameters of a configuration request. - */ -type ConfigurationParams struct { - Items []ConfigurationItem `json:"items"` -} - -/** - * Create file operation. - */ -type CreateFile struct { - /** - * A create - */ - Kind string `json:"kind"` - /** - * The resource to create. - */ - URI DocumentURI `json:"uri"` - /** - * Additional options - */ - Options CreateFileOptions `json:"options,omitempty"` - ResourceOperation -} - -/** - * Options to create a file. - */ -type CreateFileOptions struct { - /** - * Overwrite existing file. Overwrite wins over `ignoreIfExists` - */ - Overwrite bool `json:"overwrite,omitempty"` - /** - * Ignore if exists. - */ - IgnoreIfExists bool `json:"ignoreIfExists,omitempty"` -} - -/** - * The parameters sent in file create requests/notifications. - * - * @since 3.16.0 - */ -type CreateFilesParams struct { - /** - * An array of all files/folders created in this operation. - */ - Files []FileCreate `json:"files"` -} - -/** - * Defines a decimal number. Since decimal numbers are very - * rare in the language server specification we denote the - * exact range with every decimal using the mathematics - * interval notations (e.g. [0, 1] denotes all decimals d with - * 0 <= d <= 1. - */ -type Decimal = float64 - -/** - * The declaration of a symbol representation as one or many [locations](#Location). - */ -type Declaration = []Location /*Location | Location[]*/ - -/** - * @since 3.14.0 - */ -type DeclarationClientCapabilities struct { - /** - * Whether declaration supports dynamic registration. If this is set to `true` - * the client supports the new `DeclarationRegistrationOptions` return value - * for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports additional metadata in the form of declaration links. - */ - LinkSupport bool `json:"linkSupport,omitempty"` -} - -/** - * Information about where a symbol is declared. - * - * Provides additional metadata over normal [location](#Location) declarations, including the range of - * the declaring symbol. - * - * Servers should prefer returning `DeclarationLink` over `Declaration` if supported - * by the client. - */ -type DeclarationLink = LocationLink - -type DeclarationOptions struct { - WorkDoneProgressOptions -} - -type DeclarationParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -type DeclarationRegistrationOptions struct { - DeclarationOptions - TextDocumentRegistrationOptions - StaticRegistrationOptions -} - -/** - * The definition of a symbol represented as one or many [locations](#Location). - * For most programming languages there is only one location at which a symbol is - * defined. - * - * Servers should prefer returning `DefinitionLink` over `Definition` if supported - * by the client. - */ -type Definition = []Location /*Location | Location[]*/ - -/** - * Client Capabilities for a [DefinitionRequest](#DefinitionRequest). - */ -type DefinitionClientCapabilities struct { - /** - * Whether definition supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports additional metadata in the form of definition links. - * - * @since 3.14.0 - */ - LinkSupport bool `json:"linkSupport,omitempty"` -} - -/** - * Information about where a symbol is defined. - * - * Provides additional metadata over normal [location](#Location) definitions, including the range of - * the defining symbol - */ -type DefinitionLink = LocationLink - -/** - * Server Capabilities for a [DefinitionRequest](#DefinitionRequest). - */ -type DefinitionOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [DefinitionRequest](#DefinitionRequest). - */ -type DefinitionParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -/** - * Delete file operation - */ -type DeleteFile struct { - /** - * A delete - */ - Kind string `json:"kind"` - /** - * The file to delete. - */ - URI DocumentURI `json:"uri"` - /** - * Delete options. - */ - Options DeleteFileOptions `json:"options,omitempty"` - ResourceOperation -} - -/** - * Delete file options - */ -type DeleteFileOptions struct { - /** - * Delete the content recursively if a folder is denoted. - */ - Recursive bool `json:"recursive,omitempty"` - /** - * Ignore the operation if the file doesn't exist. - */ - IgnoreIfNotExists bool `json:"ignoreIfNotExists,omitempty"` -} - -/** - * The parameters sent in file delete requests/notifications. - * - * @since 3.16.0 - */ -type DeleteFilesParams struct { - /** - * An array of all files/folders deleted in this operation. - */ - Files []FileDelete `json:"files"` -} - -/** - * Represents a diagnostic, such as a compiler error or warning. Diagnostic objects - * are only valid in the scope of a resource. - */ -type Diagnostic struct { - /** - * The range at which the message applies - */ - Range Range `json:"range"` - /** - * The diagnostic's severity. Can be omitted. If omitted it is up to the - * client to interpret diagnostics as error, warning, info or hint. - */ - Severity DiagnosticSeverity `json:"severity,omitempty"` - /** - * The diagnostic's code, which usually appear in the user interface. - */ - Code interface{}/*integer | string*/ `json:"code,omitempty"` - /** - * An optional property to describe the error code. - * - * @since 3.16.0 - */ - CodeDescription *CodeDescription `json:"codeDescription,omitempty"` - /** - * A human-readable string describing the source of this - * diagnostic, e.g. 'typescript' or 'super lint'. It usually - * appears in the user interface. - */ - Source string `json:"source,omitempty"` - /** - * The diagnostic's message. It usually appears in the user interface - */ - Message string `json:"message"` - /** - * Additional metadata about the diagnostic. - * - * @since 3.15.0 - */ - Tags []DiagnosticTag `json:"tags,omitempty"` - /** - * An array of related diagnostic information, e.g. when symbol-names within - * a scope collide all definitions can be marked via this property. - */ - RelatedInformation []DiagnosticRelatedInformation `json:"relatedInformation,omitempty"` - /** - * A data entry field that is preserved between a `textDocument/publishDiagnostics` - * notification and `textDocument/codeAction` request. - * - * @since 3.16.0 - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * Represents a related message and source code location for a diagnostic. This should be - * used to point to code locations that cause or related to a diagnostics, e.g when duplicating - * a symbol in a scope. - */ -type DiagnosticRelatedInformation struct { - /** - * The location of this related diagnostic information. - */ - Location Location `json:"location"` - /** - * The message of this related diagnostic information. - */ - Message string `json:"message"` -} - -/** - * The diagnostic's severity. - */ -type DiagnosticSeverity float64 - -/** - * The diagnostic tags. - * - * @since 3.15.0 - */ -type DiagnosticTag float64 - -type DidChangeConfigurationClientCapabilities struct { - /** - * Did change configuration notification supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * The parameters of a change configuration notification. - */ -type DidChangeConfigurationParams struct { - /** - * The actual changed settings - */ - Settings interface{} `json:"settings"` -} - -/** - * The change text document notification's parameters. - */ -type DidChangeTextDocumentParams struct { - /** - * The document that did change. The version number points - * to the version after all provided content changes have - * been applied. - */ - TextDocument VersionedTextDocumentIdentifier `json:"textDocument"` - /** - * The actual content changes. The content changes describe single state changes - * to the document. So if there are two content changes c1 (at array index 0) and - * c2 (at array index 1) for a document in state S then c1 moves the document from - * S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed - * on the state S'. - * - * To mirror the content of a document using change events use the following approach: - * - start with the same initial content - * - apply the 'textDocument/didChange' notifications in the order you receive them. - * - apply the `TextDocumentContentChangeEvent`s in a single notification in the order - * you receive them. - */ - ContentChanges []TextDocumentContentChangeEvent `json:"contentChanges"` -} - -type DidChangeWatchedFilesClientCapabilities struct { - /** - * Did change watched files notification supports dynamic registration. Please note - * that the current protocol doesn't support static configuration for file changes - * from the server side. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * The watched files change notification's parameters. - */ -type DidChangeWatchedFilesParams struct { - /** - * The actual file events. - */ - Changes []FileEvent `json:"changes"` -} - -/** - * Describe options to be used when registered for text document change events. - */ -type DidChangeWatchedFilesRegistrationOptions struct { - /** - * The watchers to register. - */ - Watchers []FileSystemWatcher `json:"watchers"` -} - -/** - * The parameters of a `workspace/didChangeWorkspaceFolders` notification. - */ -type DidChangeWorkspaceFoldersParams struct { - /** - * The actual workspace folder change event. - */ - Event WorkspaceFoldersChangeEvent `json:"event"` -} - -/** - * The parameters send in a close text document notification - */ -type DidCloseTextDocumentParams struct { - /** - * The document that was closed. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` -} - -/** - * The parameters send in a open text document notification - */ -type DidOpenTextDocumentParams struct { - /** - * The document that was opened. - */ - TextDocument TextDocumentItem `json:"textDocument"` -} - -/** - * The parameters send in a save text document notification - */ -type DidSaveTextDocumentParams struct { - /** - * The document that was closed. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * Optional the content when saved. Depends on the includeText value - * when the save notification was requested. - */ - Text *string `json:"text,omitempty"` -} - -type DocumentColorClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `DocumentColorRegistrationOptions` return value - * for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -type DocumentColorOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [DocumentColorRequest](#DocumentColorRequest). - */ -type DocumentColorParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -type DocumentColorRegistrationOptions struct { - TextDocumentRegistrationOptions - StaticRegistrationOptions - DocumentColorOptions -} - -/** - * Parameters of the document diagnostic request. - * - * @since 3.17.0 - proposed state - */ -type DocumentDiagnosticParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The additional identifier provided during registration. - */ - Identifier string `json:"identifier,omitempty"` - /** - * The result id of a previous response if provided. - */ - PreviousResultID string `json:"previousResultId,omitempty"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * The result of a document diagnostic pull request. A report can - * either be a full report containing all diagnostics for the - * requested document or a unchanged report indicating that nothing - * has changed in terms of diagnostics in comparison to the last - * pull request. - * - * @since 3.17.0 - proposed state - */ -type DocumentDiagnosticReport = interface{} /*RelatedFullDocumentDiagnosticReport | RelatedUnchangedDocumentDiagnosticReport*/ - -/** - * A document filter denotes a document by different properties like - * the [language](#TextDocument.languageId), the [scheme](#Uri.scheme) of - * its resource, or a glob-pattern that is applied to the [path](#TextDocument.fileName). - * - * Glob patterns can have the following syntax: - * - `*` to match one or more characters in a path segment - * - `?` to match on one character in a path segment - * - `**` to match any number of path segments, including none - * - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) - * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) - * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) - * - * @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` - * @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` - */ -type DocumentFilter = struct { - /** A language id, like `typescript`. */ - Language string `json:"language"` - /** A Uri [scheme](#Uri.scheme), like `file` or `untitled`. */ - Scheme string `json:"scheme,omitempty"` - /** A glob pattern, like `*.{ts,js}`. */ - Pattern string `json:"pattern,omitempty"` -} - -/** - * Client capabilities of a [DocumentFormattingRequest](#DocumentFormattingRequest). - */ -type DocumentFormattingClientCapabilities struct { - /** - * Whether formatting supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Provider options for a [DocumentFormattingRequest](#DocumentFormattingRequest). - */ -type DocumentFormattingOptions struct { - WorkDoneProgressOptions -} - -/** - * The parameters of a [DocumentFormattingRequest](#DocumentFormattingRequest). - */ -type DocumentFormattingParams struct { - /** - * The document to format. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The format options - */ - Options FormattingOptions `json:"options"` - WorkDoneProgressParams -} - -/** - * A document highlight is a range inside a text document which deserves - * special attention. Usually a document highlight is visualized by changing - * the background color of its range. - */ -type DocumentHighlight struct { - /** - * The range this highlight applies to. - */ - Range Range `json:"range"` - /** - * The highlight kind, default is [text](#DocumentHighlightKind.Text). - */ - Kind DocumentHighlightKind `json:"kind,omitempty"` -} - -/** - * Client Capabilities for a [DocumentHighlightRequest](#DocumentHighlightRequest). - */ -type DocumentHighlightClientCapabilities struct { - /** - * Whether document highlight supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * A document highlight kind. - */ -type DocumentHighlightKind float64 - -/** - * Provider options for a [DocumentHighlightRequest](#DocumentHighlightRequest). - */ -type DocumentHighlightOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [DocumentHighlightRequest](#DocumentHighlightRequest). - */ -type DocumentHighlightParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -/** - * A document link is a range in a text document that links to an internal or external resource, like another - * text document or a web site. - */ -type DocumentLink struct { - /** - * The range this link applies to. - */ - Range Range `json:"range"` - /** - * The uri this link points to. - */ - Target string `json:"target,omitempty"` - /** - * The tooltip text when you hover over this link. - * - * If a tooltip is provided, is will be displayed in a string that includes instructions on how to - * trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, - * user settings, and localization. - * - * @since 3.15.0 - */ - Tooltip string `json:"tooltip,omitempty"` - /** - * A data entry field that is preserved on a document link between a - * DocumentLinkRequest and a DocumentLinkResolveRequest. - */ - Data interface{} `json:"data,omitempty"` -} - -/** - * The client capabilities of a [DocumentLinkRequest](#DocumentLinkRequest). - */ -type DocumentLinkClientCapabilities struct { - /** - * Whether document link supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Whether the client support the `tooltip` property on `DocumentLink`. - * - * @since 3.15.0 - */ - TooltipSupport bool `json:"tooltipSupport,omitempty"` -} - -/** - * Provider options for a [DocumentLinkRequest](#DocumentLinkRequest). - */ -type DocumentLinkOptions struct { - /** - * Document links have a resolve provider as well. - */ - ResolveProvider bool `json:"resolveProvider,omitempty"` - WorkDoneProgressOptions -} - -/** - * The parameters of a [DocumentLinkRequest](#DocumentLinkRequest). - */ -type DocumentLinkParams struct { - /** - * The document to provide document links for. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * Client capabilities of a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). - */ -type DocumentOnTypeFormattingClientCapabilities struct { - /** - * Whether on type formatting supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Provider options for a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). - */ -type DocumentOnTypeFormattingOptions struct { - /** - * A character on which formatting should be triggered, like `}`. - */ - FirstTriggerCharacter string `json:"firstTriggerCharacter"` - /** - * More trigger characters. - */ - MoreTriggerCharacter []string `json:"moreTriggerCharacter,omitempty"` -} - -/** - * The parameters of a [DocumentOnTypeFormattingRequest](#DocumentOnTypeFormattingRequest). - */ -type DocumentOnTypeFormattingParams struct { - /** - * The document to format. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The position at which this request was send. - */ - Position Position `json:"position"` - /** - * The character that has been typed. - */ - Ch string `json:"ch"` - /** - * The format options. - */ - Options FormattingOptions `json:"options"` -} - -/** - * Client capabilities of a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). - */ -type DocumentRangeFormattingClientCapabilities struct { - /** - * Whether range formatting supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Provider options for a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). - */ -type DocumentRangeFormattingOptions struct { - WorkDoneProgressOptions -} - -/** - * The parameters of a [DocumentRangeFormattingRequest](#DocumentRangeFormattingRequest). - */ -type DocumentRangeFormattingParams struct { - /** - * The document to format. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The range to format - */ - Range Range `json:"range"` - /** - * The format options - */ - Options FormattingOptions `json:"options"` - WorkDoneProgressParams -} - -/** - * A document selector is the combination of one or many document filters. - * - * @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; - * - * The use of a string as a document filter is deprecated @since 3.16.0. - */ -type DocumentSelector = []string /*string | DocumentFilter*/ - -/** - * Represents programming constructs like variables, classes, interfaces etc. - * that appear in a document. Document symbols can be hierarchical and they - * have two ranges: one that encloses its definition and one that points to - * its most interesting range, e.g. the range of an identifier. - */ -type DocumentSymbol struct { - /** - * The name of this symbol. Will be displayed in the user interface and therefore must not be - * an empty string or a string only consisting of white spaces. - */ - Name string `json:"name"` - /** - * More detail for this symbol, e.g the signature of a function. - */ - Detail string `json:"detail,omitempty"` - /** - * The kind of this symbol. - */ - Kind SymbolKind `json:"kind"` - /** - * Tags for this completion item. - * - * @since 3.16.0 - */ - Tags []SymbolTag `json:"tags,omitempty"` - /** - * Indicates if this symbol is deprecated. - * - * @deprecated Use tags instead - */ - Deprecated bool `json:"deprecated,omitempty"` - /** - * The range enclosing this symbol not including leading/trailing whitespace but everything else - * like comments. This information is typically used to determine if the the clients cursor is - * inside the symbol to reveal in the symbol in the UI. - */ - Range Range `json:"range"` - /** - * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. - * Must be contained by the the `range`. - */ - SelectionRange Range `json:"selectionRange"` - /** - * Children of this symbol, e.g. properties of a class. - */ - Children []DocumentSymbol `json:"children,omitempty"` -} - -/** - * Client Capabilities for a [DocumentSymbolRequest](#DocumentSymbolRequest). - */ -type DocumentSymbolClientCapabilities struct { - /** - * Whether document symbol supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Specific capabilities for the `SymbolKind`. - */ - SymbolKind struct { - /** - * The symbol kind values the client supports. When this - * property exists the client also guarantees that it will - * handle values outside its set gracefully and falls back - * to a default value when unknown. - * - * If this property is not present the client only supports - * the symbol kinds from `File` to `Array` as defined in - * the initial version of the protocol. - */ - ValueSet []SymbolKind `json:"valueSet,omitempty"` - } `json:"symbolKind,omitempty"` - /** - * The client support hierarchical document symbols. - */ - HierarchicalDocumentSymbolSupport bool `json:"hierarchicalDocumentSymbolSupport,omitempty"` - /** - * The client supports tags on `SymbolInformation`. Tags are supported on - * `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. - * Clients supporting tags have to handle unknown tags gracefully. - * - * @since 3.16.0 - */ - TagSupport struct { - /** - * The tags supported by the client. - */ - ValueSet []SymbolTag `json:"valueSet"` - } `json:"tagSupport,omitempty"` - /** - * The client supports an additional label presented in the UI when - * registering a document symbol provider. - * - * @since 3.16.0 - */ - LabelSupport bool `json:"labelSupport,omitempty"` -} - -/** - * Provider options for a [DocumentSymbolRequest](#DocumentSymbolRequest). - */ -type DocumentSymbolOptions struct { - /** - * A human-readable string that is shown when multiple outlines trees - * are shown for the same document. - * - * @since 3.16.0 - */ - Label string `json:"label,omitempty"` - WorkDoneProgressOptions -} - -/** - * Parameters for a [DocumentSymbolRequest](#DocumentSymbolRequest). - */ -type DocumentSymbolParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * A tagging type for string properties that are actually document URIs. - */ -type DocumentURI string - -/** - * The client capabilities of a [ExecuteCommandRequest](#ExecuteCommandRequest). - */ -type ExecuteCommandClientCapabilities struct { - /** - * Execute command supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * The server capabilities of a [ExecuteCommandRequest](#ExecuteCommandRequest). - */ -type ExecuteCommandOptions struct { - /** - * The commands to be executed on the server - */ - Commands []string `json:"commands"` - WorkDoneProgressOptions -} - -/** - * The parameters of a [ExecuteCommandRequest](#ExecuteCommandRequest). - */ -type ExecuteCommandParams struct { - /** - * The identifier of the actual command handler. - */ - Command string `json:"command"` - /** - * Arguments that the command should be invoked with. - */ - Arguments []json.RawMessage `json:"arguments,omitempty"` - WorkDoneProgressParams -} - -type FailureHandlingKind string - -/** - * The file event type - */ -type FileChangeType float64 - -/** - * Represents information on a file/folder create. - * - * @since 3.16.0 - */ -type FileCreate struct { - /** - * A file:// URI for the location of the file/folder being created. - */ - URI string `json:"uri"` -} - -/** - * Represents information on a file/folder delete. - * - * @since 3.16.0 - */ -type FileDelete struct { - /** - * A file:// URI for the location of the file/folder being deleted. - */ - URI string `json:"uri"` -} - -/** - * An event describing a file change. - */ -type FileEvent struct { - /** - * The file's uri. - */ - URI DocumentURI `json:"uri"` - /** - * The change type. - */ - Type FileChangeType `json:"type"` -} - -/** - * Capabilities relating to events from file operations by the user in the client. - * - * These events do not come from the file system, they come from user operations - * like renaming a file in the UI. - * - * @since 3.16.0 - */ -type FileOperationClientCapabilities struct { - /** - * Whether the client supports dynamic registration for file requests/notifications. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client has support for sending didCreateFiles notifications. - */ - DidCreate bool `json:"didCreate,omitempty"` - /** - * The client has support for willCreateFiles requests. - */ - WillCreate bool `json:"willCreate,omitempty"` - /** - * The client has support for sending didRenameFiles notifications. - */ - DidRename bool `json:"didRename,omitempty"` - /** - * The client has support for willRenameFiles requests. - */ - WillRename bool `json:"willRename,omitempty"` - /** - * The client has support for sending didDeleteFiles notifications. - */ - DidDelete bool `json:"didDelete,omitempty"` - /** - * The client has support for willDeleteFiles requests. - */ - WillDelete bool `json:"willDelete,omitempty"` -} - -/** - * A filter to describe in which file operation requests or notifications - * the server is interested in. - * - * @since 3.16.0 - */ -type FileOperationFilter struct { - /** - * A Uri like `file` or `untitled`. - */ - Scheme string `json:"scheme,omitempty"` - /** - * The actual file operation pattern. - */ - Pattern FileOperationPattern `json:"pattern"` -} - -/** - * Options for notifications/requests for user operations on files. - * - * @since 3.16.0 - */ -type FileOperationOptions struct { - /** - * The server is interested in didCreateFiles notifications. - */ - DidCreate FileOperationRegistrationOptions `json:"didCreate,omitempty"` - /** - * The server is interested in willCreateFiles requests. - */ - WillCreate FileOperationRegistrationOptions `json:"willCreate,omitempty"` - /** - * The server is interested in didRenameFiles notifications. - */ - DidRename FileOperationRegistrationOptions `json:"didRename,omitempty"` - /** - * The server is interested in willRenameFiles requests. - */ - WillRename FileOperationRegistrationOptions `json:"willRename,omitempty"` - /** - * The server is interested in didDeleteFiles file notifications. - */ - DidDelete FileOperationRegistrationOptions `json:"didDelete,omitempty"` - /** - * The server is interested in willDeleteFiles file requests. - */ - WillDelete FileOperationRegistrationOptions `json:"willDelete,omitempty"` -} - -/** - * A pattern to describe in which file operation requests or notifications - * the server is interested in. - * - * @since 3.16.0 - */ -type FileOperationPattern struct { - /** - * The glob pattern to match. Glob patterns can have the following syntax: - * - `*` to match one or more characters in a path segment - * - `?` to match on one character in a path segment - * - `**` to match any number of path segments, including none - * - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) - * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) - * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) - */ - Glob string `json:"glob"` - /** - * Whether to match files or folders with this pattern. - * - * Matches both if undefined. - */ - Matches FileOperationPatternKind `json:"matches,omitempty"` - /** - * Additional options used during matching. - */ - Options FileOperationPatternOptions `json:"options,omitempty"` -} - -/** - * A pattern kind describing if a glob pattern matches a file a folder or - * both. - * - * @since 3.16.0 - */ -type FileOperationPatternKind string - -/** - * Matching options for the file operation pattern. - * - * @since 3.16.0 - */ -type FileOperationPatternOptions struct { - /** - * The pattern should be matched ignoring casing. - */ - IgnoreCase bool `json:"ignoreCase,omitempty"` -} - -/** - * The options to register for file operations. - * - * @since 3.16.0 - */ -type FileOperationRegistrationOptions struct { - /** - * The actual filters. - */ - Filters []FileOperationFilter `json:"filters"` -} - -/** - * Represents information on a file/folder rename. - * - * @since 3.16.0 - */ -type FileRename struct { - /** - * A file:// URI for the original location of the file/folder being renamed. - */ - OldURI string `json:"oldUri"` - /** - * A file:// URI for the new location of the file/folder being renamed. - */ - NewURI string `json:"newUri"` -} - -type FileSystemWatcher struct { - /** - * The glob pattern to watch. Glob patterns can have the following syntax: - * - `*` to match one or more characters in a path segment - * - `?` to match on one character in a path segment - * - `**` to match any number of path segments, including none - * - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) - * - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) - * - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) - */ - GlobPattern string `json:"globPattern"` - /** - * The kind of events of interest. If omitted it defaults - * to WatchKind.Create | WatchKind.Change | WatchKind.Delete - * which is 7. - */ - Kind uint32 `json:"kind,omitempty"` -} - -/** - * Represents a folding range. To be valid, start and end line must be bigger than zero and smaller - * than the number of lines in the document. Clients are free to ignore invalid ranges. - */ -type FoldingRange struct { - /** - * The zero-based start line of the range to fold. The folded area starts after the line's last character. - * To be valid, the end must be zero or larger and smaller than the number of lines in the document. - */ - StartLine uint32 `json:"startLine"` - /** - * The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. - */ - StartCharacter uint32 `json:"startCharacter,omitempty"` - /** - * The zero-based end line of the range to fold. The folded area ends with the line's last character. - * To be valid, the end must be zero or larger and smaller than the number of lines in the document. - */ - EndLine uint32 `json:"endLine"` - /** - * The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. - */ - EndCharacter uint32 `json:"endCharacter,omitempty"` - /** - * Describes the kind of the folding range such as `comment' or 'region'. The kind - * is used to categorize folding ranges and used by commands like 'Fold all comments'. See - * [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds. - */ - Kind string `json:"kind,omitempty"` -} - -type FoldingRangeClientCapabilities struct { - /** - * Whether implementation supports dynamic registration for folding range providers. If this is set to `true` - * the client supports the new `FoldingRangeRegistrationOptions` return value for the corresponding server - * capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The maximum number of folding ranges that the client prefers to receive per document. The value serves as a - * hint, servers are free to follow the limit. - */ - RangeLimit uint32 `json:"rangeLimit,omitempty"` - /** - * If set, the client signals that it only supports folding complete lines. If set, client will - * ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange. - */ - LineFoldingOnly bool `json:"lineFoldingOnly,omitempty"` -} - -/** - * Enum of known range kinds - */ -type FoldingRangeKind string - -type FoldingRangeOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [FoldingRangeRequest](#FoldingRangeRequest). - */ -type FoldingRangeParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -type FoldingRangeRegistrationOptions struct { - TextDocumentRegistrationOptions - FoldingRangeOptions - StaticRegistrationOptions -} - -/** - * Value-object describing what options formatting should use. - */ -type FormattingOptions struct { - /** - * Size of a tab in spaces. - */ - TabSize uint32 `json:"tabSize"` - /** - * Prefer spaces over tabs. - */ - InsertSpaces bool `json:"insertSpaces"` - /** - * Trim trailing whitespaces on a line. - * - * @since 3.15.0 - */ - TrimTrailingWhitespace bool `json:"trimTrailingWhitespace,omitempty"` - /** - * Insert a newline character at the end of the file if one does not exist. - * - * @since 3.15.0 - */ - InsertFinalNewline bool `json:"insertFinalNewline,omitempty"` - /** - * Trim all newlines after the final newline at the end of the file. - * - * @since 3.15.0 - */ - TrimFinalNewlines bool `json:"trimFinalNewlines,omitempty"` -} - -/** - * A diagnostic report with a full set of problems. - * - * @since 3.17.0 - proposed state - */ -type FullDocumentDiagnosticReport struct { - /** - * A full document diagnostic report. - */ - Kind string `json:"kind"` - /** - * An optional result id. If provided it will - * be sent on the next diagnostic request for the - * same document. - */ - ResultID string `json:"resultId,omitempty"` - /** - * The actual items. - */ - Items []Diagnostic `json:"items"` -} - -/** - * General client capabilities. - * - * @since 3.16.0 - */ -type GeneralClientCapabilities struct { - /** - * Client capability that signals how the client - * handles stale requests (e.g. a request - * for which the client will not process the response - * anymore since the information is outdated). - * - * @since 3.17.0 - */ - StaleRequestSupport struct { - /** - * The client will actively cancel the request. - */ - Cancel bool `json:"cancel"` - /** - * The list of requests for which the client - * will retry the request if it receives a - * response with error code `ContentModified`` - */ - RetryOnContentModified []string `json:"retryOnContentModified"` - } `json:"staleRequestSupport,omitempty"` - /** - * Client capabilities specific to regular expressions. - * - * @since 3.16.0 - */ - RegularExpressions RegularExpressionsClientCapabilities `json:"regularExpressions,omitempty"` - /** - * Client capabilities specific to the client's markdown parser. - * - * @since 3.16.0 - */ - Markdown MarkdownClientCapabilities `json:"markdown,omitempty"` -} - -/** - * The result of a hover request. - */ -type Hover struct { - /** - * The hover's content - */ - Contents MarkupContent/*MarkupContent | MarkedString | MarkedString[]*/ `json:"contents"` - /** - * An optional range - */ - Range Range `json:"range,omitempty"` -} - -type HoverClientCapabilities struct { - /** - * Whether hover supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Client supports the follow content formats for the content - * property. The order describes the preferred format of the client. - */ - ContentFormat []MarkupKind `json:"contentFormat,omitempty"` -} - -/** - * Hover options. - */ -type HoverOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [HoverRequest](#HoverRequest). - */ -type HoverParams struct { - TextDocumentPositionParams - WorkDoneProgressParams -} - -/** - * @since 3.6.0 - */ -type ImplementationClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `ImplementationRegistrationOptions` return value - * for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports additional metadata in the form of definition links. - * - * @since 3.14.0 - */ - LinkSupport bool `json:"linkSupport,omitempty"` -} - -type ImplementationOptions struct { - WorkDoneProgressOptions -} - -type ImplementationParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -type ImplementationRegistrationOptions struct { - TextDocumentRegistrationOptions - ImplementationOptions - StaticRegistrationOptions -} - -/** - * Known error codes for an `InitializeError`; - */ -type InitializeError float64 - -type InitializeParams struct { - /** - * The process Id of the parent process that started - * the server. - */ - ProcessID int32/*integer | null*/ `json:"processId"` - /** - * Information about the client - * - * @since 3.15.0 - */ - ClientInfo struct { - /** - * The name of the client as defined by the client. - */ - Name string `json:"name"` - /** - * The client's version as defined by the client. - */ - Version string `json:"version,omitempty"` - } `json:"clientInfo,omitempty"` - /** - * The locale the client is currently showing the user interface - * in. This must not necessarily be the locale of the operating - * system. - * - * Uses IETF language tags as the value's syntax - * (See https://en.wikipedia.org/wiki/IETF_language_tag) - * - * @since 3.16.0 - */ - Locale string `json:"locale,omitempty"` - /** - * The rootPath of the workspace. Is null - * if no folder is open. - * - * @deprecated in favour of rootUri. - */ - RootPath string/*string | null*/ `json:"rootPath,omitempty"` - /** - * The rootUri of the workspace. Is null if no - * folder is open. If both `rootPath` and `rootUri` are set - * `rootUri` wins. - * - * @deprecated in favour of workspaceFolders. - */ - RootURI DocumentURI/*DocumentUri | null*/ `json:"rootUri"` - /** - * The capabilities provided by the client (editor or tool) - */ - Capabilities ClientCapabilities `json:"capabilities"` - /** - * User provided initialization options. - */ - InitializationOptions interface{} `json:"initializationOptions,omitempty"` - /** - * The initial trace setting. If omitted trace is disabled ('off'). - */ - Trace string/*'off' | 'messages' | 'verbose'*/ `json:"trace,omitempty"` - /** - * The actual configured workspace folders. - */ - WorkspaceFolders []WorkspaceFolder/*WorkspaceFolder[] | null*/ `json:"workspaceFolders"` -} - -/** - * The result returned from an initialize request. - */ -type InitializeResult struct { - /** - * The capabilities the language server provides. - */ - Capabilities ServerCapabilities `json:"capabilities"` - /** - * Information about the server. - * - * @since 3.15.0 - */ - ServerInfo struct { - /** - * The name of the server as defined by the server. - */ - Name string `json:"name"` - /** - * The server's version as defined by the server. - */ - Version string `json:"version,omitempty"` - } `json:"serverInfo,omitempty"` -} - -type InitializedParams struct { -} - -/** - * A special text edit to provide an insert and a replace operation. - * - * @since 3.16.0 - */ -type InsertReplaceEdit struct { - /** - * The string to be inserted. - */ - NewText string `json:"newText"` - /** - * The range if the insert is requested - */ - Insert Range `json:"insert"` - /** - * The range if the replace is requested. - */ - Replace Range `json:"replace"` -} - -/** - * Defines whether the insert text in a completion item should be interpreted as - * plain text or a snippet. - */ -type InsertTextFormat float64 - -/** - * How whitespace and indentation is handled during completion - * item insertion. - * - * @since 3.16.0 - */ -type InsertTextMode float64 - -/** - * Client capabilities for the linked editing range request. - * - * @since 3.16.0 - */ -type LinkedEditingRangeClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` - * return value for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -type LinkedEditingRangeOptions struct { - WorkDoneProgressOptions -} - -type LinkedEditingRangeParams struct { - TextDocumentPositionParams - WorkDoneProgressParams -} - -type LinkedEditingRangeRegistrationOptions struct { - TextDocumentRegistrationOptions - LinkedEditingRangeOptions - StaticRegistrationOptions -} - -/** - * The result of a linked editing range request. - * - * @since 3.16.0 - */ -type LinkedEditingRanges struct { - /** - * A list of ranges that can be edited together. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap. - */ - Ranges []Range `json:"ranges"` - /** - * An optional word pattern (regular expression) that describes valid contents for - * the given ranges. If no pattern is provided, the client configuration's word - * pattern will be used. - */ - WordPattern string `json:"wordPattern,omitempty"` -} - -/** - * Represents a location inside a resource, such as a line - * inside a text file. - */ -type Location struct { - URI DocumentURI `json:"uri"` - Range Range `json:"range"` -} - -/** - * Represents the connection of two locations. Provides additional metadata over normal [locations](#Location), - * including an origin range. - */ -type LocationLink struct { - /** - * Span of the origin of this link. - * - * Used as the underlined span for mouse definition hover. Defaults to the word range at - * the definition position. - */ - OriginSelectionRange Range `json:"originSelectionRange,omitempty"` - /** - * The target resource identifier of this link. - */ - TargetURI DocumentURI `json:"targetUri"` - /** - * The full target range of this link. If the target for example is a symbol then target range is the - * range enclosing this symbol not including leading/trailing whitespace but everything else - * like comments. This information is typically used to highlight the range in the editor. - */ - TargetRange Range `json:"targetRange"` - /** - * The range that should be selected and revealed when this link is being followed, e.g the name of a function. - * Must be contained by the the `targetRange`. See also `DocumentSymbol#range` - */ - TargetSelectionRange Range `json:"targetSelectionRange"` -} - -/** - * The log message parameters. - */ -type LogMessageParams struct { - /** - * The message type. See {@link MessageType} - */ - Type MessageType `json:"type"` - /** - * The actual message - */ - Message string `json:"message"` -} - -type LogTraceParams struct { - Message string `json:"message"` - Verbose string `json:"verbose,omitempty"` -} - -/** - * Client capabilities specific to the used markdown parser. - * - * @since 3.16.0 - */ -type MarkdownClientCapabilities struct { - /** - * The name of the parser. - */ - Parser string `json:"parser"` - /** - * The version of the parser. - */ - Version string `json:"version,omitempty"` -} - -/** - * MarkedString can be used to render human readable text. It is either a markdown string - * or a code-block that provides a language and a code snippet. The language identifier - * is semantically equal to the optional language identifier in fenced code blocks in GitHub - * issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting - * - * The pair of a language and a value is an equivalent to markdown: - * ```${language} - * ${value} - * ``` - * - * Note that markdown strings will be sanitized - that means html will be escaped. - * @deprecated use MarkupContent instead. - */ -type MarkedString = string /*string | { language: string; value: string }*/ - -/** - * A `MarkupContent` literal represents a string value which content is interpreted base on its - * kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds. - * - * If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues. - * See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting - * - * Here is an example how such a string can be constructed using JavaScript / TypeScript: - * ```ts - * let markdown: MarkdownContent = { - * kind: MarkupKind.Markdown, - * value: [ - * '# Header', - * 'Some text', - * '```typescript', - * 'someCode();', - * '```' - * ].join('\n') - * }; - * ``` - * - * *Please Note* that clients might sanitize the return markdown. A client could decide to - * remove HTML from the markdown to avoid script execution. - */ -type MarkupContent struct { - /** - * The type of the Markup - */ - Kind MarkupKind `json:"kind"` - /** - * The content itself - */ - Value string `json:"value"` -} - -/** - * Describes the content type that a client supports in various - * result literals like `Hover`, `ParameterInfo` or `CompletionItem`. - * - * Please note that `MarkupKinds` must not start with a `$`. This kinds - * are reserved for internal usage. - */ -type MarkupKind string - -type MessageActionItem struct { - /** - * A short title like 'Retry', 'Open Log' etc. - */ - Title string `json:"title"` -} - -/** - * The message type - */ -type MessageType float64 - -/** - * Moniker definition to match LSIF 0.5 moniker definition. - * - * @since 3.16.0 - */ -type Moniker struct { - /** - * The scheme of the moniker. For example tsc or .Net - */ - Scheme string `json:"scheme"` - /** - * The identifier of the moniker. The value is opaque in LSIF however - * schema owners are allowed to define the structure if they want. - */ - Identifier string `json:"identifier"` - /** - * The scope in which the moniker is unique - */ - Unique UniquenessLevel `json:"unique"` - /** - * The moniker kind if known. - */ - Kind MonikerKind `json:"kind,omitempty"` -} - -/** - * Client capabilities specific to the moniker request. - * - * @since 3.16.0 - */ -type MonikerClientCapabilities struct { - /** - * Whether moniker supports dynamic registration. If this is set to `true` - * the client supports the new `MonikerRegistrationOptions` return value - * for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * The moniker kind. - * - * @since 3.16.0 - */ -type MonikerKind string - -type MonikerOptions struct { - WorkDoneProgressOptions -} - -type MonikerParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -type MonikerRegistrationOptions struct { - TextDocumentRegistrationOptions - MonikerOptions -} - -/** - * A text document identifier to optionally denote a specific version of a text document. - */ -type OptionalVersionedTextDocumentIdentifier struct { - /** - * The version number of this document. If a versioned text document identifier - * is sent from the server to the client and the file is not open in the editor - * (the server has not received an open notification before) the server can send - * `null` to indicate that the version is unknown and the content on disk is the - * truth (as specified with document content ownership). - */ - Version int32/*integer | null*/ `json:"version"` - TextDocumentIdentifier -} - -/** - * Represents a parameter of a callable-signature. A parameter can - * have a label and a doc-comment. - */ -type ParameterInformation struct { - /** - * The label of this parameter information. - * - * Either a string or an inclusive start and exclusive end offsets within its containing - * signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 - * string representation as `Position` and `Range` does. - * - * *Note*: a label of type string should be a substring of its containing signature label. - * Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. - */ - Label string/*string | [uinteger, uinteger]*/ `json:"label"` - /** - * The human-readable doc-comment of this signature. Will be shown - * in the UI but can be omitted. - */ - Documentation string/*string | MarkupContent*/ `json:"documentation,omitempty"` -} - -type PartialResultParams struct { - /** - * An optional token that a server can use to report partial results (e.g. streaming) to - * the client. - */ - PartialResultToken ProgressToken `json:"partialResultToken,omitempty"` -} - -/** - * Position in a text document expressed as zero-based line and character offset. - * The offsets are based on a UTF-16 string representation. So a string of the form - * `a𐐀b` the character offset of the character `a` is 0, the character offset of `𐐀` - * is 1 and the character offset of b is 3 since `𐐀` is represented using two code - * units in UTF-16. - * - * Positions are line end character agnostic. So you can not specify a position that - * denotes `\r|\n` or `\n|` where `|` represents the character offset. - */ -type Position struct { - /** - * Line position in a document (zero-based). - */ - Line uint32 `json:"line"` - /** - * Character offset on a line in a document (zero-based). Assuming that the line is - * represented as a string, the `character` value represents the gap between the - * `character` and `character + 1`. - * - * If the character value is greater than the line length it defaults back to the - * line length. - */ - Character uint32 `json:"character"` -} - -type PrepareRenameParams struct { - TextDocumentPositionParams - WorkDoneProgressParams -} - -type PrepareSupportDefaultBehavior = interface{} - -/** - * A previous result id in a workspace pull request. - * - * @since 3.17.0 - proposed state - */ -type PreviousResultID = struct { - /** - * The URI for which the client knowns a - * result id. - */ - URI DocumentURI `json:"uri"` - /** - * The value of the previous result id. - */ - Value string `json:"value"` -} - -type ProgressParams struct { - /** - * The progress token provided by the client or server. - */ - Token ProgressToken `json:"token"` - /** - * The progress data. - */ - Value interface{} `json:"value"` -} - -type ProgressToken = interface{} /*number | string*/ - -/** - * The publish diagnostic client capabilities. - */ -type PublishDiagnosticsClientCapabilities struct { - /** - * Whether the clients accepts diagnostics with related information. - */ - RelatedInformation bool `json:"relatedInformation,omitempty"` - /** - * Client supports the tag property to provide meta data about a diagnostic. - * Clients supporting tags have to handle unknown tags gracefully. - * - * @since 3.15.0 - */ - TagSupport struct { - /** - * The tags supported by the client. - */ - ValueSet []DiagnosticTag `json:"valueSet"` - } `json:"tagSupport,omitempty"` - /** - * Whether the client interprets the version property of the - * `textDocument/publishDiagnostics` notification`s parameter. - * - * @since 3.15.0 - */ - VersionSupport bool `json:"versionSupport,omitempty"` - /** - * Client supports a codeDescription property - * - * @since 3.16.0 - */ - CodeDescriptionSupport bool `json:"codeDescriptionSupport,omitempty"` - /** - * Whether code action supports the `data` property which is - * preserved between a `textDocument/publishDiagnostics` and - * `textDocument/codeAction` request. - * - * @since 3.16.0 - */ - DataSupport bool `json:"dataSupport,omitempty"` -} - -/** - * The publish diagnostic notification's parameters. - */ -type PublishDiagnosticsParams struct { - /** - * The URI for which diagnostic information is reported. - */ - URI DocumentURI `json:"uri"` - /** - * Optional the version number of the document the diagnostics are published for. - * - * @since 3.15.0 - */ - Version int32 `json:"version,omitempty"` - /** - * An array of diagnostic information items. - */ - Diagnostics []Diagnostic `json:"diagnostics"` -} - -/** - * A range in a text document expressed as (zero-based) start and end positions. - * - * If you want to specify a range that contains a line including the line ending - * character(s) then use an end position denoting the start of the next line. - * For example: - * ```ts - * { - * start: { line: 5, character: 23 } - * end : { line 6, character : 0 } - * } - * ``` - */ -type Range struct { - /** - * The range's start position - */ - Start Position `json:"start"` - /** - * The range's end position. - */ - End Position `json:"end"` -} - -/** - * Client Capabilities for a [ReferencesRequest](#ReferencesRequest). - */ -type ReferenceClientCapabilities struct { - /** - * Whether references supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -/** - * Value-object that contains additional information when - * requesting references. - */ -type ReferenceContext struct { - /** - * Include the declaration of the current symbol. - */ - IncludeDeclaration bool `json:"includeDeclaration"` -} - -/** - * Reference options. - */ -type ReferenceOptions struct { - WorkDoneProgressOptions -} - -/** - * Parameters for a [ReferencesRequest](#ReferencesRequest). - */ -type ReferenceParams struct { - Context ReferenceContext `json:"context"` - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -/** - * General parameters to to register for an notification or to register a provider. - */ -type Registration struct { - /** - * The id used to register the request. The id can be used to deregister - * the request again. - */ - ID string `json:"id"` - /** - * The method to register for. - */ - Method string `json:"method"` - /** - * Options necessary for the registration. - */ - RegisterOptions interface{} `json:"registerOptions,omitempty"` -} - -type RegistrationParams struct { - Registrations []Registration `json:"registrations"` -} - -/** - * Client capabilities specific to regular expressions. - * - * @since 3.16.0 - */ -type RegularExpressionsClientCapabilities struct { - /** - * The engine's name. - */ - Engine string `json:"engine"` - /** - * The engine's version. - */ - Version string `json:"version,omitempty"` -} - -/** - * A full diagnostic report with a set of related documents. - * - * @since 3.17.0 - proposed state - */ -type RelatedFullDocumentDiagnosticReport struct { - /** - * Diagnostics of related documents. This information is useful - * in programming languages where code in a file A can generate - * diagnostics in a file B which A depends on. An example of - * such a language is C/C++ where marco definitions in a file - * a.cpp and result in errors in a header file b.hpp. - * - * @since 3.17.0 - proposed state - */ - RelatedDocuments map[string]interface{}/*[uri: string ** DocumentUri *]: FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport;*/ `json:"relatedDocuments,omitempty"` - FullDocumentDiagnosticReport -} - -/** - * An unchanged diagnostic report with a set of related documents. - * - * @since 3.17.0 - proposed state - */ -type RelatedUnchangedDocumentDiagnosticReport struct { - /** - * Diagnostics of related documents. This information is useful - * in programming languages where code in a file A can generate - * diagnostics in a file B which A depends on. An example of - * such a language is C/C++ where marco definitions in a file - * a.cpp and result in errors in a header file b.hpp. - * - * @since 3.17.0 - proposed state - */ - RelatedDocuments map[string]interface{}/*[uri: string ** DocumentUri *]: FullDocumentDiagnosticReport | UnchangedDocumentDiagnosticReport;*/ `json:"relatedDocuments,omitempty"` - UnchangedDocumentDiagnosticReport -} - -type RenameClientCapabilities struct { - /** - * Whether rename supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Client supports testing for validity of rename operations - * before execution. - * - * @since 3.12.0 - */ - PrepareSupport bool `json:"prepareSupport,omitempty"` - /** - * Client supports the default behavior result. - * - * The value indicates the default behavior used by the - * client. - * - * @since 3.16.0 - */ - PrepareSupportDefaultBehavior PrepareSupportDefaultBehavior `json:"prepareSupportDefaultBehavior,omitempty"` - /** - * Whether th client honors the change annotations in - * text edits and resource operations returned via the - * rename request's workspace edit by for example presenting - * the workspace edit in the user interface and asking - * for confirmation. - * - * @since 3.16.0 - */ - HonorsChangeAnnotations bool `json:"honorsChangeAnnotations,omitempty"` -} - -/** - * Rename file operation - */ -type RenameFile struct { - /** - * A rename - */ - Kind string `json:"kind"` - /** - * The old (existing) location. - */ - OldURI DocumentURI `json:"oldUri"` - /** - * The new location. - */ - NewURI DocumentURI `json:"newUri"` - /** - * Rename options. - */ - Options RenameFileOptions `json:"options,omitempty"` - ResourceOperation -} - -/** - * Rename file options - */ -type RenameFileOptions struct { - /** - * Overwrite target if existing. Overwrite wins over `ignoreIfExists` - */ - Overwrite bool `json:"overwrite,omitempty"` - /** - * Ignores if target exists. - */ - IgnoreIfExists bool `json:"ignoreIfExists,omitempty"` -} - -/** - * The parameters sent in file rename requests/notifications. - * - * @since 3.16.0 - */ -type RenameFilesParams struct { - /** - * An array of all files/folders renamed in this operation. When a folder is renamed, only - * the folder will be included, and not its children. - */ - Files []FileRename `json:"files"` -} - -/** - * Provider options for a [RenameRequest](#RenameRequest). - */ -type RenameOptions struct { - /** - * Renames should be checked and tested before being executed. - * - * @since version 3.12.0 - */ - PrepareProvider bool `json:"prepareProvider,omitempty"` - WorkDoneProgressOptions -} - -/** - * The parameters of a [RenameRequest](#RenameRequest). - */ -type RenameParams struct { - /** - * The document to rename. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The position at which this request was sent. - */ - Position Position `json:"position"` - /** - * The new name of the symbol. If the given name is not valid the - * request must return a [ResponseError](#ResponseError) with an - * appropriate message set. - */ - NewName string `json:"newName"` - WorkDoneProgressParams -} - -/** - * A generic resource operation. - */ -type ResourceOperation struct { - /** - * The resource operation kind. - */ - Kind string `json:"kind"` - /** - * An optional annotation identifier describing the operation. - * - * @since 3.16.0 - */ - AnnotationID ChangeAnnotationIdentifier `json:"annotationId,omitempty"` -} - -type ResourceOperationKind string - -/** - * Save options. - */ -type SaveOptions struct { - /** - * The client is supposed to include the content on save. - */ - IncludeText bool `json:"includeText,omitempty"` -} - -/** - * A selection range represents a part of a selection hierarchy. A selection range - * may have a parent selection range that contains it. - */ -type SelectionRange struct { - /** - * The [range](#Range) of this selection range. - */ - Range Range `json:"range"` - /** - * The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. - */ - Parent *SelectionRange `json:"parent,omitempty"` -} - -type SelectionRangeClientCapabilities struct { - /** - * Whether implementation supports dynamic registration for selection range providers. If this is set to `true` - * the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server - * capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` -} - -type SelectionRangeOptions struct { - WorkDoneProgressOptions -} - -/** - * A parameter literal used in selection range requests. - */ -type SelectionRangeParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The positions inside the text document. - */ - Positions []Position `json:"positions"` - WorkDoneProgressParams - PartialResultParams -} - -type SelectionRangeRegistrationOptions struct { - SelectionRangeOptions - TextDocumentRegistrationOptions - StaticRegistrationOptions -} - -/** - * @since 3.16.0 - */ -type SemanticTokens struct { - /** - * An optional result id. If provided and clients support delta updating - * the client will include the result id in the next semantic token request. - * A server can then instead of computing all semantic tokens again simply - * send a delta. - */ - ResultID string `json:"resultId,omitempty"` - /** - * The actual tokens. - */ - Data []uint32 `json:"data"` -} - -/** - * @since 3.16.0 - */ -type SemanticTokensClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` - * return value for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Which requests the client supports and might send to the server - * depending on the server's capability. Please note that clients might not - * show semantic tokens or degrade some of the user experience if a range - * or full request is advertised by the client but not provided by the - * server. If for example the client capability `requests.full` and - * `request.range` are both set to true but the server only provides a - * range provider the client might not render a minimap correctly or might - * even decide to not show any semantic tokens at all. - */ - Requests struct { - /** - * The client will send the `textDocument/semanticTokens/range` request if - * the server provides a corresponding handler. - */ - Range bool/*boolean | { }*/ `json:"range,omitempty"` - /** - * The client will send the `textDocument/semanticTokens/full` request if - * the server provides a corresponding handler. - */ - Full interface{}/*boolean | */ `json:"full,omitempty"` - } `json:"requests"` - /** - * The token types that the client supports. - */ - TokenTypes []string `json:"tokenTypes"` - /** - * The token modifiers that the client supports. - */ - TokenModifiers []string `json:"tokenModifiers"` - /** - * The token formats the clients supports. - */ - Formats []TokenFormat `json:"formats"` - /** - * Whether the client supports tokens that can overlap each other. - */ - OverlappingTokenSupport bool `json:"overlappingTokenSupport,omitempty"` - /** - * Whether the client supports tokens that can span multiple lines. - */ - MultilineTokenSupport bool `json:"multilineTokenSupport,omitempty"` -} - -/** - * @since 3.16.0 - */ -type SemanticTokensDelta struct { - ResultID string `json:"resultId,omitempty"` - /** - * The semantic token edits to transform a previous result into a new result. - */ - Edits []SemanticTokensEdit `json:"edits"` -} - -/** - * @since 3.16.0 - */ -type SemanticTokensDeltaParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The result id of a previous response. The result Id can either point to a full response - * or a delta response depending on what was received last. - */ - PreviousResultID string `json:"previousResultId"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * @since 3.16.0 - */ -type SemanticTokensEdit struct { - /** - * The start offset of the edit. - */ - Start uint32 `json:"start"` - /** - * The count of elements to remove. - */ - DeleteCount uint32 `json:"deleteCount"` - /** - * The elements to insert. - */ - Data []uint32 `json:"data,omitempty"` -} - -/** - * @since 3.16.0 - */ -type SemanticTokensLegend struct { - /** - * The token types a server uses. - */ - TokenTypes []string `json:"tokenTypes"` - /** - * The token modifiers a server uses. - */ - TokenModifiers []string `json:"tokenModifiers"` -} - -/** - * @since 3.16.0 - */ -type SemanticTokensOptions struct { - /** - * The legend used by the server - */ - Legend SemanticTokensLegend `json:"legend"` - /** - * Server supports providing semantic tokens for a specific range - * of a document. - */ - Range bool/*boolean | { }*/ `json:"range,omitempty"` - /** - * Server supports providing semantic tokens for a full document. - */ - Full interface{}/*boolean | */ `json:"full,omitempty"` - WorkDoneProgressOptions -} - -/** - * @since 3.16.0 - */ -type SemanticTokensParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * @since 3.16.0 - */ -type SemanticTokensRangeParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The range the semantic tokens are requested for. - */ - Range Range `json:"range"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * @since 3.16.0 - */ -type SemanticTokensRegistrationOptions struct { - TextDocumentRegistrationOptions - SemanticTokensOptions - StaticRegistrationOptions -} - -/** - * @since 3.16.0 - */ -type SemanticTokensWorkspaceClientCapabilities struct { - /** - * Whether the client implementation supports a refresh request sent from - * the server to the client. - * - * Note that this event is global and will force the client to refresh all - * semantic tokens currently shown. It should be used with absolute care - * and is useful for situation where a server for example detects a project - * wide change that requires such a calculation. - */ - RefreshSupport bool `json:"refreshSupport,omitempty"` -} - -type ServerCapabilities struct { - /** - * Defines how text documents are synced. Is either a detailed structure defining each notification or - * for backwards compatibility the TextDocumentSyncKind number. - */ - TextDocumentSync interface{}/*TextDocumentSyncOptions | TextDocumentSyncKind*/ `json:"textDocumentSync,omitempty"` - /** - * The server provides completion support. - */ - CompletionProvider *CompletionOptions `json:"completionProvider,omitempty"` - /** - * The server provides hover support. - */ - HoverProvider bool/*boolean | HoverOptions*/ `json:"hoverProvider,omitempty"` - /** - * The server provides signature help support. - */ - SignatureHelpProvider *SignatureHelpOptions `json:"signatureHelpProvider,omitempty"` - /** - * The server provides Goto Declaration support. - */ - DeclarationProvider interface{}/* bool | DeclarationOptions | DeclarationRegistrationOptions*/ `json:"declarationProvider,omitempty"` - /** - * The server provides goto definition support. - */ - DefinitionProvider bool/*boolean | DefinitionOptions*/ `json:"definitionProvider,omitempty"` - /** - * The server provides Goto Type Definition support. - */ - TypeDefinitionProvider interface{}/* bool | TypeDefinitionOptions | TypeDefinitionRegistrationOptions*/ `json:"typeDefinitionProvider,omitempty"` - /** - * The server provides Goto Implementation support. - */ - ImplementationProvider interface{}/* bool | ImplementationOptions | ImplementationRegistrationOptions*/ `json:"implementationProvider,omitempty"` - /** - * The server provides find references support. - */ - ReferencesProvider bool/*boolean | ReferenceOptions*/ `json:"referencesProvider,omitempty"` - /** - * The server provides document highlight support. - */ - DocumentHighlightProvider bool/*boolean | DocumentHighlightOptions*/ `json:"documentHighlightProvider,omitempty"` - /** - * The server provides document symbol support. - */ - DocumentSymbolProvider bool/*boolean | DocumentSymbolOptions*/ `json:"documentSymbolProvider,omitempty"` - /** - * The server provides code actions. CodeActionOptions may only be - * specified if the client states that it supports - * `codeActionLiteralSupport` in its initial `initialize` request. - */ - CodeActionProvider interface{}/*boolean | CodeActionOptions*/ `json:"codeActionProvider,omitempty"` - /** - * The server provides code lens. - */ - CodeLensProvider *CodeLensOptions `json:"codeLensProvider,omitempty"` - /** - * The server provides document link support. - */ - DocumentLinkProvider *DocumentLinkOptions `json:"documentLinkProvider,omitempty"` - /** - * The server provides color provider support. - */ - ColorProvider interface{}/* bool | DocumentColorOptions | DocumentColorRegistrationOptions*/ `json:"colorProvider,omitempty"` - /** - * The server provides workspace symbol support. - */ - WorkspaceSymbolProvider bool/*boolean | WorkspaceSymbolOptions*/ `json:"workspaceSymbolProvider,omitempty"` - /** - * The server provides document formatting. - */ - DocumentFormattingProvider bool/*boolean | DocumentFormattingOptions*/ `json:"documentFormattingProvider,omitempty"` - /** - * The server provides document range formatting. - */ - DocumentRangeFormattingProvider bool/*boolean | DocumentRangeFormattingOptions*/ `json:"documentRangeFormattingProvider,omitempty"` - /** - * The server provides document formatting on typing. - */ - DocumentOnTypeFormattingProvider *DocumentOnTypeFormattingOptions `json:"documentOnTypeFormattingProvider,omitempty"` - /** - * The server provides rename support. RenameOptions may only be - * specified if the client states that it supports - * `prepareSupport` in its initial `initialize` request. - */ - RenameProvider interface{}/*boolean | RenameOptions*/ `json:"renameProvider,omitempty"` - /** - * The server provides folding provider support. - */ - FoldingRangeProvider interface{}/* bool | FoldingRangeOptions | FoldingRangeRegistrationOptions*/ `json:"foldingRangeProvider,omitempty"` - /** - * The server provides selection range support. - */ - SelectionRangeProvider interface{}/* bool | SelectionRangeOptions | SelectionRangeRegistrationOptions*/ `json:"selectionRangeProvider,omitempty"` - /** - * The server provides execute command support. - */ - ExecuteCommandProvider *ExecuteCommandOptions `json:"executeCommandProvider,omitempty"` - /** - * The server provides call hierarchy support. - * - * @since 3.16.0 - */ - CallHierarchyProvider interface{}/* bool | CallHierarchyOptions | CallHierarchyRegistrationOptions*/ `json:"callHierarchyProvider,omitempty"` - /** - * The server provides linked editing range support. - * - * @since 3.16.0 - */ - LinkedEditingRangeProvider interface{}/* bool | LinkedEditingRangeOptions | LinkedEditingRangeRegistrationOptions*/ `json:"linkedEditingRangeProvider,omitempty"` - /** - * The server provides semantic tokens support. - * - * @since 3.16.0 - */ - SemanticTokensProvider interface{}/*SemanticTokensOptions | SemanticTokensRegistrationOptions*/ `json:"semanticTokensProvider,omitempty"` - /** - * The workspace server capabilities - */ - Workspace Workspace5Gn `json:"workspace,omitempty"` - /** - * The server provides moniker support. - * - * @since 3.16.0 - */ - MonikerProvider interface{}/* bool | MonikerOptions | MonikerRegistrationOptions*/ `json:"monikerProvider,omitempty"` - /** - * Experimental server capabilities. - */ - Experimental interface{} `json:"experimental,omitempty"` -} - -type SetTraceParams struct { - Value TraceValues `json:"value"` -} - -/** - * Client capabilities for the show document request. - * - * @since 3.16.0 - */ -type ShowDocumentClientCapabilities struct { - /** - * The client has support for the show document - * request. - */ - Support bool `json:"support"` -} - -/** - * Params to show a document. - * - * @since 3.16.0 - */ -type ShowDocumentParams struct { - /** - * The document uri to show. - */ - URI URI `json:"uri"` - /** - * Indicates to show the resource in an external program. - * To show for example `https://code.visualstudio.com/` - * in the default WEB browser set `external` to `true`. - */ - External bool `json:"external,omitempty"` - /** - * An optional property to indicate whether the editor - * showing the document should take focus or not. - * Clients might ignore this property if an external - * program in started. - */ - TakeFocus bool `json:"takeFocus,omitempty"` - /** - * An optional selection range if the document is a text - * document. Clients might ignore the property if an - * external program is started or the file is not a text - * file. - */ - Selection Range `json:"selection,omitempty"` -} - -/** - * The result of an show document request. - * - * @since 3.16.0 - */ -type ShowDocumentResult struct { - /** - * A boolean indicating if the show was successful. - */ - Success bool `json:"success"` -} - -/** - * The parameters of a notification message. - */ -type ShowMessageParams struct { - /** - * The message type. See {@link MessageType} - */ - Type MessageType `json:"type"` - /** - * The actual message - */ - Message string `json:"message"` -} - -/** - * Show message request client capabilities - */ -type ShowMessageRequestClientCapabilities struct { - /** - * Capabilities specific to the `MessageActionItem` type. - */ - MessageActionItem struct { - /** - * Whether the client supports additional attributes which - * are preserved and send back to the server in the - * request's response. - */ - AdditionalPropertiesSupport bool `json:"additionalPropertiesSupport,omitempty"` - } `json:"messageActionItem,omitempty"` -} - -type ShowMessageRequestParams struct { - /** - * The message type. See {@link MessageType} - */ - Type MessageType `json:"type"` - /** - * The actual message - */ - Message string `json:"message"` - /** - * The message action items to present. - */ - Actions []MessageActionItem `json:"actions,omitempty"` -} - -/** - * Signature help represents the signature of something - * callable. There can be multiple signature but only one - * active and only one active parameter. - */ -type SignatureHelp struct { - /** - * One or more signatures. - */ - Signatures []SignatureInformation `json:"signatures"` - /** - * The active signature. Set to `null` if no - * signatures exist. - */ - ActiveSignature uint32/*uinteger | null*/ `json:"activeSignature"` - /** - * The active parameter of the active signature. Set to `null` - * if the active signature has no parameters. - */ - ActiveParameter uint32/*uinteger | null*/ `json:"activeParameter"` -} - -/** - * Client Capabilities for a [SignatureHelpRequest](#SignatureHelpRequest). - */ -type SignatureHelpClientCapabilities struct { - /** - * Whether signature help supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports the following `SignatureInformation` - * specific properties. - */ - SignatureInformation struct { - /** - * Client supports the follow content formats for the documentation - * property. The order describes the preferred format of the client. - */ - DocumentationFormat []MarkupKind `json:"documentationFormat,omitempty"` - /** - * Client capabilities specific to parameter information. - */ - ParameterInformation struct { - /** - * The client supports processing label offsets instead of a - * simple label string. - * - * @since 3.14.0 - */ - LabelOffsetSupport bool `json:"labelOffsetSupport,omitempty"` - } `json:"parameterInformation,omitempty"` - /** - * The client support the `activeParameter` property on `SignatureInformation` - * literal. - * - * @since 3.16.0 - */ - ActiveParameterSupport bool `json:"activeParameterSupport,omitempty"` - } `json:"signatureInformation,omitempty"` - /** - * The client supports to send additional context information for a - * `textDocument/signatureHelp` request. A client that opts into - * contextSupport will also support the `retriggerCharacters` on - * `SignatureHelpOptions`. - * - * @since 3.15.0 - */ - ContextSupport bool `json:"contextSupport,omitempty"` -} - -/** - * Additional information about the context in which a signature help request was triggered. - * - * @since 3.15.0 - */ -type SignatureHelpContext struct { - /** - * Action that caused signature help to be triggered. - */ - TriggerKind SignatureHelpTriggerKind `json:"triggerKind"` - /** - * Character that caused signature help to be triggered. - * - * This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` - */ - TriggerCharacter string `json:"triggerCharacter,omitempty"` - /** - * `true` if signature help was already showing when it was triggered. - * - * Retrigger occurs when the signature help is already active and can be caused by actions such as - * typing a trigger character, a cursor move, or document content changes. - */ - IsRetrigger bool `json:"isRetrigger"` - /** - * The currently active `SignatureHelp`. - * - * The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on - * the user navigating through available signatures. - */ - ActiveSignatureHelp SignatureHelp `json:"activeSignatureHelp,omitempty"` -} - -/** - * Server Capabilities for a [SignatureHelpRequest](#SignatureHelpRequest). - */ -type SignatureHelpOptions struct { - /** - * List of characters that trigger signature help. - */ - TriggerCharacters []string `json:"triggerCharacters,omitempty"` - /** - * List of characters that re-trigger signature help. - * - * These trigger characters are only active when signature help is already showing. All trigger characters - * are also counted as re-trigger characters. - * - * @since 3.15.0 - */ - RetriggerCharacters []string `json:"retriggerCharacters,omitempty"` - WorkDoneProgressOptions -} - -/** - * Parameters for a [SignatureHelpRequest](#SignatureHelpRequest). - */ -type SignatureHelpParams struct { - /** - * The signature help context. This is only available if the client specifies - * to send this using the client capability `textDocument.signatureHelp.contextSupport === true` - * - * @since 3.15.0 - */ - Context SignatureHelpContext `json:"context,omitempty"` - TextDocumentPositionParams - WorkDoneProgressParams -} - -/** - * How a signature help was triggered. - * - * @since 3.15.0 - */ -type SignatureHelpTriggerKind float64 - -/** - * Represents the signature of something callable. A signature - * can have a label, like a function-name, a doc-comment, and - * a set of parameters. - */ -type SignatureInformation struct { - /** - * The label of this signature. Will be shown in - * the UI. - */ - Label string `json:"label"` - /** - * The human-readable doc-comment of this signature. Will be shown - * in the UI but can be omitted. - */ - Documentation string/*string | MarkupContent*/ `json:"documentation,omitempty"` - /** - * The parameters of this signature. - */ - Parameters []ParameterInformation `json:"parameters,omitempty"` - /** - * The index of the active parameter. - * - * If provided, this is used in place of `SignatureHelp.activeParameter`. - * - * @since 3.16.0 - */ - ActiveParameter uint32 `json:"activeParameter,omitempty"` -} - -/** - * Static registration options to be returned in the initialize - * request. - */ -type StaticRegistrationOptions struct { - /** - * The id used to register the request. The id can be used to deregister - * the request again. See also Registration#id. - */ - ID string `json:"id,omitempty"` -} - -/** - * Represents information about programming constructs like variables, classes, - * interfaces etc. - */ -type SymbolInformation struct { - /** - * The name of this symbol. - */ - Name string `json:"name"` - /** - * The kind of this symbol. - */ - Kind SymbolKind `json:"kind"` - /** - * Tags for this completion item. - * - * @since 3.16.0 - */ - Tags []SymbolTag `json:"tags,omitempty"` - /** - * Indicates if this symbol is deprecated. - * - * @deprecated Use tags instead - */ - Deprecated bool `json:"deprecated,omitempty"` - /** - * The location of this symbol. The location's range is used by a tool - * to reveal the location in the editor. If the symbol is selected in the - * tool the range's start information is used to position the cursor. So - * the range usually spans more than the actual symbol's name and does - * normally include thinks like visibility modifiers. - * - * The range doesn't have to denote a node range in the sense of a abstract - * syntax tree. It can therefore not be used to re-construct a hierarchy of - * the symbols. - */ - Location Location `json:"location"` - /** - * The name of the symbol containing this symbol. This information is for - * user interface purposes (e.g. to render a qualifier in the user interface - * if necessary). It can't be used to re-infer a hierarchy for the document - * symbols. - */ - ContainerName string `json:"containerName,omitempty"` -} - -/** - * A symbol kind. - */ -type SymbolKind float64 - -/** - * Symbol tags are extra annotations that tweak the rendering of a symbol. - * @since 3.16 - */ -type SymbolTag float64 - -/** - * Text document specific client capabilities. - */ -type TextDocumentClientCapabilities struct { - /** - * Defines which synchronization capabilities the client supports. - */ - Synchronization TextDocumentSyncClientCapabilities `json:"synchronization,omitempty"` - /** - * Capabilities specific to the `textDocument/completion` - */ - Completion CompletionClientCapabilities `json:"completion,omitempty"` - /** - * Capabilities specific to the `textDocument/hover` - */ - Hover HoverClientCapabilities `json:"hover,omitempty"` - /** - * Capabilities specific to the `textDocument/signatureHelp` - */ - SignatureHelp SignatureHelpClientCapabilities `json:"signatureHelp,omitempty"` - /** - * Capabilities specific to the `textDocument/declaration` - * - * @since 3.14.0 - */ - Declaration DeclarationClientCapabilities `json:"declaration,omitempty"` - /** - * Capabilities specific to the `textDocument/definition` - */ - Definition DefinitionClientCapabilities `json:"definition,omitempty"` - /** - * Capabilities specific to the `textDocument/typeDefinition` - * - * @since 3.6.0 - */ - TypeDefinition TypeDefinitionClientCapabilities `json:"typeDefinition,omitempty"` - /** - * Capabilities specific to the `textDocument/implementation` - * - * @since 3.6.0 - */ - Implementation ImplementationClientCapabilities `json:"implementation,omitempty"` - /** - * Capabilities specific to the `textDocument/references` - */ - References ReferenceClientCapabilities `json:"references,omitempty"` - /** - * Capabilities specific to the `textDocument/documentHighlight` - */ - DocumentHighlight DocumentHighlightClientCapabilities `json:"documentHighlight,omitempty"` - /** - * Capabilities specific to the `textDocument/documentSymbol` - */ - DocumentSymbol DocumentSymbolClientCapabilities `json:"documentSymbol,omitempty"` - /** - * Capabilities specific to the `textDocument/codeAction` - */ - CodeAction CodeActionClientCapabilities `json:"codeAction,omitempty"` - /** - * Capabilities specific to the `textDocument/codeLens` - */ - CodeLens CodeLensClientCapabilities `json:"codeLens,omitempty"` - /** - * Capabilities specific to the `textDocument/documentLink` - */ - DocumentLink DocumentLinkClientCapabilities `json:"documentLink,omitempty"` - /** - * Capabilities specific to the `textDocument/documentColor` - */ - ColorProvider DocumentColorClientCapabilities `json:"colorProvider,omitempty"` - /** - * Capabilities specific to the `textDocument/formatting` - */ - Formatting DocumentFormattingClientCapabilities `json:"formatting,omitempty"` - /** - * Capabilities specific to the `textDocument/rangeFormatting` - */ - RangeFormatting DocumentRangeFormattingClientCapabilities `json:"rangeFormatting,omitempty"` - /** - * Capabilities specific to the `textDocument/onTypeFormatting` - */ - OnTypeFormatting DocumentOnTypeFormattingClientCapabilities `json:"onTypeFormatting,omitempty"` - /** - * Capabilities specific to the `textDocument/rename` - */ - Rename RenameClientCapabilities `json:"rename,omitempty"` - /** - * Capabilities specific to `textDocument/foldingRange` request. - * - * @since 3.10.0 - */ - FoldingRange FoldingRangeClientCapabilities `json:"foldingRange,omitempty"` - /** - * Capabilities specific to `textDocument/selectionRange` request. - * - * @since 3.15.0 - */ - SelectionRange SelectionRangeClientCapabilities `json:"selectionRange,omitempty"` - /** - * Capabilities specific to `textDocument/publishDiagnostics` notification. - */ - PublishDiagnostics PublishDiagnosticsClientCapabilities `json:"publishDiagnostics,omitempty"` - /** - * Capabilities specific to the various call hierarchy request. - * - * @since 3.16.0 - */ - CallHierarchy CallHierarchyClientCapabilities `json:"callHierarchy,omitempty"` - /** - * Capabilities specific to the various semantic token request. - * - * @since 3.16.0 - */ - SemanticTokens SemanticTokensClientCapabilities `json:"semanticTokens,omitempty"` - /** - * Capabilities specific to the linked editing range request. - * - * @since 3.16.0 - */ - LinkedEditingRange LinkedEditingRangeClientCapabilities `json:"linkedEditingRange,omitempty"` - /** - * Client capabilities specific to the moniker request. - * - * @since 3.16.0 - */ - Moniker MonikerClientCapabilities `json:"moniker,omitempty"` -} - -/** - * An event describing a change to a text document. If range and rangeLength are omitted - * the new text is considered to be the full content of the document. - */ -type TextDocumentContentChangeEvent = struct { - /** - * The range of the document that changed. - */ - Range *Range `json:"range,omitempty"` - /** - * The optional length of the range that got replaced. - * - * @deprecated use range instead. - */ - RangeLength uint32 `json:"rangeLength,omitempty"` - /** - * The new text for the provided range. - */ - Text string `json:"text"` -} - -/** - * Describes textual changes on a text document. A TextDocumentEdit describes all changes - * on a document version Si and after they are applied move the document to version Si+1. - * So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any - * kind of ordering. However the edits must be non overlapping. - */ -type TextDocumentEdit struct { - /** - * The text document to change. - */ - TextDocument OptionalVersionedTextDocumentIdentifier `json:"textDocument"` - /** - * The edits to be applied. - * - * @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a - * client capability. - */ - Edits []TextEdit/*TextEdit | AnnotatedTextEdit*/ `json:"edits"` -} - -/** - * A literal to identify a text document in the client. - */ -type TextDocumentIdentifier struct { - /** - * The text document's uri. - */ - URI DocumentURI `json:"uri"` -} - -/** - * An item to transfer a text document from the client to the - * server. - */ -type TextDocumentItem struct { - /** - * The text document's uri. - */ - URI DocumentURI `json:"uri"` - /** - * The text document's language identifier - */ - LanguageID string `json:"languageId"` - /** - * The version number of this document (it will increase after each - * change, including undo/redo). - */ - Version int32 `json:"version"` - /** - * The content of the opened text document. - */ - Text string `json:"text"` -} - -/** - * A parameter literal used in requests to pass a text document and a position inside that - * document. - */ -type TextDocumentPositionParams struct { - /** - * The text document. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The position inside the text document. - */ - Position Position `json:"position"` -} - -/** - * General text document registration options. - */ -type TextDocumentRegistrationOptions struct { - /** - * A document selector to identify the scope of the registration. If set to null - * the document selector provided on the client side will be used. - */ - DocumentSelector DocumentSelector /*DocumentSelector | null*/ `json:"documentSelector"` -} - -/** - * Represents reasons why a text document is saved. - */ -type TextDocumentSaveReason float64 - -type TextDocumentSyncClientCapabilities struct { - /** - * Whether text document synchronization supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports sending will save notifications. - */ - WillSave bool `json:"willSave,omitempty"` - /** - * The client supports sending a will save request and - * waits for a response providing text edits which will - * be applied to the document before it is saved. - */ - WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` - /** - * The client supports did save notifications. - */ - DidSave bool `json:"didSave,omitempty"` -} - -/** - * Defines how the host (editor) should sync - * document changes to the language server. - */ -type TextDocumentSyncKind float64 - -type TextDocumentSyncOptions struct { - /** - * Open and close notifications are sent to the server. If omitted open close notification should not - * be sent. - */ - OpenClose bool `json:"openClose,omitempty"` - /** - * Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full - * and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None. - */ - Change TextDocumentSyncKind `json:"change,omitempty"` - /** - * If present will save notifications are sent to the server. If omitted the notification should not be - * sent. - */ - WillSave bool `json:"willSave,omitempty"` - /** - * If present will save wait until requests are sent to the server. If omitted the request should not be - * sent. - */ - WillSaveWaitUntil bool `json:"willSaveWaitUntil,omitempty"` - /** - * If present save notifications are sent to the server. If omitted the notification should not be - * sent. - */ - Save *SaveOptions/*boolean | SaveOptions*/ `json:"save,omitempty"` -} - -/** - * A text edit applicable to a text document. - */ -type TextEdit struct { - /** - * The range of the text document to be manipulated. To insert - * text into a document create a range where start === end. - */ - Range Range `json:"range"` - /** - * The string to be inserted. For delete operations use an - * empty string. - */ - NewText string `json:"newText"` -} - -type TokenFormat = string - -type TraceValues = string /*'off' | 'messages' | 'verbose'*/ - -/** - * Since 3.6.0 - */ -type TypeDefinitionClientCapabilities struct { - /** - * Whether implementation supports dynamic registration. If this is set to `true` - * the client supports the new `TypeDefinitionRegistrationOptions` return value - * for the corresponding server capability as well. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * The client supports additional metadata in the form of definition links. - * - * Since 3.14.0 - */ - LinkSupport bool `json:"linkSupport,omitempty"` -} - -type TypeDefinitionOptions struct { - WorkDoneProgressOptions -} - -type TypeDefinitionParams struct { - TextDocumentPositionParams - WorkDoneProgressParams - PartialResultParams -} - -type TypeDefinitionRegistrationOptions struct { - TextDocumentRegistrationOptions - TypeDefinitionOptions - StaticRegistrationOptions -} - -/** - * A tagging type for string properties that are actually URIs - * - * @since 3.16.0 - */ -type URI = string - -/** - * A diagnostic report indicating that the last returned - * report is still accurate. - * - * @since 3.17.0 - proposed state - */ -type UnchangedDocumentDiagnosticReport struct { - /** - * A document diagnostic report indicating - * no changes to the last result. A server can - * only return `unchanged` if result ids are - * provided. - */ - Kind string `json:"kind"` - /** - * A result id which will be sent on the next - * diagnostic request for the same document. - */ - ResultID string `json:"resultId"` -} - -/** - * Moniker uniqueness level to define scope of the moniker. - * - * @since 3.16.0 - */ -type UniquenessLevel string - -/** - * General parameters to unregister a request or notification. - */ -type Unregistration struct { - /** - * The id used to unregister the request or notification. Usually an id - * provided during the register request. - */ - ID string `json:"id"` - /** - * The method to unregister for. - */ - Method string `json:"method"` -} - -type UnregistrationParams struct { - Unregisterations []Unregistration `json:"unregisterations"` -} - -/** - * A text document identifier to denote a specific version of a text document. - */ -type VersionedTextDocumentIdentifier struct { - /** - * The version number of this document. - */ - Version int32 `json:"version"` - TextDocumentIdentifier -} - -type WatchKind float64 - -/** - * The parameters send in a will save text document notification. - */ -type WillSaveTextDocumentParams struct { - /** - * The document that will be saved. - */ - TextDocument TextDocumentIdentifier `json:"textDocument"` - /** - * The 'TextDocumentSaveReason'. - */ - Reason TextDocumentSaveReason `json:"reason"` -} - -type WorkDoneProgressBegin struct { - Kind string `json:"kind"` - /** - * Mandatory title of the progress operation. Used to briefly inform about - * the kind of operation being performed. - * - * Examples: "Indexing" or "Linking dependencies". - */ - Title string `json:"title"` - /** - * Controls if a cancel button should show to allow the user to cancel the - * long running operation. Clients that don't support cancellation are allowed - * to ignore the setting. - */ - Cancellable bool `json:"cancellable,omitempty"` - /** - * Optional, more detailed associated progress message. Contains - * complementary information to the `title`. - * - * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". - * If unset, the previous progress message (if any) is still valid. - */ - Message string `json:"message,omitempty"` - /** - * Optional progress percentage to display (value 100 is considered 100%). - * If not provided infinite progress is assumed and clients are allowed - * to ignore the `percentage` value in subsequent in report notifications. - * - * The value should be steadily rising. Clients are free to ignore values - * that are not following this rule. The value range is [0, 100]. - */ - Percentage uint32 `json:"percentage,omitempty"` -} - -type WorkDoneProgressCancelParams struct { - /** - * The token to be used to report progress. - */ - Token ProgressToken `json:"token"` -} - -type WorkDoneProgressClientCapabilities struct { - /** - * Window specific client capabilities. - */ - Window struct { - /** - * Whether client supports server initiated progress using the - * `window/workDoneProgress/create` request. - * - * Since 3.15.0 - */ - WorkDoneProgress bool `json:"workDoneProgress,omitempty"` - /** - * Capabilities specific to the showMessage request. - * - * @since 3.16.0 - */ - ShowMessage ShowMessageRequestClientCapabilities `json:"showMessage,omitempty"` - /** - * Capabilities specific to the showDocument request. - * - * @since 3.16.0 - */ - ShowDocument ShowDocumentClientCapabilities `json:"showDocument,omitempty"` - } `json:"window,omitempty"` -} - -type WorkDoneProgressCreateParams struct { - /** - * The token to be used to report progress. - */ - Token ProgressToken `json:"token"` -} - -type WorkDoneProgressEnd struct { - Kind string `json:"kind"` - /** - * Optional, a final message indicating to for example indicate the outcome - * of the operation. - */ - Message string `json:"message,omitempty"` -} - -type WorkDoneProgressOptions struct { - WorkDoneProgress bool `json:"workDoneProgress,omitempty"` -} - -type WorkDoneProgressParams struct { - /** - * An optional token that a server can use to report work done progress. - */ - WorkDoneToken ProgressToken `json:"workDoneToken,omitempty"` -} - -type WorkDoneProgressReport struct { - Kind string `json:"kind"` - /** - * Controls enablement state of a cancel button. - * - * Clients that don't support cancellation or don't support controlling the button's - * enablement state are allowed to ignore the property. - */ - Cancellable bool `json:"cancellable,omitempty"` - /** - * Optional, more detailed associated progress message. Contains - * complementary information to the `title`. - * - * Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". - * If unset, the previous progress message (if any) is still valid. - */ - Message string `json:"message,omitempty"` - /** - * Optional progress percentage to display (value 100 is considered 100%). - * If not provided infinite progress is assumed and clients are allowed - * to ignore the `percentage` value in subsequent in report notifications. - * - * The value should be steadily rising. Clients are free to ignore values - * that are not following this rule. The value range is [0, 100] - */ - Percentage uint32 `json:"percentage,omitempty"` -} - -/** - * Workspace specific client capabilities. - */ -type WorkspaceClientCapabilities struct { - /** - * The client supports applying batch edits - * to the workspace by supporting the request - * 'workspace/applyEdit' - */ - ApplyEdit bool `json:"applyEdit,omitempty"` - /** - * Capabilities specific to `WorkspaceEdit`s - */ - WorkspaceEdit WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` - /** - * Capabilities specific to the `workspace/didChangeConfiguration` notification. - */ - DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` - /** - * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. - */ - DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` - /** - * Capabilities specific to the `workspace/symbol` request. - */ - Symbol WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` - /** - * Capabilities specific to the `workspace/executeCommand` request. - */ - ExecuteCommand ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` - /** - * Capabilities specific to the semantic token requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - SemanticTokens SemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitempty"` - /** - * Capabilities specific to the code lens requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - CodeLens CodeLensWorkspaceClientCapabilities `json:"codeLens,omitempty"` - /** - * The client has support for file notifications/requests for user operations on files. - * - * Since 3.16.0 - */ - FileOperations FileOperationClientCapabilities `json:"fileOperations,omitempty"` -} - -/** - * Parameters of the workspace diagnostic request. - * - * @since 3.17.0 - proposed state - */ -type WorkspaceDiagnosticParams struct { - /** - * The additional identifier provided during registration. - */ - Identifier string `json:"identifier,omitempty"` - /** - * The currently known diagnostic reports with their - * previous result ids. - */ - PreviousResultIds []PreviousResultID `json:"previousResultIds"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * A workspace diagnostic report. - * - * @since 3.17.0 - proposed state - */ -type WorkspaceDiagnosticReport struct { - Items []WorkspaceDocumentDiagnosticReport `json:"items"` -} - -/** - * A workspace diagnostic document report. - * - * @since 3.17.0 - proposed state - */ -type WorkspaceDocumentDiagnosticReport = interface{} /*WorkspaceFullDocumentDiagnosticReport | WorkspaceUnchangedDocumentDiagnosticReport*/ - -/** - * A workspace edit represents changes to many resources managed in the workspace. The edit - * should either provide `changes` or `documentChanges`. If documentChanges are present - * they are preferred over `changes` if the client can handle versioned document edits. - * - * Since version 3.13.0 a workspace edit can contain resource operations as well. If resource - * operations are present clients need to execute the operations in the order in which they - * are provided. So a workspace edit for example can consist of the following two changes: - * (1) a create file a.txt and (2) a text document edit which insert text into file a.txt. - * - * An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into file a.txt) will - * cause failure of the operation. How the client recovers from the failure is described by - * the client capability: `workspace.workspaceEdit.failureHandling` - */ -type WorkspaceEdit struct { - /** - * Holds changes to existing resources. - */ - Changes map[string][]TextEdit/*[uri: string]: TextEdit[];*/ `json:"changes,omitempty"` - /** - * Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes - * are either an array of `TextDocumentEdit`s to express changes to n different text documents - * where each text document edit addresses a specific version of a text document. Or it can contain - * above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations. - * - * Whether a client supports versioned document edits is expressed via - * `workspace.workspaceEdit.documentChanges` client capability. - * - * If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then - * only plain `TextEdit`s using the `changes` property are supported. - */ - DocumentChanges []TextDocumentEdit/*TextDocumentEdit | CreateFile | RenameFile | DeleteFile*/ `json:"documentChanges,omitempty"` - /** - * A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and - * delete file / folder operations. - * - * Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`. - * - * @since 3.16.0 - */ - ChangeAnnotations map[string]ChangeAnnotationIdentifier/*[id: string * ChangeAnnotationIdentifier *]: ChangeAnnotation;*/ `json:"changeAnnotations,omitempty"` -} - -type WorkspaceEditClientCapabilities struct { - /** - * The client supports versioned document changes in `WorkspaceEdit`s - */ - DocumentChanges bool `json:"documentChanges,omitempty"` - /** - * The resource operations the client supports. Clients should at least - * support 'create', 'rename' and 'delete' files and folders. - * - * @since 3.13.0 - */ - ResourceOperations []ResourceOperationKind `json:"resourceOperations,omitempty"` - /** - * The failure handling strategy of a client if applying the workspace edit - * fails. - * - * @since 3.13.0 - */ - FailureHandling FailureHandlingKind `json:"failureHandling,omitempty"` - /** - * Whether the client normalizes line endings to the client specific - * setting. - * If set to `true` the client will normalize line ending characters - * in a workspace edit containing to the client specific new line - * character. - * - * @since 3.16.0 - */ - NormalizesLineEndings bool `json:"normalizesLineEndings,omitempty"` - /** - * Whether the client in general supports change annotations on text edits, - * create file, rename file and delete file changes. - * - * @since 3.16.0 - */ - ChangeAnnotationSupport struct { - /** - * Whether the client groups edits with equal labels into tree nodes, - * for instance all edits labelled with "Changes in Strings" would - * be a tree node. - */ - GroupsOnLabel bool `json:"groupsOnLabel,omitempty"` - } `json:"changeAnnotationSupport,omitempty"` -} - -type WorkspaceFolder struct { - /** - * The associated URI for this workspace folder. - */ - URI string `json:"uri"` - /** - * The name of the workspace folder. Used to refer to this - * workspace folder in the user interface. - */ - Name string `json:"name"` -} - -/** - * The workspace folder change event. - */ -type WorkspaceFoldersChangeEvent struct { - /** - * The array of added workspace folders - */ - Added []WorkspaceFolder `json:"added"` - /** - * The array of the removed workspace folders - */ - Removed []WorkspaceFolder `json:"removed"` -} - -type WorkspaceFoldersClientCapabilities struct { - /** - * The workspace client capabilities - */ - Workspace Workspace6Gn `json:"workspace,omitempty"` -} - -type WorkspaceFoldersInitializeParams struct { - /** - * The actual configured workspace folders. - */ - WorkspaceFolders []WorkspaceFolder /*WorkspaceFolder[] | null*/ `json:"workspaceFolders"` -} - -type WorkspaceFoldersServerCapabilities struct { - /** - * The workspace server capabilities - */ - Workspace Workspace8Gn `json:"workspace,omitempty"` -} - -/** - * A full document diagnostic report for a workspace diagnostic result. - * - * @since 3.17.0 - proposed state - */ -type WorkspaceFullDocumentDiagnosticReport struct { - /** - * The URI for which diagnostic information is reported. - */ - URI DocumentURI `json:"uri"` - /** - * The version number for which the diagnostics are reported. - * If the document is not marked as open `null` can be provided. - */ - Version int32/*integer | null*/ `json:"version"` - FullDocumentDiagnosticReport -} - -/** - * Client capabilities for a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). - */ -type WorkspaceSymbolClientCapabilities struct { - /** - * Symbol request supports dynamic registration. - */ - DynamicRegistration bool `json:"dynamicRegistration,omitempty"` - /** - * Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. - */ - SymbolKind struct { - /** - * The symbol kind values the client supports. When this - * property exists the client also guarantees that it will - * handle values outside its set gracefully and falls back - * to a default value when unknown. - * - * If this property is not present the client only supports - * the symbol kinds from `File` to `Array` as defined in - * the initial version of the protocol. - */ - ValueSet []SymbolKind `json:"valueSet,omitempty"` - } `json:"symbolKind,omitempty"` - /** - * The client supports tags on `SymbolInformation`. - * Clients supporting tags have to handle unknown tags gracefully. - * - * @since 3.16.0 - */ - TagSupport struct { - /** - * The tags supported by the client. - */ - ValueSet []SymbolTag `json:"valueSet"` - } `json:"tagSupport,omitempty"` -} - -/** - * Server capabilities for a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). - */ -type WorkspaceSymbolOptions struct { - WorkDoneProgressOptions -} - -/** - * The parameters of a [WorkspaceSymbolRequest](#WorkspaceSymbolRequest). - */ -type WorkspaceSymbolParams struct { - /** - * A query string to filter symbols by. Clients may send an empty - * string here to request all symbols. - */ - Query string `json:"query"` - WorkDoneProgressParams - PartialResultParams -} - -/** - * An unchanged document diagnostic report for a workspace diagnostic result. - * - * @since 3.17.0 - proposed state - */ -type WorkspaceUnchangedDocumentDiagnosticReport struct { - /** - * The URI for which diagnostic information is reported. - */ - URI DocumentURI `json:"uri"` - /** - * The version number for which the diagnostics are reported. - * If the document is not marked as open `null` can be provided. - */ - Version int32/*integer | null*/ `json:"version"` - UnchangedDocumentDiagnosticReport -} - -const ( - /** - * Empty kind. - */ - - Empty CodeActionKind = "" - /** - * Base kind for quickfix actions: 'quickfix' - */ - - QuickFix CodeActionKind = "quickfix" - /** - * Base kind for refactoring actions: 'refactor' - */ - - Refactor CodeActionKind = "refactor" - /** - * Base kind for refactoring extraction actions: 'refactor.extract' - * - * Example extract actions: - * - * - Extract method - * - Extract function - * - Extract variable - * - Extract interface from class - * - ... - */ - - RefactorExtract CodeActionKind = "refactor.extract" - /** - * Base kind for refactoring inline actions: 'refactor.inline' - * - * Example inline actions: - * - * - Inline function - * - Inline variable - * - Inline constant - * - ... - */ - - RefactorInline CodeActionKind = "refactor.inline" - /** - * Base kind for refactoring rewrite actions: 'refactor.rewrite' - * - * Example rewrite actions: - * - * - Convert JavaScript function to class - * - Add or remove parameter - * - Encapsulate field - * - Make method static - * - Move method to base class - * - ... - */ - - RefactorRewrite CodeActionKind = "refactor.rewrite" - /** - * Base kind for source actions: `source` - * - * Source code actions apply to the entire file. - */ - - Source CodeActionKind = "source" - /** - * Base kind for an organize imports source action: `source.organizeImports` - */ - - SourceOrganizeImports CodeActionKind = "source.organizeImports" - /** - * Base kind for auto-fix source actions: `source.fixAll`. - * - * Fix all actions automatically fix errors that have a clear fix that do not require user input. - * They should not suppress errors or perform unsafe fixes such as generating new types or classes. - * - * @since 3.15.0 - */ - - SourceFixAll CodeActionKind = "source.fixAll" - TextCompletion CompletionItemKind = 1 - MethodCompletion CompletionItemKind = 2 - FunctionCompletion CompletionItemKind = 3 - ConstructorCompletion CompletionItemKind = 4 - FieldCompletion CompletionItemKind = 5 - VariableCompletion CompletionItemKind = 6 - ClassCompletion CompletionItemKind = 7 - InterfaceCompletion CompletionItemKind = 8 - ModuleCompletion CompletionItemKind = 9 - PropertyCompletion CompletionItemKind = 10 - UnitCompletion CompletionItemKind = 11 - ValueCompletion CompletionItemKind = 12 - EnumCompletion CompletionItemKind = 13 - KeywordCompletion CompletionItemKind = 14 - SnippetCompletion CompletionItemKind = 15 - ColorCompletion CompletionItemKind = 16 - FileCompletion CompletionItemKind = 17 - ReferenceCompletion CompletionItemKind = 18 - FolderCompletion CompletionItemKind = 19 - EnumMemberCompletion CompletionItemKind = 20 - ConstantCompletion CompletionItemKind = 21 - StructCompletion CompletionItemKind = 22 - EventCompletion CompletionItemKind = 23 - OperatorCompletion CompletionItemKind = 24 - TypeParameterCompletion CompletionItemKind = 25 - /** - * Render a completion as obsolete, usually using a strike-out. - */ - - ComplDeprecated CompletionItemTag = 1 - /** - * Completion was triggered by typing an identifier (24x7 code - * complete), manual invocation (e.g Ctrl+Space) or via API. - */ - - Invoked CompletionTriggerKind = 1 - /** - * Completion was triggered by a trigger character specified by - * the `triggerCharacters` properties of the `CompletionRegistrationOptions`. - */ - - TriggerCharacter CompletionTriggerKind = 2 - /** - * Completion was re-triggered as current completion list is incomplete - */ - - TriggerForIncompleteCompletions CompletionTriggerKind = 3 - /** - * Reports an error. - */ - - SeverityError DiagnosticSeverity = 1 - /** - * Reports a warning. - */ - - SeverityWarning DiagnosticSeverity = 2 - /** - * Reports an information. - */ - - SeverityInformation DiagnosticSeverity = 3 - /** - * Reports a hint. - */ - - SeverityHint DiagnosticSeverity = 4 - /** - * Unused or unnecessary code. - * - * Clients are allowed to render diagnostics with this tag faded out instead of having - * an error squiggle. - */ - - Unnecessary DiagnosticTag = 1 - /** - * Deprecated or obsolete code. - * - * Clients are allowed to rendered diagnostics with this tag strike through. - */ - - Deprecated DiagnosticTag = 2 - /** - * A textual occurrence. - */ - - Text DocumentHighlightKind = 1 - /** - * Read-access of a symbol, like reading a variable. - */ - - Read DocumentHighlightKind = 2 - /** - * Write-access of a symbol, like writing to a variable. - */ - - Write DocumentHighlightKind = 3 - /** - * Applying the workspace change is simply aborted if one of the changes provided - * fails. All operations executed before the failing operation stay executed. - */ - - Abort FailureHandlingKind = "abort" - /** - * All operations are executed transactional. That means they either all - * succeed or no changes at all are applied to the workspace. - */ - - Transactional FailureHandlingKind = "transactional" - /** - * If the workspace edit contains only textual file changes they are executed transactional. - * If resource changes (create, rename or delete file) are part of the change the failure - * handling strategy is abort. - */ - - TextOnlyTransactional FailureHandlingKind = "textOnlyTransactional" - /** - * The client tries to undo the operations already executed. But there is no - * guarantee that this is succeeding. - */ - - Undo FailureHandlingKind = "undo" - /** - * The file got created. - */ - - Created FileChangeType = 1 - /** - * The file got changed. - */ - - Changed FileChangeType = 2 - /** - * The file got deleted. - */ - - Deleted FileChangeType = 3 - /** - * The pattern matches a file only. - */ - - FileOp FileOperationPatternKind = "file" - /** - * The pattern matches a folder only. - */ - - FolderOp FileOperationPatternKind = "folder" - /** - * Folding range for a comment - */ - Comment FoldingRangeKind = "comment" - /** - * Folding range for a imports or includes - */ - Imports FoldingRangeKind = "imports" - /** - * Folding range for a region (e.g. `#region`) - */ - Region FoldingRangeKind = "region" - /** - * If the protocol version provided by the client can't be handled by the server. - * @deprecated This initialize error got replaced by client capabilities. There is - * no version handshake in version 3.0x - */ - - UnknownProtocolVersion InitializeError = 1 - /** - * The primary text to be inserted is treated as a plain string. - */ - - PlainTextTextFormat InsertTextFormat = 1 - /** - * The primary text to be inserted is treated as a snippet. - * - * A snippet can define tab stops and placeholders with `$1`, `$2` - * and `${3:foo}`. `$0` defines the final tab stop, it defaults to - * the end of the snippet. Placeholders with equal identifiers are linked, - * that is typing in one will update others too. - * - * See also: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax - */ - - SnippetTextFormat InsertTextFormat = 2 - /** - * The insertion or replace strings is taken as it is. If the - * value is multi line the lines below the cursor will be - * inserted using the indentation defined in the string value. - * The client will not apply any kind of adjustments to the - * string. - */ - - AsIs InsertTextMode = 1 - /** - * The editor adjusts leading whitespace of new lines so that - * they match the indentation up to the cursor of the line for - * which the item is accepted. - * - * Consider a line like this: <2tabs><3tabs>foo. Accepting a - * multi line completion item is indented using 2 tabs and all - * following lines inserted will be indented using 2 tabs as well. - */ - - AdjustIndentation InsertTextMode = 2 - /** - * Plain text is supported as a content format - */ - - PlainText MarkupKind = "plaintext" - /** - * Markdown is supported as a content format - */ - - Markdown MarkupKind = "markdown" - /** - * An error message. - */ - - Error MessageType = 1 - /** - * A warning message. - */ - - Warning MessageType = 2 - /** - * An information message. - */ - - Info MessageType = 3 - /** - * A log message. - */ - - Log MessageType = 4 - /** - * The moniker represent a symbol that is imported into a project - */ - Import MonikerKind = "import" - /** - * The moniker represents a symbol that is exported from a project - */ - Export MonikerKind = "export" - /** - * The moniker represents a symbol that is local to a project (e.g. a local - * variable of a function, a class not visible outside the project, ...) - */ - Local MonikerKind = "local" - /** - * Supports creating new files and folders. - */ - - Create ResourceOperationKind = "create" - /** - * Supports renaming existing files and folders. - */ - - Rename ResourceOperationKind = "rename" - /** - * Supports deleting existing files and folders. - */ - - Delete ResourceOperationKind = "delete" - /** - * Signature help was invoked manually by the user or by a command. - */ - - SigInvoked SignatureHelpTriggerKind = 1 - /** - * Signature help was triggered by a trigger character. - */ - - SigTriggerCharacter SignatureHelpTriggerKind = 2 - /** - * Signature help was triggered by the cursor moving or by the document content changing. - */ - - SigContentChange SignatureHelpTriggerKind = 3 - File SymbolKind = 1 - Module SymbolKind = 2 - Namespace SymbolKind = 3 - Package SymbolKind = 4 - Class SymbolKind = 5 - Method SymbolKind = 6 - Property SymbolKind = 7 - Field SymbolKind = 8 - Constructor SymbolKind = 9 - Enum SymbolKind = 10 - Interface SymbolKind = 11 - Function SymbolKind = 12 - Variable SymbolKind = 13 - Constant SymbolKind = 14 - String SymbolKind = 15 - Number SymbolKind = 16 - Boolean SymbolKind = 17 - Array SymbolKind = 18 - Object SymbolKind = 19 - Key SymbolKind = 20 - Null SymbolKind = 21 - EnumMember SymbolKind = 22 - Struct SymbolKind = 23 - Event SymbolKind = 24 - Operator SymbolKind = 25 - TypeParameter SymbolKind = 26 - /** - * Render a symbol as obsolete, usually using a strike-out. - */ - - DeprecatedSymbol SymbolTag = 1 - /** - * Manually triggered, e.g. by the user pressing save, by starting debugging, - * or by an API call. - */ - - Manual TextDocumentSaveReason = 1 - /** - * Automatic after a delay. - */ - - AfterDelay TextDocumentSaveReason = 2 - /** - * When the editor lost focus. - */ - - FocusOut TextDocumentSaveReason = 3 - /** - * Documents should not be synced at all. - */ - - None TextDocumentSyncKind = 0 - /** - * Documents are synced by always sending the full content - * of the document. - */ - - Full TextDocumentSyncKind = 1 - /** - * Documents are synced by sending the full content on open. - * After that only incremental updates to the document are - * send. - */ - - Incremental TextDocumentSyncKind = 2 - /** - * The moniker is only unique inside a document - */ - Document UniquenessLevel = "document" - /** - * The moniker is unique inside a project for which a dump got created - */ - Project UniquenessLevel = "project" - /** - * The moniker is unique inside the group to which a project belongs - */ - Group UniquenessLevel = "group" - /** - * The moniker is unique inside the moniker scheme. - */ - Scheme UniquenessLevel = "scheme" - /** - * The moniker is globally unique - */ - Global UniquenessLevel = "global" - /** - * Interested in create events. - */ - - WatchCreate WatchKind = 1 - /** - * Interested in change events - */ - - WatchChange WatchKind = 2 - /** - * Interested in delete events - */ - - WatchDelete WatchKind = 4 -) - -// Types created to name formal parameters and embedded structs -type ParamConfiguration struct { - ConfigurationParams - PartialResultParams -} -type ParamInitialize struct { - InitializeParams - WorkDoneProgressParams -} -type Workspace2Gn struct { - /** - * The client supports applying batch edits - * to the workspace by supporting the request - * 'workspace/applyEdit' - */ - ApplyEdit bool `json:"applyEdit,omitempty"` - - /** - * Capabilities specific to `WorkspaceEdit`s - */ - WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeConfiguration` notification. - */ - DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. - */ - DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` - - /** - * Capabilities specific to the `workspace/symbol` request. - */ - Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` - - /** - * Capabilities specific to the `workspace/executeCommand` request. - */ - ExecuteCommand ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` - - /** - * Capabilities specific to the semantic token requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - SemanticTokens SemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitempty"` - - /** - * Capabilities specific to the code lens requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - CodeLens CodeLensWorkspaceClientCapabilities `json:"codeLens,omitempty"` - - /** - * The client has support for file notifications/requests for user operations on files. - * - * Since 3.16.0 - */ - FileOperations *FileOperationClientCapabilities `json:"fileOperations,omitempty"` - - /** - * The client has support for workspace folders - * - * @since 3.6.0 - */ - WorkspaceFolders bool `json:"workspaceFolders,omitempty"` - - /** - * The client supports `workspace/configuration` requests. - * - * @since 3.6.0 - */ - Configuration bool `json:"configuration,omitempty"` -} -type Workspace3Gn struct { - /** - * The client supports applying batch edits - * to the workspace by supporting the request - * 'workspace/applyEdit' - */ - ApplyEdit bool `json:"applyEdit,omitempty"` - - /** - * Capabilities specific to `WorkspaceEdit`s - */ - WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeConfiguration` notification. - */ - DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. - */ - DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` - - /** - * Capabilities specific to the `workspace/symbol` request. - */ - Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` - - /** - * Capabilities specific to the `workspace/executeCommand` request. - */ - ExecuteCommand ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` - - /** - * Capabilities specific to the semantic token requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - SemanticTokens SemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitempty"` - - /** - * Capabilities specific to the code lens requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - CodeLens CodeLensWorkspaceClientCapabilities `json:"codeLens,omitempty"` - - /** - * The client has support for file notifications/requests for user operations on files. - * - * Since 3.16.0 - */ - FileOperations *FileOperationClientCapabilities `json:"fileOperations,omitempty"` - - /** - * The client has support for workspace folders - * - * @since 3.6.0 - */ - WorkspaceFolders bool `json:"workspaceFolders,omitempty"` - - /** - * The client supports `workspace/configuration` requests. - * - * @since 3.6.0 - */ - Configuration bool `json:"configuration,omitempty"` -} -type WorkspaceFolders4Gn struct { - /** - * The Server has support for workspace folders - */ - Supported bool `json:"supported,omitempty"` - - /** - * Whether the server wants to receive workspace folder - * change notifications. - * - * If a strings is provided the string is treated as a ID - * under which the notification is registered on the client - * side. The ID can be used to unregister for these events - * using the `client/unregisterCapability` request. - */ - ChangeNotifications string/*string | boolean*/ `json:"changeNotifications,omitempty"` -} -type Workspace5Gn struct { - /** - * The server is interested in notifications/requests for operations on files. - * - * @since 3.16.0 - */ - FileOperations *FileOperationOptions `json:"fileOperations,omitempty"` - - WorkspaceFolders WorkspaceFolders4Gn `json:"workspaceFolders,omitempty"` -} -type Workspace6Gn struct { - /** - * The client supports applying batch edits - * to the workspace by supporting the request - * 'workspace/applyEdit' - */ - ApplyEdit bool `json:"applyEdit,omitempty"` - - /** - * Capabilities specific to `WorkspaceEdit`s - */ - WorkspaceEdit *WorkspaceEditClientCapabilities `json:"workspaceEdit,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeConfiguration` notification. - */ - DidChangeConfiguration DidChangeConfigurationClientCapabilities `json:"didChangeConfiguration,omitempty"` - - /** - * Capabilities specific to the `workspace/didChangeWatchedFiles` notification. - */ - DidChangeWatchedFiles DidChangeWatchedFilesClientCapabilities `json:"didChangeWatchedFiles,omitempty"` - - /** - * Capabilities specific to the `workspace/symbol` request. - */ - Symbol *WorkspaceSymbolClientCapabilities `json:"symbol,omitempty"` - - /** - * Capabilities specific to the `workspace/executeCommand` request. - */ - ExecuteCommand ExecuteCommandClientCapabilities `json:"executeCommand,omitempty"` - - /** - * Capabilities specific to the semantic token requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - SemanticTokens SemanticTokensWorkspaceClientCapabilities `json:"semanticTokens,omitempty"` - - /** - * Capabilities specific to the code lens requests scoped to the - * workspace. - * - * @since 3.16.0. - */ - CodeLens CodeLensWorkspaceClientCapabilities `json:"codeLens,omitempty"` - - /** - * The client has support for file notifications/requests for user operations on files. - * - * Since 3.16.0 - */ - FileOperations *FileOperationClientCapabilities `json:"fileOperations,omitempty"` - - /** - * The client has support for workspace folders - * - * @since 3.6.0 - */ - WorkspaceFolders bool `json:"workspaceFolders,omitempty"` - - /** - * The client supports `workspace/configuration` requests. - * - * @since 3.6.0 - */ - Configuration bool `json:"configuration,omitempty"` -} -type WorkspaceFolders7Gn struct { - /** - * The Server has support for workspace folders - */ - Supported bool `json:"supported,omitempty"` - - /** - * Whether the server wants to receive workspace folder - * change notifications. - * - * If a strings is provided the string is treated as a ID - * under which the notification is registered on the client - * side. The ID can be used to unregister for these events - * using the `client/unregisterCapability` request. - */ - ChangeNotifications string/*string | boolean*/ `json:"changeNotifications,omitempty"` -} -type Workspace8Gn struct { - /** - * The server is interested in notifications/requests for operations on files. - * - * @since 3.16.0 - */ - FileOperations *FileOperationOptions `json:"fileOperations,omitempty"` - - WorkspaceFolders WorkspaceFolders7Gn `json:"workspaceFolders,omitempty"` -} \ No newline at end of file diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go deleted file mode 100644 index 457ceb4..0000000 --- a/internal/lsp/handlers.go +++ /dev/null @@ -1,246 +0,0 @@ -package lsp - -import ( - "encoding/json" - "fmt" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" - - "github.com/sourcegraph/jsonrpc2" -) - -type InMemoryDocument struct { - Text string - CheckResult analysis.CheckResult -} - -type State struct { - documents map[DocumentURI]InMemoryDocument -} - -func (state *State) updateDocument(uri DocumentURI, text string) { - checkResult := analysis.CheckSource(text) - - state.documents[uri] = InMemoryDocument{ - Text: text, - CheckResult: checkResult, - } - - var diagnostics []Diagnostic = make([]Diagnostic, 0) - for _, diagnostic := range checkResult.Diagnostics { - diagnostics = append(diagnostics, toLspDiagnostic(diagnostic)) - } - - SendNotification("textDocument/publishDiagnostics", PublishDiagnosticsParams{ - URI: uri, - Diagnostics: diagnostics, - }) -} - -func InitialState() State { - return State{ - documents: make(map[DocumentURI]InMemoryDocument), - } -} - -func (state *State) handleHover(params HoverParams) *Hover { - position := fromLspPosition(params.Position) - - doc, ok := state.documents[params.TextDocument.URI] - if !ok { - return nil - } - - hoverable := analysis.HoverOn(doc.CheckResult.Program, position) - - switch hoverable := hoverable.(type) { - case *analysis.VariableHover: - - varLit := hoverable.Node - resolution := doc.CheckResult.ResolveVar(varLit) - - if resolution == nil { - return nil - } - - msg := fmt.Sprintf("```numscript\n$%s: %s\n```", varLit.Name, resolution.Type.Name) - - return &Hover{ - Contents: MarkupContent{ - Value: msg, - Kind: "markdown", - }, - Range: toLspRange(hoverable.Range), - } - case *analysis.BuiltinFnHover: - resolved := doc.CheckResult.ResolveBuiltinFn(hoverable.Node.Caller) - if resolved == nil { - return nil - } - - var msg string - switch resolved := resolved.(type) { - case analysis.StatementFnCallResolution: - params := "(" - for index, arg := range resolved.Params { - if index != 0 { - params += ", " - } - params += arg - } - params += ")" - msg = fmt.Sprintf("`%s%s`\n\n%s", hoverable.Node.Caller.Name, params, resolved.Docs) - case analysis.VarOriginFnCallResolution: - params := "(" - for index, arg := range resolved.Params { - if index != 0 { - params += ", " - } - params += arg - } - params += ")" - - msg = fmt.Sprintf("`%s%s -> %s`\n\n%s", hoverable.Node.Caller.Name, params, resolved.Return, resolved.Docs) - default: - utils.NonExhaustiveMatchPanic[any](resolved) - } - - return &Hover{ - Contents: MarkupContent{ - Value: msg, - Kind: "markdown", - }, - Range: toLspRange(hoverable.Range), - } - - default: - return nil - } -} - -func (state *State) handleGotoDefinition(params DefinitionParams) *Location { - doc, ok := state.documents[params.TextDocument.URI] - if !ok { - return nil - } - - position := fromLspPosition(params.Position) - res := analysis.GotoDefinition(doc.CheckResult.Program, position, doc.CheckResult) - if res == nil { - return nil - } - - return &Location{ - Range: toLspRange(res.Range), - URI: params.TextDocument.URI, - } -} - -func (state *State) handleGetSymbols(params DocumentSymbolParams) []DocumentSymbol { - doc, ok := state.documents[params.TextDocument.URI] - if !ok { - return nil - } - - var lspDocumentSymbols []DocumentSymbol - for _, sym := range doc.CheckResult.GetSymbols() { - lspDocumentSymbols = append(lspDocumentSymbols, DocumentSymbol{ - Name: sym.Name, - Detail: sym.Detail, - Kind: SymbolKind(sym.Kind), - Range: toLspRange(sym.Range), - SelectionRange: toLspRange(sym.SelectionRange), - }) - } - - return lspDocumentSymbols -} - -func Handle(r jsonrpc2.Request, state *State) any { - switch r.Method { - case "initialize": - return InitializeResult{ - Capabilities: ServerCapabilities{ - TextDocumentSync: TextDocumentSyncOptions{ - OpenClose: true, - Change: Full, - }, - HoverProvider: true, - DefinitionProvider: true, - DocumentSymbolProvider: true, - }, - // This is ugly. Is there a shortcut? - ServerInfo: struct { - Name string "json:\"name\"" - Version string "json:\"version,omitempty\"" - }{ - Name: "numscript-ls", - Version: "0.0.1", - }, - } - - case "textDocument/didOpen": - var p DidOpenTextDocumentParams - json.Unmarshal([]byte(*r.Params), &p) - state.updateDocument(p.TextDocument.URI, p.TextDocument.Text) - return nil - - case "textDocument/didChange": - var p DidChangeTextDocumentParams - json.Unmarshal([]byte(*r.Params), &p) - text := p.ContentChanges[len(p.ContentChanges)-1].Text - state.updateDocument(p.TextDocument.URI, text) - return nil - - case "textDocument/hover": - var p HoverParams - json.Unmarshal([]byte(*r.Params), &p) - return state.handleHover(p) - - case "textDocument/definition": - var p DefinitionParams - json.Unmarshal([]byte(*r.Params), &p) - return state.handleGotoDefinition(p) - - case "textDocument/documentSymbol": - var p DocumentSymbolParams - json.Unmarshal([]byte(*r.Params), &p) - return state.handleGetSymbols(p) - - default: - // Unhandled method - // TODO should it panic? - return nil - } -} - -func fromLspPosition(p Position) parser.Position { - return parser.Position{ - Line: int(p.Line), - Character: int(p.Character), - } -} - -func toLspPosition(p parser.Position) Position { - return Position{ - Line: uint32(p.Line), - Character: uint32(p.Character), - } -} - -func toLspRange(p parser.Range) Range { - return Range{ - Start: toLspPosition(p.Start), - End: toLspPosition(p.End), - } -} - -func toLspDiagnostic(d analysis.Diagnostic) Diagnostic { - return Diagnostic{ - Range: toLspRange(d.Range), - Severity: DiagnosticSeverity(d.Kind.Severity()), - Message: d.Kind.Message(), - } -} diff --git a/internal/lsp/server.go b/internal/lsp/server.go deleted file mode 100644 index 20c98e0..0000000 --- a/internal/lsp/server.go +++ /dev/null @@ -1,111 +0,0 @@ -package lsp - -import ( - "bufio" - "encoding/json" - "fmt" - "io" - "net/textproto" - "os" - "strconv" - - "github.com/sourcegraph/jsonrpc2" -) - -type ServerArgs[State any] struct { - InitialState State - Handler func(r jsonrpc2.Request, state *State) any -} - -func SendNotification(method string, params interface{}) { - bytes, err := json.Marshal(params) - if err != nil { - panic(err) - } - rawParams := json.RawMessage(bytes) - encoded := encodeMessage(jsonrpc2.Request{ - Notif: true, - Method: method, - Params: &rawParams, - }) - os.Stderr.Write([]byte(encoded)) - _, err = fmt.Print(encoded) - if err != nil { - panic(err) - } -} - -func RunServer[State any](args ServerArgs[State]) { - buf := NewMessageBuffer(os.Stdin) - - for { - request := buf.Read() - - bytes, err := json.Marshal(args.Handler(request, &args.InitialState)) - if err != nil { - panic(err) - } - - rawMsg := json.RawMessage(bytes) - encoded := encodeMessage(jsonrpc2.Response{ - ID: request.ID, - Result: &rawMsg, - }) - _, err = fmt.Print(encoded) - if err != nil { - panic(err) - } - } -} - -type MessageBuffer struct{ reader *bufio.Reader } - -func NewMessageBuffer(r io.Reader) MessageBuffer { - return MessageBuffer{ - reader: bufio.NewReader(r), - } -} - -func (mb *MessageBuffer) Read() jsonrpc2.Request { - tpr := textproto.NewReader(mb.reader) - - headers, err := tpr.ReadMIMEHeader() - if err != nil { - if err.Error() == "EOF" { - os.Exit(0) - } - panic(err) - } - - contentLenHeader := headers.Get("Content-Length") - len, err := strconv.ParseInt(contentLenHeader, 10, 0) - if err != nil { - panic(err) - } - - bytes := make([]byte, len) - readBytes, readErr := io.ReadFull(tpr.R, bytes) - if readErr != nil { - panic(readErr) - } - if readBytes != int(len) { - panic(fmt.Sprint("Missing bytes to read. Read: ", readBytes, ", total: ", len)) - } - - var req jsonrpc2.Request - err1 := req.UnmarshalJSON(bytes) - if err1 != nil { - panic(err1) - } - - return req -} - -func encodeMessage(msg any) string { - bytes, err := json.Marshal(msg) - if err != nil { - panic(err) - } - - return fmt.Sprintf("Content-Length: %d\r\n\r\n%s", len(bytes), bytes) -} diff --git a/internal/lsp/server_test.go b/internal/lsp/server_test.go deleted file mode 100644 index 1516d35..0000000 --- a/internal/lsp/server_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package lsp_test - -import ( - "fmt" - "strings" - "testing" - - lsp "github.com/PagoPlus/numscript-wasm/internal/lsp" -) - -func encodePayload(payload string) *strings.Reader { - s := fmt.Sprint(`Content-Length: `, len(payload), "\r\n\r\n", payload) - return strings.NewReader(s) -} - -const mockPayload = `{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":19864,"clientInfo":{"name":"Visual Studio Code","version":"1.90.2"},"locale":"en","rootPath":"/Users/alessandro/Desktop/example","rootUri":"file:///Users/alessandro/Desktop/example","capabilities":{"workspace":{"applyEdit":true,"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"],"failureHandling":"textOnlyTransactional","normalizesLineEndings":true,"changeAnnotationSupport":{"groupsOnLabel":true}},"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true},"symbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"tagSupport":{"valueSet":[1]},"resolveSupport":{"properties":["location.range"]}},"codeLens":{"refreshSupport":true},"executeCommand":{"dynamicRegistration":true},"didChangeConfiguration":{"dynamicRegistration":true},"workspaceFolders":true,"semanticTokens":{"refreshSupport":true},"fileOperations":{"dynamicRegistration":true,"didCreate":true,"didRename":true,"didDelete":true,"willCreate":true,"willRename":true,"willDelete":true},"inlineValue":{"refreshSupport":true},"inlayHint":{"refreshSupport":true},"diagnostics":{"refreshSupport":true}},"textDocument":{"publishDiagnostics":{"relatedInformation":true,"versionSupport":false,"tagSupport":{"valueSet":[1,2]},"codeDescriptionSupport":true,"dataSupport":true},"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"contextSupport":true,"completionItem":{"snippetSupport":true,"commitCharactersSupport":true,"documentationFormat":["markdown","plaintext"],"deprecatedSupport":true,"preselectSupport":true,"tagSupport":{"valueSet":[1]},"insertReplaceSupport":true,"resolveSupport":{"properties":["documentation","detail","additionalTextEdits"]},"insertTextModeSupport":{"valueSet":[1,2]},"labelDetailsSupport":true},"insertTextMode":2,"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},"completionList":{"itemDefaults":["commitCharacters","editRange","insertTextFormat","insertTextMode"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"signatureHelp":{"dynamicRegistration":true,"signatureInformation":{"documentationFormat":["markdown","plaintext"],"parameterInformation":{"labelOffsetSupport":true},"activeParameterSupport":true},"contextSupport":true},"definition":{"dynamicRegistration":true,"linkSupport":true},"references":{"dynamicRegistration":true},"documentHighlight":{"dynamicRegistration":true},"documentSymbol":{"dynamicRegistration":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true,"tagSupport":{"valueSet":[1]},"labelSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"disabledSupport":true,"dataSupport":true,"resolveSupport":{"properties":["edit"]},"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"honorsChangeAnnotations":false},"codeLens":{"dynamicRegistration":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"onTypeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true,"prepareSupportDefaultBehavior":1,"honorsChangeAnnotations":true},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"typeDefinition":{"dynamicRegistration":true,"linkSupport":true},"implementation":{"dynamicRegistration":true,"linkSupport":true},"colorProvider":{"dynamicRegistration":true},"foldingRange":{"dynamicRegistration":true,"rangeLimit":5000,"lineFoldingOnly":true,"foldingRangeKind":{"valueSet":["comment","imports","region"]},"foldingRange":{"collapsedText":false}},"declaration":{"dynamicRegistration":true,"linkSupport":true},"selectionRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":true},"semanticTokens":{"dynamicRegistration":true,"tokenTypes":["namespace","type","class","enum","interface","struct","typeParameter","parameter","variable","property","enumMember","event","function","method","macro","keyword","modifier","comment","string","number","regexp","operator","decorator"],"tokenModifiers":["declaration","definition","readonly","static","deprecated","abstract","async","modification","documentation","defaultLibrary"],"formats":["relative"],"requests":{"range":true,"full":{"delta":true}},"multilineTokenSupport":false,"overlappingTokenSupport":false,"serverCancelSupport":true,"augmentsSyntaxTokens":true},"linkedEditingRange":{"dynamicRegistration":true},"typeHierarchy":{"dynamicRegistration":true},"inlineValue":{"dynamicRegistration":true},"inlayHint":{"dynamicRegistration":true,"resolveSupport":{"properties":["tooltip","textEdits","label.tooltip","label.location","label.command"]}},"diagnostic":{"dynamicRegistration":true,"relatedDocumentSupport":false}},"window":{"showMessage":{"messageActionItem":{"additionalPropertiesSupport":true}},"showDocument":{"support":true},"workDoneProgress":true},"general":{"staleRequestSupport":{"cancel":true,"retryOnContentModified":["textDocument/semanticTokens/full","textDocument/semanticTokens/range","textDocument/semanticTokens/full/delta"]},"regularExpressions":{"engine":"ECMAScript","version":"ES2020"},"markdown":{"parser":"marked","version":"1.1.0"},"positionEncodings":["utf-16"]},"notebookDocument":{"synchronization":{"dynamicRegistration":true,"executionSummarySupport":true}}},"trace":"off","workspaceFolders":[{"uri":"file:///Users/alessandro/Desktop/example","name":"example"}]}}` - -func TestBuf(t *testing.T) { - t.Parallel() - - buf := lsp.NewMessageBuffer(encodePayload(mockPayload)) - - got := buf.Read() - - if got.Method != "initialize" { - t.Errorf("expected: %s, got: %s", "initialize", got.Method) - } -} diff --git a/internal/numscript/numscript.go b/internal/numscript/numscript.go deleted file mode 100644 index 2accfc1..0000000 --- a/internal/numscript/numscript.go +++ /dev/null @@ -1,203 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "sort" - - "github.com/Jeffail/gabs/v2" - "github.com/spf13/cobra" - - "github.com/PagoPlus/numscript-wasm/internal/analysis" - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/PagoPlus/numscript-wasm/internal/utils" -) - -type RunInputOpts struct { - Script string `json:"script"` - Variables map[string]string `json:"variables"` - Meta interpreter.AccountsMetadata `json:"metadata"` - Balances interpreter.Balances `json:"balances"` -} - -var Version string - -func version() string { - if Version == "" { - return "dev" - } else { - return Version - } -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Shows the app version", - Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { - fmt.Print(version()) - }, -} - -func SeverityToString(s analysis.Severity) string { - switch s { - case analysis.ErrorSeverity: - return "error" - case analysis.WarningSeverity: - return "warning" - case analysis.Information: - return "info" - case analysis.Hint: - return "hint" - default: - return utils.NonExhaustiveMatchPanic[string](s) - } -} - -func check() { - dat, err := io.ReadAll(os.Stdin) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - os.Exit(1) - } - - res := analysis.CheckSource(string(dat)) - sort.Slice(res.Diagnostics, func(i, j int) bool { - p1 := res.Diagnostics[i].Range.Start - p2 := res.Diagnostics[j].Range.Start - - return p2.GtEq(p1) - }) - - hasErrors := false - jsonObj := gabs.New() - for _, d := range res.Diagnostics { - if d.Kind.Severity() == analysis.ErrorSeverity { - hasErrors = true - } - - logLevel := SeverityToString(d.Kind.Severity()) - - buildCheckDetails(d, jsonObj, logLevel) - } - - if hasErrors { - jsonObj.Set(false, "valid") - } else { - jsonObj.Set(true, "valid") - } - - fmt.Println(jsonObj.String()) -} - -func buildCheckDetails(diagnostic analysis.Diagnostic, jsonObj *gabs.Container, logLevel string) { - logLevelKey := logLevel + "s" - subJsonObj := gabs.New() - - subJsonObj.Set(diagnostic.Range.Start.Line, "line") - subJsonObj.Set(diagnostic.Range.Start.Character, "character") - subJsonObj.Set(logLevel, "level") - subJsonObj.Set(diagnostic.Kind.Message(), logLevel) - - jsonObj.ArrayAppend(subJsonObj, logLevelKey) -} - -var checkCmd = &cobra.Command{ - Use: "check", - Short: "Check a numscript file", - Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { - check() - }, -} - -func run() { - opt := RunInputOpts{ - Variables: make(map[string]string), - Meta: make(interpreter.AccountsMetadata), - Balances: make(interpreter.Balances), - } - - bytes, err := io.ReadAll(os.Stdin) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - os.Exit(1) - } - - err = json.Unmarshal(bytes, &opt) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - os.Exit(1) - } - - parseResult := parser.Parse(opt.Script) - if len(parseResult.Errors) != 0 { - os.Stderr.Write([]byte(parser.ParseErrorsToString(parseResult.Errors, opt.Script))) - os.Exit(1) - } - - featureFlags := make(map[string]struct{}) - result, err := interpreter.RunProgram( - context.Background(), - parseResult.Value, - opt.Variables, - interpreter.StaticStore{ - Balances: opt.Balances, - Meta: opt.Meta, - }, - featureFlags, - ) - - if err != nil { - os.Stderr.Write([]byte(err.Error())) - os.Exit(1) - } - - out, err := json.Marshal(result) - if err != nil { - os.Stderr.Write([]byte(err.Error())) - os.Exit(1) - } - - os.Stdout.Write(out) -} - -var runCmd = &cobra.Command{ - Use: "run", - Short: "Evaluate a numscript file", - Long: "Evaluate a numscript file, using the balances, the current metadata and the variables values as input.", - Run: func(cmd *cobra.Command, args []string) { - run() - }, -} - -var rootCmd = &cobra.Command{ - Use: "numscript", - Short: "Numscript cli", - Long: "Numscript cli", - Version: version(), - CompletionOptions: cobra.CompletionOptions{ - DisableDefaultCmd: true, - }, -} - -func main() { - defer func() { - if err := recover(); err != nil { - fmt.Fprintf(os.Stderr, "Exception: %v\n", err) - os.Exit(1) - } - }() - - rootCmd.SetVersionTemplate(rootCmd.Version) - - rootCmd.AddCommand(checkCmd) - rootCmd.AddCommand(runCmd) - rootCmd.AddCommand(versionCmd) - - rootCmd.Execute() -} diff --git a/internal/parser/__snapshots__/parser_fault_tolerance_test.snap b/internal/parser/__snapshots__/parser_fault_tolerance_test.snap deleted file mode 100755 index cbe089e..0000000 --- a/internal/parser/__snapshots__/parser_fault_tolerance_test.snap +++ /dev/null @@ -1,430 +0,0 @@ - -[TestFaultToleranceVarName - 1] -parser.Program{ - Vars: { - { - Range: parser.Range{ - Start: parser.Position{Character:7, Line:0}, - End: parser.Position{Character:18, Line:0}, - }, - Name: (*parser.Variable)(nil), - Type: &parser.TypeDecl{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Name: "monetary", - }, - Origin: (*parser.FnCall)(nil), - }, - }, - Statements: nil, -} ---- - -[TestFaultToleranceSend - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:4, Line:0}, - }, - SentValue: nil, - Source: nil, - Destination: nil, - }, - }, -} ---- - -[TestFaultToleranceMonetary - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:11, Line:0}, - }, - SentValue: nil, - Source: nil, - Destination: nil, - }, - }, -} ---- - -[TestFaultToleranceNoAddr - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:5}, - }, - SentValue: nil, - Source: &parser.SourceInorder{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:3, Line:3}, - }, - Sources: nil, - }, - Destination: nil, - }, - }, -} ---- - -[TestFaultToleranceInvalidDest - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:10, Line:0}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Number: 10, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Name: "a", - }, - }, - Destination: nil, - }, - }, -} ---- - -[TestFaultToleranceInvalidSrcTk - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:10, Line:0}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Number: 10, - }, - }, - }, - Source: &parser.SourceCapped{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - From: nil, - Cap: nil, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:20, Line:2}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestFaultToleranceTrailingComma - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:16, Line:0}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:11, Line:0}, - }, - Name: "set_tx_meta", - }, - Args: { - &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Number: 1, - }, - nil, - }, - }, - }, -} ---- - -[TestFaultToleranceDestinationNoRemainingMispelledFrom - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:2, Line:5}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:10, Line:0}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Number: 10, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "a", - }, - }, - Destination: &parser.DestinationInorder{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:3, Line:4}, - }, - Clauses: { - { - Range: parser.Range{ - Start: parser.Position{Character:3, Line:3}, - End: parser.Position{Character:3, Line:4}, - }, - Cap: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:3}, - End: parser.Position{Character:16, Line:3}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:8, Line:3}, - End: parser.Position{Character:12, Line:3}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:3}, - End: parser.Position{Character:15, Line:3}, - }, - Number: 10, - }, - }, - To: nil, - }, - }, - Remaining: nil, - }, - }, - }, -} ---- - -[TestFaultToleranceIncompleteOrigin - 1] -parser.Program{ - Vars: { - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:11, Line:2}, - }, - Name: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:2}, - End: parser.Position{Character:9, Line:2}, - }, - Name: "a", - }, - Type: &parser.TypeDecl{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:6, Line:2}, - }, - Name: "asset", - }, - Origin: (*parser.FnCall)(nil), - }, - }, - Statements: nil, -} ---- - -[TestFaultToleranceIncompleteSave - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:4, Line:1}, - }, - SentValue: nil, - Amount: nil, - }, - }, -} ---- - -[TestFaultToleranceIncompleteSave2 - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:10, Line:1}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Number: 10, - }, - }, - }, - Amount: nil, - }, - }, -} ---- - -[TestFaultToleranceIncompleteSave3 - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:19, Line:1}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:10, Line:1}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Number: 10, - }, - }, - }, - Amount: nil, - }, - }, -} ---- diff --git a/internal/parser/__snapshots__/parser_test.snap b/internal/parser/__snapshots__/parser_test.snap deleted file mode 100755 index 1fb5140..0000000 --- a/internal/parser/__snapshots__/parser_test.snap +++ /dev/null @@ -1,2266 +0,0 @@ -[TestPlainAddress - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Name: "src", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestVariable - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:27, Line:1}, - }, - Name: "example_var_src", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:33, Line:2}, - }, - Name: "example_var_dest", - }, - }, - }, - }, -} ---- - -[TestAllotment - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:27, Line:1}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:25, Line:1}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x3}, - }, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:1}, - End: parser.Position{Character:25, Line:1}, - }, - Name: "s1", - }, - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:18, Line:2}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestAllotmentPerc - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:7}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:3, Line:5}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:4, Line:2}, - End: parser.Position{Character:16, Line:2}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:4, Line:2}, - End: parser.Position{Character:7, Line:2}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x2a}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x64}, - }, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:2}, - End: parser.Position{Character:16, Line:2}, - }, - Name: "s1", - }, - }, - }, - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:3}, - End: parser.Position{Character:13, Line:3}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:3}, - End: parser.Position{Character:4, Line:3}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:3}, - End: parser.Position{Character:13, Line:3}, - }, - Name: "s2", - }, - }, - }, - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:19, Line:4}, - }, - Allotment: &parser.RemainingAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:10, Line:4}, - }, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:4}, - End: parser.Position{Character:19, Line:4}, - }, - Name: "s3", - }, - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:6}, - End: parser.Position{Character:18, Line:6}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestAllotmentPercFloating - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:28, Line:1}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:26, Line:1}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:18, Line:1}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0xf2}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2710}, - }, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:24, Line:1}, - End: parser.Position{Character:26, Line:1}, - }, - Name: "s", - }, - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:18, Line:2}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestAllotmentDest - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "s", - }, - }, - Destination: &parser.DestinationAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:29, Line:2}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:27, Line:2}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - To: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:25, Line:2}, - End: parser.Position{Character:27, Line:2}, - }, - Name: "d", - }, - }, - }, - }, - }, - }, - }, - }, -} ---- - -[TestCapped - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceCapped{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:35, Line:1}, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:31, Line:1}, - End: parser.Position{Character:35, Line:1}, - }, - Name: "src", - }, - }, - Cap: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:1}, - End: parser.Position{Character:25, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:1}, - End: parser.Position{Character:21, Line:1}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:1}, - End: parser.Position{Character:24, Line:1}, - }, - Number: 10, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestCappedVariable - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceCapped{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:32, Line:1}, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:28, Line:1}, - End: parser.Position{Character:32, Line:1}, - }, - Name: "src", - }, - }, - Cap: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:1}, - End: parser.Position{Character:22, Line:1}, - }, - Name: "my_var", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestNested - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:7}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceInorder{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:3, Line:5}, - }, - Sources: { - &parser.SourceCapped{ - Range: parser.Range{ - Start: parser.Position{Character:4, Line:2}, - End: parser.Position{Character:27, Line:2}, - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:23, Line:2}, - End: parser.Position{Character:27, Line:2}, - }, - Name: "src", - }, - }, - Cap: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:8, Line:2}, - End: parser.Position{Character:17, Line:2}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:9, Line:2}, - End: parser.Position{Character:13, Line:2}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:14, Line:2}, - End: parser.Position{Character:16, Line:2}, - }, - Number: 42, - }, - }, - }, - &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:3}, - End: parser.Position{Character:3, Line:3}, - }, - Name: "a", - }, - }, - &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:3, Line:4}, - }, - Name: "b", - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:6}, - End: parser.Position{Character:21, Line:6}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestMultipleSends - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:1}, - End: parser.Position{Character:53, Line:1}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:1}, - End: parser.Position{Character:11, Line:1}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Number: 10, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:27, Line:1}, - End: parser.Position{Character:31, Line:1}, - }, - Name: "src", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:46, Line:1}, - End: parser.Position{Character:51, Line:1}, - }, - Name: "dest", - }, - }, - }, - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:53, Line:2}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:2}, - End: parser.Position{Character:15, Line:2}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:2}, - End: parser.Position{Character:15, Line:2}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:2}, - End: parser.Position{Character:11, Line:2}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:2}, - End: parser.Position{Character:14, Line:2}, - }, - Number: 20, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:27, Line:2}, - End: parser.Position{Character:31, Line:2}, - }, - Name: "src", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:46, Line:2}, - End: parser.Position{Character:51, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- -[TestEmptyVars - 1] -parser.Program{} ---- - -[TestSingleVar - 1] -parser.Program{ - Vars: { - { - Range: parser.Range{ - Start: parser.Position{Character:7, Line:0}, - End: parser.Position{Character:23, Line:0}, - }, - Name: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:0}, - End: parser.Position{Character:23, Line:0}, - }, - Name: "my_var", - }, - Type: &parser.TypeDecl{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Name: "monetary", - }, - Origin: (*parser.FnCall)(nil), - }, - }, - Statements: nil, -} ---- - -[TestVariableMonetary - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:13, Line:0}, - }, - Name: "example", - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "a", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:18, Line:2}, - }, - Name: "b", - }, - }, - }, - }, -} ---- - -[TestAllotmentDestRemaining - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:6}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "s", - }, - }, - Destination: &parser.DestinationAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:3, Line:5}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:3, Line:3}, - End: parser.Position{Character:12, Line:3}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:3, Line:3}, - End: parser.Position{Character:6, Line:3}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - To: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:3}, - End: parser.Position{Character:12, Line:3}, - }, - Name: "d", - }, - }, - }, - }, - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:17, Line:4}, - }, - Allotment: &parser.RemainingAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:10, Line:4}, - }, - }, - To: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:14, Line:4}, - End: parser.Position{Character:17, Line:4}, - }, - Name: "d2", - }, - }, - }, - }, - }, - }, - }, - }, -} ---- - -[TestAllotmentVariableSource - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:5}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:3, Line:3}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:11, Line:2}, - }, - Allotment: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:3, Line:2}, - }, - Name: "x", - }, - From: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:9, Line:2}, - End: parser.Position{Character:11, Line:2}, - }, - Name: "a", - }, - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:4}, - End: parser.Position{Character:18, Line:4}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestOverdraftUnbounded - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Name: "x", - }, - }, - Source: &parser.SourceOverdraft{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:43, Line:1}, - }, - Address: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Name: "src", - }, - Bounded: (*parser.ValueExpr)(nil), - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:2}, - End: parser.Position{Character:20, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestOverdraftUnboundedVariable - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Name: "x", - }, - }, - Source: &parser.SourceOverdraft{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:50, Line:1}, - }, - Address: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:21, Line:1}, - }, - Name: "my_src_var", - }, - Bounded: (*parser.ValueExpr)(nil), - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:2}, - End: parser.Position{Character:20, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestBoundedOverdraft - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:7, Line:0}, - }, - Name: "x", - }, - }, - Source: &parser.SourceOverdraft{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:57, Line:1}, - }, - Address: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:21, Line:1}, - }, - Name: "my_src_var", - }, - Bounded: &&parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:47, Line:1}, - End: parser.Position{Character:57, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:48, Line:1}, - End: parser.Position{Character:52, Line:1}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:53, Line:1}, - End: parser.Position{Character:56, Line:1}, - }, - Number: 100, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:2}, - End: parser.Position{Character:20, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestFunctionCallNoArgs - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:12, Line:0}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:10, Line:0}, - }, - Name: "example_fn", - }, - Args: nil, - }, - }, -} ---- - -[TestFunctionCallOneArg - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:20, Line:0}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:10, Line:0}, - }, - Name: "example_fn", - }, - Args: { - &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:0}, - End: parser.Position{Character:19, Line:0}, - }, - Name: "example", - }, - }, - }, - }, -} ---- - -[TestFunctionCallManyArgs - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:1, Line:7}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:10, Line:1}, - }, - Name: "example_fn", - }, - Args: { - &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:10, Line:2}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:2, Line:2}, - End: parser.Position{Character:6, Line:2}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:7, Line:2}, - End: parser.Position{Character:9, Line:2}, - }, - Number: 42, - }, - }, - &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:3}, - End: parser.Position{Character:4, Line:3}, - }, - Number: 100, - }, - &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:4, Line:4}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:5}, - End: parser.Position{Character:8, Line:5}, - }, - Name: "my_var", - }, - &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:6}, - End: parser.Position{Character:14, Line:6}, - }, - String: "example_str", - }, - }, - }, - }, -} ---- - -[TestVarOrigin - 1] -parser.Program{ - Vars: { - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:49, Line:2}, - }, - Name: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:2}, - End: parser.Position{Character:17, Line:2}, - }, - Name: "my_var", - }, - Type: &parser.TypeDecl{ - Range: parser.Range{ - Start: parser.Position{Character:1, Line:2}, - End: parser.Position{Character:9, Line:2}, - }, - Name: "monetary", - }, - Origin: &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{Character:20, Line:2}, - End: parser.Position{Character:49, Line:2}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{Character:20, Line:2}, - End: parser.Position{Character:29, Line:2}, - }, - Name: "origin_fn", - }, - Args: { - &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:30, Line:2}, - End: parser.Position{Character:41, Line:2}, - }, - Name: "my_account", - }, - &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:43, Line:2}, - End: parser.Position{Character:48, Line:2}, - }, - String: "str", - }, - }, - }, - }, - }, - Statements: nil, -} ---- - -[TestInorderSource - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceInorder{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:22, Line:1}, - }, - Sources: { - &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - Name: "s1", - }, - }, - &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:17, Line:1}, - End: parser.Position{Character:20, Line:1}, - }, - Name: "s2", - }, - }, - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:18, Line:2}, - }, - Name: "d", - }, - }, - }, - }, -} ---- - -[TestInorderDestination - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:7}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:9, Line:0}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:9, Line:0}, - }, - Name: "amt", - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "s", - }, - }, - Destination: &parser.DestinationInorder{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:3, Line:6}, - }, - Clauses: { - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:3}, - End: parser.Position{Character:15, Line:3}, - }, - Cap: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:3}, - End: parser.Position{Character:8, Line:3}, - }, - Name: "m1", - }, - To: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:3}, - End: parser.Position{Character:15, Line:3}, - }, - Name: "d1", - }, - }, - }, - }, - { - Range: parser.Range{ - Start: parser.Position{Character:1, Line:4}, - End: parser.Position{Character:16, Line:4}, - }, - Cap: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:4}, - End: parser.Position{Character:11, Line:4}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:4}, - End: parser.Position{Character:7, Line:4}, - }, - Asset: "C", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:8, Line:4}, - End: parser.Position{Character:10, Line:4}, - }, - Number: 42, - }, - }, - To: &parser.DestinationKept{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:4}, - End: parser.Position{Character:16, Line:4}, - }, - }, - }, - }, - Remaining: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:14, Line:5}, - End: parser.Position{Character:17, Line:5}, - }, - Name: "d3", - }, - }, - }, - }, - }, - }, -} ---- - -[TestSendAll - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueAll{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:14, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "ASSET", - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:10, Line:1}, - End: parser.Position{Character:12, Line:1}, - }, - Name: "a", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:2}, - End: parser.Position{Character:17, Line:2}, - }, - Name: "b", - }, - }, - }, - }, -} ---- - -[TestAllotmentDestKept - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:15, Line:0}, - }, - Number: 100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:13, Line:1}, - }, - Name: "s", - }, - }, - Destination: &parser.DestinationAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:28, Line:2}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:26, Line:2}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - To: &parser.DestinationKept{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:2}, - End: parser.Position{Character:26, Line:2}, - }, - }, - }, - }, - }, - }, - }, -} ---- - -[TestWhitespaceInRatio - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:1, Line:6}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:9, Line:1}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:9, Line:1}, - }, - Name: "var", - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:2}, - End: parser.Position{Character:17, Line:2}, - }, - Name: "world", - }, - }, - Destination: &parser.DestinationAllotment{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:3}, - End: parser.Position{Character:3, Line:5}, - }, - Items: { - { - Range: parser.Range{ - Start: parser.Position{Character:4, Line:4}, - End: parser.Position{Character:22, Line:4}, - }, - Allotment: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:4, Line:4}, - End: parser.Position{Character:9, Line:4}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x6}, - }, - }, - To: &parser.DestinationTo{ - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:13, Line:4}, - End: parser.Position{Character:22, Line:4}, - }, - Name: "player:1", - }, - }, - }, - }, - }, - }, - }, - }, -} ---- - -[TestShowErrorLines - 1] -Got errors while parsing: -mismatched input 'err' expecting {'max', '[', '{', RATIO_PORTION_LITERAL, PERCENTAGE_PORTION_LITERAL, STRING, NUMBER, VARIABLE_NAME, ACCOUNT, ASSET} - 0 | send [EUR/2 100] ( - 1 | source = err - | ~~ - 2 | destination = ee - -mismatched input 'ee' expecting {'[', '{', RATIO_PORTION_LITERAL, PERCENTAGE_PORTION_LITERAL, STRING, NUMBER, VARIABLE_NAME, ACCOUNT, ASSET} - 1 | source = err - 2 | destination = ee - | ~ - 3 | ) - - ---- - -[TestNegativeNumberLit - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SendStatement{ - Range: parser.Range{ - Start: parser.Position{}, - End: parser.Position{Character:1, Line:3}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:17, Line:0}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:0}, - End: parser.Position{Character:17, Line:0}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:0}, - End: parser.Position{Character:11, Line:0}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:0}, - End: parser.Position{Character:16, Line:0}, - }, - Number: -100, - }, - }, - }, - Source: &parser.SourceAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:11, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Name: "src", - }, - }, - Destination: &parser.DestinationAccount{ - ValueExpr: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:16, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Name: "dest", - }, - }, - }, - }, -} ---- - -[TestSaveStatementSimple - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:28, Line:1}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - Monetary: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:11, Line:1}, - }, - Asset: "EUR/2", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:1}, - End: parser.Position{Character:15, Line:1}, - }, - Number: 100, - }, - }, - }, - Amount: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:1}, - End: parser.Position{Character:28, Line:1}, - }, - Name: "alice", - }, - }, - }, -} ---- - -[TestSaveAllStatement - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:26, Line:1}, - }, - SentValue: &parser.SentValueAll{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:14, Line:1}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:6, Line:1}, - End: parser.Position{Character:11, Line:1}, - }, - Asset: "EUR/2", - }, - }, - Amount: &parser.AccountLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:20, Line:1}, - End: parser.Position{Character:26, Line:1}, - }, - Name: "alice", - }, - }, - }, -} ---- - -[TestSaveStatementVar - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.SaveStatement{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:19, Line:1}, - }, - SentValue: &parser.SentValueLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:9, Line:1}, - }, - Monetary: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:5, Line:1}, - End: parser.Position{Character:9, Line:1}, - }, - Name: "amt", - }, - }, - Amount: &parser.Variable{ - Range: parser.Range{ - Start: parser.Position{Character:15, Line:1}, - End: parser.Position{Character:19, Line:1}, - }, - Name: "acc", - }, - }, - }, -} ---- - -[TestInfix - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:36, Line:1}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:11, Line:1}, - }, - Name: "set_tx_meta", - }, - Args: { - &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - String: "k1", - }, - &parser.BinaryInfix{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:1}, - End: parser.Position{Character:35, Line:1}, - }, - Operator: "+", - Left: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:1}, - End: parser.Position{Character:19, Line:1}, - }, - Number: 1, - }, - Right: &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:1}, - End: parser.Position{Character:35, Line:1}, - }, - String: "invalid arg", - }, - }, - }, - }, - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:2}, - End: parser.Position{Character:34, Line:2}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:2}, - End: parser.Position{Character:11, Line:2}, - }, - Name: "set_tx_meta", - }, - Args: { - &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:2}, - End: parser.Position{Character:16, Line:2}, - }, - String: "k2", - }, - &parser.BinaryInfix{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:33, Line:2}, - }, - Operator: "-", - Left: &parser.RatioLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:2}, - End: parser.Position{Character:21, Line:2}, - }, - Numerator: &big.Int{ - neg: false, - abs: {0x1}, - }, - Denominator: &big.Int{ - neg: false, - abs: {0x2}, - }, - }, - Right: &parser.MonetaryLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:24, Line:2}, - End: parser.Position{Character:33, Line:2}, - }, - Asset: &parser.AssetLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:25, Line:2}, - End: parser.Position{Character:29, Line:2}, - }, - Asset: "COIN", - }, - Amount: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:30, Line:2}, - End: parser.Position{Character:32, Line:2}, - }, - Number: 10, - }, - }, - }, - }, - }, - }, -} ---- - - -[TestInfixPrec - 1] -parser.Program{ - Vars: nil, - Statements: { - &parser.FnCall{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:28, Line:1}, - }, - Caller: &parser.FnCallIdentifier{ - Range: parser.Range{ - Start: parser.Position{Character:0, Line:1}, - End: parser.Position{Character:11, Line:1}, - }, - Name: "set_tx_meta", - }, - Args: { - &parser.StringLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:12, Line:1}, - End: parser.Position{Character:16, Line:1}, - }, - String: "k1", - }, - &parser.BinaryInfix{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:1}, - End: parser.Position{Character:27, Line:1}, - }, - Operator: "-", - Left: &parser.BinaryInfix{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:1}, - End: parser.Position{Character:23, Line:1}, - }, - Operator: "+", - Left: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:18, Line:1}, - End: parser.Position{Character:19, Line:1}, - }, - Number: 1, - }, - Right: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:22, Line:1}, - End: parser.Position{Character:23, Line:1}, - }, - Number: 2, - }, - }, - Right: &parser.NumberLiteral{ - Range: parser.Range{ - Start: parser.Position{Character:26, Line:1}, - End: parser.Position{Character:27, Line:1}, - }, - Number: 3, - }, - }, - }, - }, - }, -} ---- diff --git a/internal/parser/__snapshots__/range_test.snap b/internal/parser/__snapshots__/range_test.snap deleted file mode 100755 index a942c3e..0000000 --- a/internal/parser/__snapshots__/range_test.snap +++ /dev/null @@ -1,24 +0,0 @@ - -[TestShowRangeOnSourceSameLine - 1] - 0 | example error end of line - | ~~~~~ ---- - -[TestShowRangeOnMultilineRanges - 1] - 0 | example err - | ~~~ - 1 | or spanning 2 lines - | ~~ ---- - -[TestShowRangeComplex - 1] - 0 | - 1 | example err - | ~~~~~~~~ - 2 | or that spans more - | ~~~~~~~~~~~~~~~~~~ - 3 | lines and then other - | ~~~~~ - 4 | words with no error - ---- diff --git a/internal/parser/antlr/Numscript.interp b/internal/parser/antlr/Numscript.interp deleted file mode 100644 index 8dc2e94..0000000 --- a/internal/parser/antlr/Numscript.interp +++ /dev/null @@ -1,104 +0,0 @@ -token literal names: -null -'+' -null -null -null -null -'vars' -'max' -'source' -'destination' -'send' -'from' -'up' -'to' -'remaining' -'allowing' -'unbounded' -'overdraft' -'kept' -'save' -'(' -')' -'[' -']' -'{' -'}' -',' -'=' -'*' -'-' -null -null -null -null -null -null -null -null - -token symbolic names: -null -null -WS -NEWLINE -MULTILINE_COMMENT -LINE_COMMENT -VARS -MAX -SOURCE -DESTINATION -SEND -FROM -UP -TO -REMAINING -ALLOWING -UNBOUNDED -OVERDRAFT -KEPT -SAVE -LPARENS -RPARENS -LBRACKET -RBRACKET -LBRACE -RBRACE -COMMA -EQ -STAR -MINUS -RATIO_PORTION_LITERAL -PERCENTAGE_PORTION_LITERAL -STRING -IDENTIFIER -NUMBER -VARIABLE_NAME -ACCOUNT -ASSET - -rule names: -monetaryLit -portion -valueExpr -functionCallArgs -functionCall -varOrigin -varDeclaration -varsDeclaration -program -sentAllLit -allotment -source -allotmentClauseSrc -keptOrDestination -destinationInOrderClause -destination -allotmentClauseDest -sentValue -statement - - -atn: -[4, 1, 37, 217, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 3, 1, 46, 8, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 56, 8, 2, 1, 2, 1, 2, 1, 2, 5, 2, 61, 8, 2, 10, 2, 12, 2, 64, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 69, 8, 3, 10, 3, 12, 3, 72, 9, 3, 1, 4, 1, 4, 1, 4, 3, 4, 77, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 3, 6, 87, 8, 6, 1, 7, 1, 7, 1, 7, 5, 7, 92, 8, 7, 10, 7, 12, 7, 95, 9, 7, 1, 7, 1, 7, 1, 8, 3, 8, 100, 8, 8, 1, 8, 5, 8, 103, 8, 8, 10, 8, 12, 8, 106, 9, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 3, 10, 118, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 4, 11, 135, 8, 11, 11, 11, 12, 11, 136, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 143, 8, 11, 10, 11, 12, 11, 146, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 3, 11, 154, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 3, 13, 163, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 4, 15, 172, 8, 15, 11, 15, 12, 15, 173, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 180, 8, 15, 10, 15, 12, 15, 183, 9, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 189, 8, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 196, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 215, 8, 18, 1, 18, 0, 1, 4, 19, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 0, 1, 2, 0, 1, 1, 29, 29, 228, 0, 38, 1, 0, 0, 0, 2, 45, 1, 0, 0, 0, 4, 55, 1, 0, 0, 0, 6, 65, 1, 0, 0, 0, 8, 73, 1, 0, 0, 0, 10, 80, 1, 0, 0, 0, 12, 83, 1, 0, 0, 0, 14, 88, 1, 0, 0, 0, 16, 99, 1, 0, 0, 0, 18, 109, 1, 0, 0, 0, 20, 117, 1, 0, 0, 0, 22, 153, 1, 0, 0, 0, 24, 155, 1, 0, 0, 0, 26, 162, 1, 0, 0, 0, 28, 164, 1, 0, 0, 0, 30, 188, 1, 0, 0, 0, 32, 190, 1, 0, 0, 0, 34, 195, 1, 0, 0, 0, 36, 214, 1, 0, 0, 0, 38, 39, 5, 22, 0, 0, 39, 40, 3, 4, 2, 0, 40, 41, 3, 4, 2, 0, 41, 42, 5, 23, 0, 0, 42, 1, 1, 0, 0, 0, 43, 46, 5, 30, 0, 0, 44, 46, 5, 31, 0, 0, 45, 43, 1, 0, 0, 0, 45, 44, 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 48, 6, 2, -1, 0, 48, 56, 5, 35, 0, 0, 49, 56, 5, 37, 0, 0, 50, 56, 5, 32, 0, 0, 51, 56, 5, 36, 0, 0, 52, 56, 5, 34, 0, 0, 53, 56, 3, 0, 0, 0, 54, 56, 3, 2, 1, 0, 55, 47, 1, 0, 0, 0, 55, 49, 1, 0, 0, 0, 55, 50, 1, 0, 0, 0, 55, 51, 1, 0, 0, 0, 55, 52, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 54, 1, 0, 0, 0, 56, 62, 1, 0, 0, 0, 57, 58, 10, 1, 0, 0, 58, 59, 7, 0, 0, 0, 59, 61, 3, 4, 2, 2, 60, 57, 1, 0, 0, 0, 61, 64, 1, 0, 0, 0, 62, 60, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 5, 1, 0, 0, 0, 64, 62, 1, 0, 0, 0, 65, 70, 3, 4, 2, 0, 66, 67, 5, 26, 0, 0, 67, 69, 3, 4, 2, 0, 68, 66, 1, 0, 0, 0, 69, 72, 1, 0, 0, 0, 70, 68, 1, 0, 0, 0, 70, 71, 1, 0, 0, 0, 71, 7, 1, 0, 0, 0, 72, 70, 1, 0, 0, 0, 73, 74, 5, 33, 0, 0, 74, 76, 5, 20, 0, 0, 75, 77, 3, 6, 3, 0, 76, 75, 1, 0, 0, 0, 76, 77, 1, 0, 0, 0, 77, 78, 1, 0, 0, 0, 78, 79, 5, 21, 0, 0, 79, 9, 1, 0, 0, 0, 80, 81, 5, 27, 0, 0, 81, 82, 3, 8, 4, 0, 82, 11, 1, 0, 0, 0, 83, 84, 5, 33, 0, 0, 84, 86, 5, 35, 0, 0, 85, 87, 3, 10, 5, 0, 86, 85, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 13, 1, 0, 0, 0, 88, 89, 5, 6, 0, 0, 89, 93, 5, 24, 0, 0, 90, 92, 3, 12, 6, 0, 91, 90, 1, 0, 0, 0, 92, 95, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 96, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 96, 97, 5, 25, 0, 0, 97, 15, 1, 0, 0, 0, 98, 100, 3, 14, 7, 0, 99, 98, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 104, 1, 0, 0, 0, 101, 103, 3, 36, 18, 0, 102, 101, 1, 0, 0, 0, 103, 106, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 104, 105, 1, 0, 0, 0, 105, 107, 1, 0, 0, 0, 106, 104, 1, 0, 0, 0, 107, 108, 5, 0, 0, 1, 108, 17, 1, 0, 0, 0, 109, 110, 5, 22, 0, 0, 110, 111, 3, 4, 2, 0, 111, 112, 5, 28, 0, 0, 112, 113, 5, 23, 0, 0, 113, 19, 1, 0, 0, 0, 114, 118, 3, 2, 1, 0, 115, 118, 5, 35, 0, 0, 116, 118, 5, 14, 0, 0, 117, 114, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 117, 116, 1, 0, 0, 0, 118, 21, 1, 0, 0, 0, 119, 120, 3, 4, 2, 0, 120, 121, 5, 15, 0, 0, 121, 122, 5, 16, 0, 0, 122, 123, 5, 17, 0, 0, 123, 154, 1, 0, 0, 0, 124, 125, 3, 4, 2, 0, 125, 126, 5, 15, 0, 0, 126, 127, 5, 17, 0, 0, 127, 128, 5, 12, 0, 0, 128, 129, 5, 13, 0, 0, 129, 130, 3, 4, 2, 0, 130, 154, 1, 0, 0, 0, 131, 154, 3, 4, 2, 0, 132, 134, 5, 24, 0, 0, 133, 135, 3, 24, 12, 0, 134, 133, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 134, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 139, 5, 25, 0, 0, 139, 154, 1, 0, 0, 0, 140, 144, 5, 24, 0, 0, 141, 143, 3, 22, 11, 0, 142, 141, 1, 0, 0, 0, 143, 146, 1, 0, 0, 0, 144, 142, 1, 0, 0, 0, 144, 145, 1, 0, 0, 0, 145, 147, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 147, 154, 5, 25, 0, 0, 148, 149, 5, 7, 0, 0, 149, 150, 3, 4, 2, 0, 150, 151, 5, 11, 0, 0, 151, 152, 3, 22, 11, 0, 152, 154, 1, 0, 0, 0, 153, 119, 1, 0, 0, 0, 153, 124, 1, 0, 0, 0, 153, 131, 1, 0, 0, 0, 153, 132, 1, 0, 0, 0, 153, 140, 1, 0, 0, 0, 153, 148, 1, 0, 0, 0, 154, 23, 1, 0, 0, 0, 155, 156, 3, 20, 10, 0, 156, 157, 5, 11, 0, 0, 157, 158, 3, 22, 11, 0, 158, 25, 1, 0, 0, 0, 159, 160, 5, 13, 0, 0, 160, 163, 3, 30, 15, 0, 161, 163, 5, 18, 0, 0, 162, 159, 1, 0, 0, 0, 162, 161, 1, 0, 0, 0, 163, 27, 1, 0, 0, 0, 164, 165, 5, 7, 0, 0, 165, 166, 3, 4, 2, 0, 166, 167, 3, 26, 13, 0, 167, 29, 1, 0, 0, 0, 168, 189, 3, 4, 2, 0, 169, 171, 5, 24, 0, 0, 170, 172, 3, 32, 16, 0, 171, 170, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 173, 171, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 176, 5, 25, 0, 0, 176, 189, 1, 0, 0, 0, 177, 181, 5, 24, 0, 0, 178, 180, 3, 28, 14, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 185, 5, 14, 0, 0, 185, 186, 3, 26, 13, 0, 186, 187, 5, 25, 0, 0, 187, 189, 1, 0, 0, 0, 188, 168, 1, 0, 0, 0, 188, 169, 1, 0, 0, 0, 188, 177, 1, 0, 0, 0, 189, 31, 1, 0, 0, 0, 190, 191, 3, 20, 10, 0, 191, 192, 3, 26, 13, 0, 192, 33, 1, 0, 0, 0, 193, 196, 3, 4, 2, 0, 194, 196, 3, 18, 9, 0, 195, 193, 1, 0, 0, 0, 195, 194, 1, 0, 0, 0, 196, 35, 1, 0, 0, 0, 197, 198, 5, 10, 0, 0, 198, 199, 3, 34, 17, 0, 199, 200, 5, 20, 0, 0, 200, 201, 5, 8, 0, 0, 201, 202, 5, 27, 0, 0, 202, 203, 3, 22, 11, 0, 203, 204, 5, 9, 0, 0, 204, 205, 5, 27, 0, 0, 205, 206, 3, 30, 15, 0, 206, 207, 5, 21, 0, 0, 207, 215, 1, 0, 0, 0, 208, 209, 5, 19, 0, 0, 209, 210, 3, 34, 17, 0, 210, 211, 5, 11, 0, 0, 211, 212, 3, 4, 2, 0, 212, 215, 1, 0, 0, 0, 213, 215, 3, 8, 4, 0, 214, 197, 1, 0, 0, 0, 214, 208, 1, 0, 0, 0, 214, 213, 1, 0, 0, 0, 215, 37, 1, 0, 0, 0, 19, 45, 55, 62, 70, 76, 86, 93, 99, 104, 117, 136, 144, 153, 162, 173, 181, 188, 195, 214] \ No newline at end of file diff --git a/internal/parser/antlr/Numscript.tokens b/internal/parser/antlr/Numscript.tokens deleted file mode 100644 index 9005dee..0000000 --- a/internal/parser/antlr/Numscript.tokens +++ /dev/null @@ -1,62 +0,0 @@ -T__0=1 -WS=2 -NEWLINE=3 -MULTILINE_COMMENT=4 -LINE_COMMENT=5 -VARS=6 -MAX=7 -SOURCE=8 -DESTINATION=9 -SEND=10 -FROM=11 -UP=12 -TO=13 -REMAINING=14 -ALLOWING=15 -UNBOUNDED=16 -OVERDRAFT=17 -KEPT=18 -SAVE=19 -LPARENS=20 -RPARENS=21 -LBRACKET=22 -RBRACKET=23 -LBRACE=24 -RBRACE=25 -COMMA=26 -EQ=27 -STAR=28 -MINUS=29 -RATIO_PORTION_LITERAL=30 -PERCENTAGE_PORTION_LITERAL=31 -STRING=32 -IDENTIFIER=33 -NUMBER=34 -VARIABLE_NAME=35 -ACCOUNT=36 -ASSET=37 -'+'=1 -'vars'=6 -'max'=7 -'source'=8 -'destination'=9 -'send'=10 -'from'=11 -'up'=12 -'to'=13 -'remaining'=14 -'allowing'=15 -'unbounded'=16 -'overdraft'=17 -'kept'=18 -'save'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'{'=24 -'}'=25 -','=26 -'='=27 -'*'=28 -'-'=29 diff --git a/internal/parser/antlr/NumscriptLexer.interp b/internal/parser/antlr/NumscriptLexer.interp deleted file mode 100644 index 316d7fb..0000000 --- a/internal/parser/antlr/NumscriptLexer.interp +++ /dev/null @@ -1,128 +0,0 @@ -token literal names: -null -'+' -null -null -null -null -'vars' -'max' -'source' -'destination' -'send' -'from' -'up' -'to' -'remaining' -'allowing' -'unbounded' -'overdraft' -'kept' -'save' -'(' -')' -'[' -']' -'{' -'}' -',' -'=' -'*' -'-' -null -null -null -null -null -null -null -null - -token symbolic names: -null -null -WS -NEWLINE -MULTILINE_COMMENT -LINE_COMMENT -VARS -MAX -SOURCE -DESTINATION -SEND -FROM -UP -TO -REMAINING -ALLOWING -UNBOUNDED -OVERDRAFT -KEPT -SAVE -LPARENS -RPARENS -LBRACKET -RBRACKET -LBRACE -RBRACE -COMMA -EQ -STAR -MINUS -RATIO_PORTION_LITERAL -PERCENTAGE_PORTION_LITERAL -STRING -IDENTIFIER -NUMBER -VARIABLE_NAME -ACCOUNT -ASSET - -rule names: -T__0 -WS -NEWLINE -MULTILINE_COMMENT -LINE_COMMENT -VARS -MAX -SOURCE -DESTINATION -SEND -FROM -UP -TO -REMAINING -ALLOWING -UNBOUNDED -OVERDRAFT -KEPT -SAVE -LPARENS -RPARENS -LBRACKET -RBRACKET -LBRACE -RBRACE -COMMA -EQ -STAR -MINUS -RATIO_PORTION_LITERAL -PERCENTAGE_PORTION_LITERAL -STRING -IDENTIFIER -NUMBER -VARIABLE_NAME -ACCOUNT -ASSET - -channel names: -DEFAULT_TOKEN_CHANNEL -HIDDEN - -mode names: -DEFAULT_MODE - -atn: -[4, 0, 37, 326, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 1, 0, 1, 0, 1, 1, 4, 1, 79, 8, 1, 11, 1, 12, 1, 80, 1, 1, 1, 1, 1, 2, 4, 2, 86, 8, 2, 11, 2, 12, 2, 87, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 95, 8, 3, 10, 3, 12, 3, 98, 9, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 109, 8, 4, 10, 4, 12, 4, 112, 9, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 4, 29, 232, 8, 29, 11, 29, 12, 29, 233, 1, 29, 3, 29, 237, 8, 29, 1, 29, 1, 29, 3, 29, 241, 8, 29, 1, 29, 4, 29, 244, 8, 29, 11, 29, 12, 29, 245, 1, 30, 4, 30, 249, 8, 30, 11, 30, 12, 30, 250, 1, 30, 1, 30, 4, 30, 255, 8, 30, 11, 30, 12, 30, 256, 3, 30, 259, 8, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 267, 8, 31, 10, 31, 12, 31, 270, 9, 31, 1, 31, 1, 31, 1, 32, 4, 32, 275, 8, 32, 11, 32, 12, 32, 276, 1, 32, 5, 32, 280, 8, 32, 10, 32, 12, 32, 283, 9, 32, 1, 33, 3, 33, 286, 8, 33, 1, 33, 4, 33, 289, 8, 33, 11, 33, 12, 33, 290, 1, 34, 1, 34, 4, 34, 295, 8, 34, 11, 34, 12, 34, 296, 1, 34, 5, 34, 300, 8, 34, 10, 34, 12, 34, 303, 9, 34, 1, 35, 1, 35, 4, 35, 307, 8, 35, 11, 35, 12, 35, 308, 1, 35, 1, 35, 4, 35, 313, 8, 35, 11, 35, 12, 35, 314, 5, 35, 317, 8, 35, 10, 35, 12, 35, 320, 9, 35, 1, 36, 4, 36, 323, 8, 36, 11, 36, 12, 36, 324, 2, 96, 110, 0, 37, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 1, 0, 10, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 1, 0, 32, 32, 3, 0, 10, 10, 13, 13, 34, 34, 1, 0, 97, 122, 2, 0, 95, 95, 97, 122, 3, 0, 48, 57, 95, 95, 97, 122, 5, 0, 45, 45, 48, 57, 65, 90, 95, 95, 97, 122, 2, 0, 47, 57, 65, 90, 349, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 1, 75, 1, 0, 0, 0, 3, 78, 1, 0, 0, 0, 5, 85, 1, 0, 0, 0, 7, 89, 1, 0, 0, 0, 9, 104, 1, 0, 0, 0, 11, 117, 1, 0, 0, 0, 13, 122, 1, 0, 0, 0, 15, 126, 1, 0, 0, 0, 17, 133, 1, 0, 0, 0, 19, 145, 1, 0, 0, 0, 21, 150, 1, 0, 0, 0, 23, 155, 1, 0, 0, 0, 25, 158, 1, 0, 0, 0, 27, 161, 1, 0, 0, 0, 29, 171, 1, 0, 0, 0, 31, 180, 1, 0, 0, 0, 33, 190, 1, 0, 0, 0, 35, 200, 1, 0, 0, 0, 37, 205, 1, 0, 0, 0, 39, 210, 1, 0, 0, 0, 41, 212, 1, 0, 0, 0, 43, 214, 1, 0, 0, 0, 45, 216, 1, 0, 0, 0, 47, 218, 1, 0, 0, 0, 49, 220, 1, 0, 0, 0, 51, 222, 1, 0, 0, 0, 53, 224, 1, 0, 0, 0, 55, 226, 1, 0, 0, 0, 57, 228, 1, 0, 0, 0, 59, 231, 1, 0, 0, 0, 61, 248, 1, 0, 0, 0, 63, 262, 1, 0, 0, 0, 65, 274, 1, 0, 0, 0, 67, 285, 1, 0, 0, 0, 69, 292, 1, 0, 0, 0, 71, 304, 1, 0, 0, 0, 73, 322, 1, 0, 0, 0, 75, 76, 5, 43, 0, 0, 76, 2, 1, 0, 0, 0, 77, 79, 7, 0, 0, 0, 78, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 78, 1, 0, 0, 0, 80, 81, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 83, 6, 1, 0, 0, 83, 4, 1, 0, 0, 0, 84, 86, 7, 1, 0, 0, 85, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 6, 1, 0, 0, 0, 89, 90, 5, 47, 0, 0, 90, 91, 5, 42, 0, 0, 91, 96, 1, 0, 0, 0, 92, 95, 3, 7, 3, 0, 93, 95, 9, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 93, 1, 0, 0, 0, 95, 98, 1, 0, 0, 0, 96, 97, 1, 0, 0, 0, 96, 94, 1, 0, 0, 0, 97, 99, 1, 0, 0, 0, 98, 96, 1, 0, 0, 0, 99, 100, 5, 42, 0, 0, 100, 101, 5, 47, 0, 0, 101, 102, 1, 0, 0, 0, 102, 103, 6, 3, 0, 0, 103, 8, 1, 0, 0, 0, 104, 105, 5, 47, 0, 0, 105, 106, 5, 47, 0, 0, 106, 110, 1, 0, 0, 0, 107, 109, 9, 0, 0, 0, 108, 107, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 111, 113, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 3, 5, 2, 0, 114, 115, 1, 0, 0, 0, 115, 116, 6, 4, 0, 0, 116, 10, 1, 0, 0, 0, 117, 118, 5, 118, 0, 0, 118, 119, 5, 97, 0, 0, 119, 120, 5, 114, 0, 0, 120, 121, 5, 115, 0, 0, 121, 12, 1, 0, 0, 0, 122, 123, 5, 109, 0, 0, 123, 124, 5, 97, 0, 0, 124, 125, 5, 120, 0, 0, 125, 14, 1, 0, 0, 0, 126, 127, 5, 115, 0, 0, 127, 128, 5, 111, 0, 0, 128, 129, 5, 117, 0, 0, 129, 130, 5, 114, 0, 0, 130, 131, 5, 99, 0, 0, 131, 132, 5, 101, 0, 0, 132, 16, 1, 0, 0, 0, 133, 134, 5, 100, 0, 0, 134, 135, 5, 101, 0, 0, 135, 136, 5, 115, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 110, 0, 0, 139, 140, 5, 97, 0, 0, 140, 141, 5, 116, 0, 0, 141, 142, 5, 105, 0, 0, 142, 143, 5, 111, 0, 0, 143, 144, 5, 110, 0, 0, 144, 18, 1, 0, 0, 0, 145, 146, 5, 115, 0, 0, 146, 147, 5, 101, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, 5, 100, 0, 0, 149, 20, 1, 0, 0, 0, 150, 151, 5, 102, 0, 0, 151, 152, 5, 114, 0, 0, 152, 153, 5, 111, 0, 0, 153, 154, 5, 109, 0, 0, 154, 22, 1, 0, 0, 0, 155, 156, 5, 117, 0, 0, 156, 157, 5, 112, 0, 0, 157, 24, 1, 0, 0, 0, 158, 159, 5, 116, 0, 0, 159, 160, 5, 111, 0, 0, 160, 26, 1, 0, 0, 0, 161, 162, 5, 114, 0, 0, 162, 163, 5, 101, 0, 0, 163, 164, 5, 109, 0, 0, 164, 165, 5, 97, 0, 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 110, 0, 0, 167, 168, 5, 105, 0, 0, 168, 169, 5, 110, 0, 0, 169, 170, 5, 103, 0, 0, 170, 28, 1, 0, 0, 0, 171, 172, 5, 97, 0, 0, 172, 173, 5, 108, 0, 0, 173, 174, 5, 108, 0, 0, 174, 175, 5, 111, 0, 0, 175, 176, 5, 119, 0, 0, 176, 177, 5, 105, 0, 0, 177, 178, 5, 110, 0, 0, 178, 179, 5, 103, 0, 0, 179, 30, 1, 0, 0, 0, 180, 181, 5, 117, 0, 0, 181, 182, 5, 110, 0, 0, 182, 183, 5, 98, 0, 0, 183, 184, 5, 111, 0, 0, 184, 185, 5, 117, 0, 0, 185, 186, 5, 110, 0, 0, 186, 187, 5, 100, 0, 0, 187, 188, 5, 101, 0, 0, 188, 189, 5, 100, 0, 0, 189, 32, 1, 0, 0, 0, 190, 191, 5, 111, 0, 0, 191, 192, 5, 118, 0, 0, 192, 193, 5, 101, 0, 0, 193, 194, 5, 114, 0, 0, 194, 195, 5, 100, 0, 0, 195, 196, 5, 114, 0, 0, 196, 197, 5, 97, 0, 0, 197, 198, 5, 102, 0, 0, 198, 199, 5, 116, 0, 0, 199, 34, 1, 0, 0, 0, 200, 201, 5, 107, 0, 0, 201, 202, 5, 101, 0, 0, 202, 203, 5, 112, 0, 0, 203, 204, 5, 116, 0, 0, 204, 36, 1, 0, 0, 0, 205, 206, 5, 115, 0, 0, 206, 207, 5, 97, 0, 0, 207, 208, 5, 118, 0, 0, 208, 209, 5, 101, 0, 0, 209, 38, 1, 0, 0, 0, 210, 211, 5, 40, 0, 0, 211, 40, 1, 0, 0, 0, 212, 213, 5, 41, 0, 0, 213, 42, 1, 0, 0, 0, 214, 215, 5, 91, 0, 0, 215, 44, 1, 0, 0, 0, 216, 217, 5, 93, 0, 0, 217, 46, 1, 0, 0, 0, 218, 219, 5, 123, 0, 0, 219, 48, 1, 0, 0, 0, 220, 221, 5, 125, 0, 0, 221, 50, 1, 0, 0, 0, 222, 223, 5, 44, 0, 0, 223, 52, 1, 0, 0, 0, 224, 225, 5, 61, 0, 0, 225, 54, 1, 0, 0, 0, 226, 227, 5, 42, 0, 0, 227, 56, 1, 0, 0, 0, 228, 229, 5, 45, 0, 0, 229, 58, 1, 0, 0, 0, 230, 232, 7, 2, 0, 0, 231, 230, 1, 0, 0, 0, 232, 233, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 233, 234, 1, 0, 0, 0, 234, 236, 1, 0, 0, 0, 235, 237, 7, 3, 0, 0, 236, 235, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 240, 5, 47, 0, 0, 239, 241, 7, 3, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 243, 1, 0, 0, 0, 242, 244, 7, 2, 0, 0, 243, 242, 1, 0, 0, 0, 244, 245, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 60, 1, 0, 0, 0, 247, 249, 7, 2, 0, 0, 248, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 258, 1, 0, 0, 0, 252, 254, 5, 46, 0, 0, 253, 255, 7, 2, 0, 0, 254, 253, 1, 0, 0, 0, 255, 256, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 259, 1, 0, 0, 0, 258, 252, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 5, 37, 0, 0, 261, 62, 1, 0, 0, 0, 262, 268, 5, 34, 0, 0, 263, 264, 5, 92, 0, 0, 264, 267, 5, 34, 0, 0, 265, 267, 8, 4, 0, 0, 266, 263, 1, 0, 0, 0, 266, 265, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 271, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 271, 272, 5, 34, 0, 0, 272, 64, 1, 0, 0, 0, 273, 275, 7, 5, 0, 0, 274, 273, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 274, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 281, 1, 0, 0, 0, 278, 280, 7, 6, 0, 0, 279, 278, 1, 0, 0, 0, 280, 283, 1, 0, 0, 0, 281, 279, 1, 0, 0, 0, 281, 282, 1, 0, 0, 0, 282, 66, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 284, 286, 3, 57, 28, 0, 285, 284, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 288, 1, 0, 0, 0, 287, 289, 7, 2, 0, 0, 288, 287, 1, 0, 0, 0, 289, 290, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 290, 291, 1, 0, 0, 0, 291, 68, 1, 0, 0, 0, 292, 294, 5, 36, 0, 0, 293, 295, 7, 6, 0, 0, 294, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 301, 1, 0, 0, 0, 298, 300, 7, 7, 0, 0, 299, 298, 1, 0, 0, 0, 300, 303, 1, 0, 0, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 70, 1, 0, 0, 0, 303, 301, 1, 0, 0, 0, 304, 306, 5, 64, 0, 0, 305, 307, 7, 8, 0, 0, 306, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 318, 1, 0, 0, 0, 310, 312, 5, 58, 0, 0, 311, 313, 7, 8, 0, 0, 312, 311, 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 315, 1, 0, 0, 0, 315, 317, 1, 0, 0, 0, 316, 310, 1, 0, 0, 0, 317, 320, 1, 0, 0, 0, 318, 316, 1, 0, 0, 0, 318, 319, 1, 0, 0, 0, 319, 72, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 321, 323, 7, 9, 0, 0, 322, 321, 1, 0, 0, 0, 323, 324, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, 0, 325, 74, 1, 0, 0, 0, 25, 0, 80, 87, 94, 96, 110, 233, 236, 240, 245, 250, 256, 258, 266, 268, 276, 281, 285, 290, 296, 301, 308, 314, 318, 324, 1, 6, 0, 0] \ No newline at end of file diff --git a/internal/parser/antlr/NumscriptLexer.tokens b/internal/parser/antlr/NumscriptLexer.tokens deleted file mode 100644 index 9005dee..0000000 --- a/internal/parser/antlr/NumscriptLexer.tokens +++ /dev/null @@ -1,62 +0,0 @@ -T__0=1 -WS=2 -NEWLINE=3 -MULTILINE_COMMENT=4 -LINE_COMMENT=5 -VARS=6 -MAX=7 -SOURCE=8 -DESTINATION=9 -SEND=10 -FROM=11 -UP=12 -TO=13 -REMAINING=14 -ALLOWING=15 -UNBOUNDED=16 -OVERDRAFT=17 -KEPT=18 -SAVE=19 -LPARENS=20 -RPARENS=21 -LBRACKET=22 -RBRACKET=23 -LBRACE=24 -RBRACE=25 -COMMA=26 -EQ=27 -STAR=28 -MINUS=29 -RATIO_PORTION_LITERAL=30 -PERCENTAGE_PORTION_LITERAL=31 -STRING=32 -IDENTIFIER=33 -NUMBER=34 -VARIABLE_NAME=35 -ACCOUNT=36 -ASSET=37 -'+'=1 -'vars'=6 -'max'=7 -'source'=8 -'destination'=9 -'send'=10 -'from'=11 -'up'=12 -'to'=13 -'remaining'=14 -'allowing'=15 -'unbounded'=16 -'overdraft'=17 -'kept'=18 -'save'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'{'=24 -'}'=25 -','=26 -'='=27 -'*'=28 -'-'=29 diff --git a/internal/parser/antlr/numscript_base_listener.go b/internal/parser/antlr/numscript_base_listener.go deleted file mode 100644 index 746f85e..0000000 --- a/internal/parser/antlr/numscript_base_listener.go +++ /dev/null @@ -1,265 +0,0 @@ -// Code generated from Numscript.g4 by ANTLR 4.13.1. DO NOT EDIT. - -package parser // Numscript -import "github.com/antlr4-go/antlr/v4" - -// BaseNumscriptListener is a complete listener for a parse tree produced by NumscriptParser. -type BaseNumscriptListener struct{} - -var _ NumscriptListener = &BaseNumscriptListener{} - -// VisitTerminal is called when a terminal node is visited. -func (s *BaseNumscriptListener) VisitTerminal(node antlr.TerminalNode) {} - -// VisitErrorNode is called when an error node is visited. -func (s *BaseNumscriptListener) VisitErrorNode(node antlr.ErrorNode) {} - -// EnterEveryRule is called when any rule is entered. -func (s *BaseNumscriptListener) EnterEveryRule(ctx antlr.ParserRuleContext) {} - -// ExitEveryRule is called when any rule is exited. -func (s *BaseNumscriptListener) ExitEveryRule(ctx antlr.ParserRuleContext) {} - -// EnterMonetaryLit is called when production monetaryLit is entered. -func (s *BaseNumscriptListener) EnterMonetaryLit(ctx *MonetaryLitContext) {} - -// ExitMonetaryLit is called when production monetaryLit is exited. -func (s *BaseNumscriptListener) ExitMonetaryLit(ctx *MonetaryLitContext) {} - -// EnterRatio is called when production ratio is entered. -func (s *BaseNumscriptListener) EnterRatio(ctx *RatioContext) {} - -// ExitRatio is called when production ratio is exited. -func (s *BaseNumscriptListener) ExitRatio(ctx *RatioContext) {} - -// EnterPercentage is called when production percentage is entered. -func (s *BaseNumscriptListener) EnterPercentage(ctx *PercentageContext) {} - -// ExitPercentage is called when production percentage is exited. -func (s *BaseNumscriptListener) ExitPercentage(ctx *PercentageContext) {} - -// EnterVariableExpr is called when production variableExpr is entered. -func (s *BaseNumscriptListener) EnterVariableExpr(ctx *VariableExprContext) {} - -// ExitVariableExpr is called when production variableExpr is exited. -func (s *BaseNumscriptListener) ExitVariableExpr(ctx *VariableExprContext) {} - -// EnterPortionLiteral is called when production portionLiteral is entered. -func (s *BaseNumscriptListener) EnterPortionLiteral(ctx *PortionLiteralContext) {} - -// ExitPortionLiteral is called when production portionLiteral is exited. -func (s *BaseNumscriptListener) ExitPortionLiteral(ctx *PortionLiteralContext) {} - -// EnterInfixExpr is called when production infixExpr is entered. -func (s *BaseNumscriptListener) EnterInfixExpr(ctx *InfixExprContext) {} - -// ExitInfixExpr is called when production infixExpr is exited. -func (s *BaseNumscriptListener) ExitInfixExpr(ctx *InfixExprContext) {} - -// EnterAssetLiteral is called when production assetLiteral is entered. -func (s *BaseNumscriptListener) EnterAssetLiteral(ctx *AssetLiteralContext) {} - -// ExitAssetLiteral is called when production assetLiteral is exited. -func (s *BaseNumscriptListener) ExitAssetLiteral(ctx *AssetLiteralContext) {} - -// EnterStringLiteral is called when production stringLiteral is entered. -func (s *BaseNumscriptListener) EnterStringLiteral(ctx *StringLiteralContext) {} - -// ExitStringLiteral is called when production stringLiteral is exited. -func (s *BaseNumscriptListener) ExitStringLiteral(ctx *StringLiteralContext) {} - -// EnterAccountLiteral is called when production accountLiteral is entered. -func (s *BaseNumscriptListener) EnterAccountLiteral(ctx *AccountLiteralContext) {} - -// ExitAccountLiteral is called when production accountLiteral is exited. -func (s *BaseNumscriptListener) ExitAccountLiteral(ctx *AccountLiteralContext) {} - -// EnterMonetaryLiteral is called when production monetaryLiteral is entered. -func (s *BaseNumscriptListener) EnterMonetaryLiteral(ctx *MonetaryLiteralContext) {} - -// ExitMonetaryLiteral is called when production monetaryLiteral is exited. -func (s *BaseNumscriptListener) ExitMonetaryLiteral(ctx *MonetaryLiteralContext) {} - -// EnterNumberLiteral is called when production numberLiteral is entered. -func (s *BaseNumscriptListener) EnterNumberLiteral(ctx *NumberLiteralContext) {} - -// ExitNumberLiteral is called when production numberLiteral is exited. -func (s *BaseNumscriptListener) ExitNumberLiteral(ctx *NumberLiteralContext) {} - -// EnterFunctionCallArgs is called when production functionCallArgs is entered. -func (s *BaseNumscriptListener) EnterFunctionCallArgs(ctx *FunctionCallArgsContext) {} - -// ExitFunctionCallArgs is called when production functionCallArgs is exited. -func (s *BaseNumscriptListener) ExitFunctionCallArgs(ctx *FunctionCallArgsContext) {} - -// EnterFunctionCall is called when production functionCall is entered. -func (s *BaseNumscriptListener) EnterFunctionCall(ctx *FunctionCallContext) {} - -// ExitFunctionCall is called when production functionCall is exited. -func (s *BaseNumscriptListener) ExitFunctionCall(ctx *FunctionCallContext) {} - -// EnterVarOrigin is called when production varOrigin is entered. -func (s *BaseNumscriptListener) EnterVarOrigin(ctx *VarOriginContext) {} - -// ExitVarOrigin is called when production varOrigin is exited. -func (s *BaseNumscriptListener) ExitVarOrigin(ctx *VarOriginContext) {} - -// EnterVarDeclaration is called when production varDeclaration is entered. -func (s *BaseNumscriptListener) EnterVarDeclaration(ctx *VarDeclarationContext) {} - -// ExitVarDeclaration is called when production varDeclaration is exited. -func (s *BaseNumscriptListener) ExitVarDeclaration(ctx *VarDeclarationContext) {} - -// EnterVarsDeclaration is called when production varsDeclaration is entered. -func (s *BaseNumscriptListener) EnterVarsDeclaration(ctx *VarsDeclarationContext) {} - -// ExitVarsDeclaration is called when production varsDeclaration is exited. -func (s *BaseNumscriptListener) ExitVarsDeclaration(ctx *VarsDeclarationContext) {} - -// EnterProgram is called when production program is entered. -func (s *BaseNumscriptListener) EnterProgram(ctx *ProgramContext) {} - -// ExitProgram is called when production program is exited. -func (s *BaseNumscriptListener) ExitProgram(ctx *ProgramContext) {} - -// EnterSentAllLit is called when production sentAllLit is entered. -func (s *BaseNumscriptListener) EnterSentAllLit(ctx *SentAllLitContext) {} - -// ExitSentAllLit is called when production sentAllLit is exited. -func (s *BaseNumscriptListener) ExitSentAllLit(ctx *SentAllLitContext) {} - -// EnterPortionedAllotment is called when production portionedAllotment is entered. -func (s *BaseNumscriptListener) EnterPortionedAllotment(ctx *PortionedAllotmentContext) {} - -// ExitPortionedAllotment is called when production portionedAllotment is exited. -func (s *BaseNumscriptListener) ExitPortionedAllotment(ctx *PortionedAllotmentContext) {} - -// EnterPortionVariable is called when production portionVariable is entered. -func (s *BaseNumscriptListener) EnterPortionVariable(ctx *PortionVariableContext) {} - -// ExitPortionVariable is called when production portionVariable is exited. -func (s *BaseNumscriptListener) ExitPortionVariable(ctx *PortionVariableContext) {} - -// EnterRemainingAllotment is called when production remainingAllotment is entered. -func (s *BaseNumscriptListener) EnterRemainingAllotment(ctx *RemainingAllotmentContext) {} - -// ExitRemainingAllotment is called when production remainingAllotment is exited. -func (s *BaseNumscriptListener) ExitRemainingAllotment(ctx *RemainingAllotmentContext) {} - -// EnterSrcAccountUnboundedOverdraft is called when production srcAccountUnboundedOverdraft is entered. -func (s *BaseNumscriptListener) EnterSrcAccountUnboundedOverdraft(ctx *SrcAccountUnboundedOverdraftContext) { -} - -// ExitSrcAccountUnboundedOverdraft is called when production srcAccountUnboundedOverdraft is exited. -func (s *BaseNumscriptListener) ExitSrcAccountUnboundedOverdraft(ctx *SrcAccountUnboundedOverdraftContext) { -} - -// EnterSrcAccountBoundedOverdraft is called when production srcAccountBoundedOverdraft is entered. -func (s *BaseNumscriptListener) EnterSrcAccountBoundedOverdraft(ctx *SrcAccountBoundedOverdraftContext) { -} - -// ExitSrcAccountBoundedOverdraft is called when production srcAccountBoundedOverdraft is exited. -func (s *BaseNumscriptListener) ExitSrcAccountBoundedOverdraft(ctx *SrcAccountBoundedOverdraftContext) { -} - -// EnterSrcAccount is called when production srcAccount is entered. -func (s *BaseNumscriptListener) EnterSrcAccount(ctx *SrcAccountContext) {} - -// ExitSrcAccount is called when production srcAccount is exited. -func (s *BaseNumscriptListener) ExitSrcAccount(ctx *SrcAccountContext) {} - -// EnterSrcAllotment is called when production srcAllotment is entered. -func (s *BaseNumscriptListener) EnterSrcAllotment(ctx *SrcAllotmentContext) {} - -// ExitSrcAllotment is called when production srcAllotment is exited. -func (s *BaseNumscriptListener) ExitSrcAllotment(ctx *SrcAllotmentContext) {} - -// EnterSrcInorder is called when production srcInorder is entered. -func (s *BaseNumscriptListener) EnterSrcInorder(ctx *SrcInorderContext) {} - -// ExitSrcInorder is called when production srcInorder is exited. -func (s *BaseNumscriptListener) ExitSrcInorder(ctx *SrcInorderContext) {} - -// EnterSrcCapped is called when production srcCapped is entered. -func (s *BaseNumscriptListener) EnterSrcCapped(ctx *SrcCappedContext) {} - -// ExitSrcCapped is called when production srcCapped is exited. -func (s *BaseNumscriptListener) ExitSrcCapped(ctx *SrcCappedContext) {} - -// EnterAllotmentClauseSrc is called when production allotmentClauseSrc is entered. -func (s *BaseNumscriptListener) EnterAllotmentClauseSrc(ctx *AllotmentClauseSrcContext) {} - -// ExitAllotmentClauseSrc is called when production allotmentClauseSrc is exited. -func (s *BaseNumscriptListener) ExitAllotmentClauseSrc(ctx *AllotmentClauseSrcContext) {} - -// EnterDestinationTo is called when production destinationTo is entered. -func (s *BaseNumscriptListener) EnterDestinationTo(ctx *DestinationToContext) {} - -// ExitDestinationTo is called when production destinationTo is exited. -func (s *BaseNumscriptListener) ExitDestinationTo(ctx *DestinationToContext) {} - -// EnterDestinationKept is called when production destinationKept is entered. -func (s *BaseNumscriptListener) EnterDestinationKept(ctx *DestinationKeptContext) {} - -// ExitDestinationKept is called when production destinationKept is exited. -func (s *BaseNumscriptListener) ExitDestinationKept(ctx *DestinationKeptContext) {} - -// EnterDestinationInOrderClause is called when production destinationInOrderClause is entered. -func (s *BaseNumscriptListener) EnterDestinationInOrderClause(ctx *DestinationInOrderClauseContext) {} - -// ExitDestinationInOrderClause is called when production destinationInOrderClause is exited. -func (s *BaseNumscriptListener) ExitDestinationInOrderClause(ctx *DestinationInOrderClauseContext) {} - -// EnterDestAccount is called when production destAccount is entered. -func (s *BaseNumscriptListener) EnterDestAccount(ctx *DestAccountContext) {} - -// ExitDestAccount is called when production destAccount is exited. -func (s *BaseNumscriptListener) ExitDestAccount(ctx *DestAccountContext) {} - -// EnterDestAllotment is called when production destAllotment is entered. -func (s *BaseNumscriptListener) EnterDestAllotment(ctx *DestAllotmentContext) {} - -// ExitDestAllotment is called when production destAllotment is exited. -func (s *BaseNumscriptListener) ExitDestAllotment(ctx *DestAllotmentContext) {} - -// EnterDestInorder is called when production destInorder is entered. -func (s *BaseNumscriptListener) EnterDestInorder(ctx *DestInorderContext) {} - -// ExitDestInorder is called when production destInorder is exited. -func (s *BaseNumscriptListener) ExitDestInorder(ctx *DestInorderContext) {} - -// EnterAllotmentClauseDest is called when production allotmentClauseDest is entered. -func (s *BaseNumscriptListener) EnterAllotmentClauseDest(ctx *AllotmentClauseDestContext) {} - -// ExitAllotmentClauseDest is called when production allotmentClauseDest is exited. -func (s *BaseNumscriptListener) ExitAllotmentClauseDest(ctx *AllotmentClauseDestContext) {} - -// EnterSentLiteral is called when production sentLiteral is entered. -func (s *BaseNumscriptListener) EnterSentLiteral(ctx *SentLiteralContext) {} - -// ExitSentLiteral is called when production sentLiteral is exited. -func (s *BaseNumscriptListener) ExitSentLiteral(ctx *SentLiteralContext) {} - -// EnterSentAll is called when production sentAll is entered. -func (s *BaseNumscriptListener) EnterSentAll(ctx *SentAllContext) {} - -// ExitSentAll is called when production sentAll is exited. -func (s *BaseNumscriptListener) ExitSentAll(ctx *SentAllContext) {} - -// EnterSendStatement is called when production sendStatement is entered. -func (s *BaseNumscriptListener) EnterSendStatement(ctx *SendStatementContext) {} - -// ExitSendStatement is called when production sendStatement is exited. -func (s *BaseNumscriptListener) ExitSendStatement(ctx *SendStatementContext) {} - -// EnterSaveStatement is called when production saveStatement is entered. -func (s *BaseNumscriptListener) EnterSaveStatement(ctx *SaveStatementContext) {} - -// ExitSaveStatement is called when production saveStatement is exited. -func (s *BaseNumscriptListener) ExitSaveStatement(ctx *SaveStatementContext) {} - -// EnterFnCallStatement is called when production fnCallStatement is entered. -func (s *BaseNumscriptListener) EnterFnCallStatement(ctx *FnCallStatementContext) {} - -// ExitFnCallStatement is called when production fnCallStatement is exited. -func (s *BaseNumscriptListener) ExitFnCallStatement(ctx *FnCallStatementContext) {} diff --git a/internal/parser/antlr/numscript_lexer.go b/internal/parser/antlr/numscript_lexer.go deleted file mode 100644 index 2b86925..0000000 --- a/internal/parser/antlr/numscript_lexer.go +++ /dev/null @@ -1,295 +0,0 @@ -// Code generated from Numscript.g4 by ANTLR 4.13.1. DO NOT EDIT. - -package parser - -import ( - "fmt" - "github.com/antlr4-go/antlr/v4" - "sync" - "unicode" -) - -// Suppress unused import error -var _ = fmt.Printf -var _ = sync.Once{} -var _ = unicode.IsLetter - -type NumscriptLexer struct { - *antlr.BaseLexer - channelNames []string - modeNames []string - // TODO: EOF string -} - -var NumscriptLexerLexerStaticData struct { - once sync.Once - serializedATN []int32 - ChannelNames []string - ModeNames []string - LiteralNames []string - SymbolicNames []string - RuleNames []string - PredictionContextCache *antlr.PredictionContextCache - atn *antlr.ATN - decisionToDFA []*antlr.DFA -} - -func numscriptlexerLexerInit() { - staticData := &NumscriptLexerLexerStaticData - staticData.ChannelNames = []string{ - "DEFAULT_TOKEN_CHANNEL", "HIDDEN", - } - staticData.ModeNames = []string{ - "DEFAULT_MODE", - } - staticData.LiteralNames = []string{ - "", "'+'", "", "", "", "", "'vars'", "'max'", "'source'", "'destination'", - "'send'", "'from'", "'up'", "'to'", "'remaining'", "'allowing'", "'unbounded'", - "'overdraft'", "'kept'", "'save'", "'('", "')'", "'['", "']'", "'{'", - "'}'", "','", "'='", "'*'", "'-'", - } - staticData.SymbolicNames = []string{ - "", "", "WS", "NEWLINE", "MULTILINE_COMMENT", "LINE_COMMENT", "VARS", - "MAX", "SOURCE", "DESTINATION", "SEND", "FROM", "UP", "TO", "REMAINING", - "ALLOWING", "UNBOUNDED", "OVERDRAFT", "KEPT", "SAVE", "LPARENS", "RPARENS", - "LBRACKET", "RBRACKET", "LBRACE", "RBRACE", "COMMA", "EQ", "STAR", "MINUS", - "RATIO_PORTION_LITERAL", "PERCENTAGE_PORTION_LITERAL", "STRING", "IDENTIFIER", - "NUMBER", "VARIABLE_NAME", "ACCOUNT", "ASSET", - } - staticData.RuleNames = []string{ - "T__0", "WS", "NEWLINE", "MULTILINE_COMMENT", "LINE_COMMENT", "VARS", - "MAX", "SOURCE", "DESTINATION", "SEND", "FROM", "UP", "TO", "REMAINING", - "ALLOWING", "UNBOUNDED", "OVERDRAFT", "KEPT", "SAVE", "LPARENS", "RPARENS", - "LBRACKET", "RBRACKET", "LBRACE", "RBRACE", "COMMA", "EQ", "STAR", "MINUS", - "RATIO_PORTION_LITERAL", "PERCENTAGE_PORTION_LITERAL", "STRING", "IDENTIFIER", - "NUMBER", "VARIABLE_NAME", "ACCOUNT", "ASSET", - } - staticData.PredictionContextCache = antlr.NewPredictionContextCache() - staticData.serializedATN = []int32{ - 4, 0, 37, 326, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, - 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, - 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, - 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, - 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, - 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, - 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, - 7, 36, 1, 0, 1, 0, 1, 1, 4, 1, 79, 8, 1, 11, 1, 12, 1, 80, 1, 1, 1, 1, - 1, 2, 4, 2, 86, 8, 2, 11, 2, 12, 2, 87, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 5, - 3, 95, 8, 3, 10, 3, 12, 3, 98, 9, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, - 1, 4, 1, 4, 1, 4, 5, 4, 109, 8, 4, 10, 4, 12, 4, 112, 9, 4, 1, 4, 1, 4, - 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, - 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, - 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, - 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, - 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, - 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, - 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, - 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, - 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, - 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, - 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 4, 29, 232, 8, 29, 11, 29, - 12, 29, 233, 1, 29, 3, 29, 237, 8, 29, 1, 29, 1, 29, 3, 29, 241, 8, 29, - 1, 29, 4, 29, 244, 8, 29, 11, 29, 12, 29, 245, 1, 30, 4, 30, 249, 8, 30, - 11, 30, 12, 30, 250, 1, 30, 1, 30, 4, 30, 255, 8, 30, 11, 30, 12, 30, 256, - 3, 30, 259, 8, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 267, - 8, 31, 10, 31, 12, 31, 270, 9, 31, 1, 31, 1, 31, 1, 32, 4, 32, 275, 8, - 32, 11, 32, 12, 32, 276, 1, 32, 5, 32, 280, 8, 32, 10, 32, 12, 32, 283, - 9, 32, 1, 33, 3, 33, 286, 8, 33, 1, 33, 4, 33, 289, 8, 33, 11, 33, 12, - 33, 290, 1, 34, 1, 34, 4, 34, 295, 8, 34, 11, 34, 12, 34, 296, 1, 34, 5, - 34, 300, 8, 34, 10, 34, 12, 34, 303, 9, 34, 1, 35, 1, 35, 4, 35, 307, 8, - 35, 11, 35, 12, 35, 308, 1, 35, 1, 35, 4, 35, 313, 8, 35, 11, 35, 12, 35, - 314, 5, 35, 317, 8, 35, 10, 35, 12, 35, 320, 9, 35, 1, 36, 4, 36, 323, - 8, 36, 11, 36, 12, 36, 324, 2, 96, 110, 0, 37, 1, 1, 3, 2, 5, 3, 7, 4, - 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, - 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, - 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, - 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 1, 0, 10, 3, 0, 9, 10, 13, 13, - 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 1, 0, 32, 32, 3, 0, 10, 10, - 13, 13, 34, 34, 1, 0, 97, 122, 2, 0, 95, 95, 97, 122, 3, 0, 48, 57, 95, - 95, 97, 122, 5, 0, 45, 45, 48, 57, 65, 90, 95, 95, 97, 122, 2, 0, 47, 57, - 65, 90, 349, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, - 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, - 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, - 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, - 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, - 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, - 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, - 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, - 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, - 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 1, 75, 1, 0, 0, - 0, 3, 78, 1, 0, 0, 0, 5, 85, 1, 0, 0, 0, 7, 89, 1, 0, 0, 0, 9, 104, 1, - 0, 0, 0, 11, 117, 1, 0, 0, 0, 13, 122, 1, 0, 0, 0, 15, 126, 1, 0, 0, 0, - 17, 133, 1, 0, 0, 0, 19, 145, 1, 0, 0, 0, 21, 150, 1, 0, 0, 0, 23, 155, - 1, 0, 0, 0, 25, 158, 1, 0, 0, 0, 27, 161, 1, 0, 0, 0, 29, 171, 1, 0, 0, - 0, 31, 180, 1, 0, 0, 0, 33, 190, 1, 0, 0, 0, 35, 200, 1, 0, 0, 0, 37, 205, - 1, 0, 0, 0, 39, 210, 1, 0, 0, 0, 41, 212, 1, 0, 0, 0, 43, 214, 1, 0, 0, - 0, 45, 216, 1, 0, 0, 0, 47, 218, 1, 0, 0, 0, 49, 220, 1, 0, 0, 0, 51, 222, - 1, 0, 0, 0, 53, 224, 1, 0, 0, 0, 55, 226, 1, 0, 0, 0, 57, 228, 1, 0, 0, - 0, 59, 231, 1, 0, 0, 0, 61, 248, 1, 0, 0, 0, 63, 262, 1, 0, 0, 0, 65, 274, - 1, 0, 0, 0, 67, 285, 1, 0, 0, 0, 69, 292, 1, 0, 0, 0, 71, 304, 1, 0, 0, - 0, 73, 322, 1, 0, 0, 0, 75, 76, 5, 43, 0, 0, 76, 2, 1, 0, 0, 0, 77, 79, - 7, 0, 0, 0, 78, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 78, 1, 0, 0, 0, - 80, 81, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 83, 6, 1, 0, 0, 83, 4, 1, 0, - 0, 0, 84, 86, 7, 1, 0, 0, 85, 84, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 85, - 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 6, 1, 0, 0, 0, 89, 90, 5, 47, 0, 0, - 90, 91, 5, 42, 0, 0, 91, 96, 1, 0, 0, 0, 92, 95, 3, 7, 3, 0, 93, 95, 9, - 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 93, 1, 0, 0, 0, 95, 98, 1, 0, 0, 0, 96, - 97, 1, 0, 0, 0, 96, 94, 1, 0, 0, 0, 97, 99, 1, 0, 0, 0, 98, 96, 1, 0, 0, - 0, 99, 100, 5, 42, 0, 0, 100, 101, 5, 47, 0, 0, 101, 102, 1, 0, 0, 0, 102, - 103, 6, 3, 0, 0, 103, 8, 1, 0, 0, 0, 104, 105, 5, 47, 0, 0, 105, 106, 5, - 47, 0, 0, 106, 110, 1, 0, 0, 0, 107, 109, 9, 0, 0, 0, 108, 107, 1, 0, 0, - 0, 109, 112, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 111, - 113, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 3, 5, 2, 0, 114, 115, - 1, 0, 0, 0, 115, 116, 6, 4, 0, 0, 116, 10, 1, 0, 0, 0, 117, 118, 5, 118, - 0, 0, 118, 119, 5, 97, 0, 0, 119, 120, 5, 114, 0, 0, 120, 121, 5, 115, - 0, 0, 121, 12, 1, 0, 0, 0, 122, 123, 5, 109, 0, 0, 123, 124, 5, 97, 0, - 0, 124, 125, 5, 120, 0, 0, 125, 14, 1, 0, 0, 0, 126, 127, 5, 115, 0, 0, - 127, 128, 5, 111, 0, 0, 128, 129, 5, 117, 0, 0, 129, 130, 5, 114, 0, 0, - 130, 131, 5, 99, 0, 0, 131, 132, 5, 101, 0, 0, 132, 16, 1, 0, 0, 0, 133, - 134, 5, 100, 0, 0, 134, 135, 5, 101, 0, 0, 135, 136, 5, 115, 0, 0, 136, - 137, 5, 116, 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 110, 0, 0, 139, - 140, 5, 97, 0, 0, 140, 141, 5, 116, 0, 0, 141, 142, 5, 105, 0, 0, 142, - 143, 5, 111, 0, 0, 143, 144, 5, 110, 0, 0, 144, 18, 1, 0, 0, 0, 145, 146, - 5, 115, 0, 0, 146, 147, 5, 101, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, - 5, 100, 0, 0, 149, 20, 1, 0, 0, 0, 150, 151, 5, 102, 0, 0, 151, 152, 5, - 114, 0, 0, 152, 153, 5, 111, 0, 0, 153, 154, 5, 109, 0, 0, 154, 22, 1, - 0, 0, 0, 155, 156, 5, 117, 0, 0, 156, 157, 5, 112, 0, 0, 157, 24, 1, 0, - 0, 0, 158, 159, 5, 116, 0, 0, 159, 160, 5, 111, 0, 0, 160, 26, 1, 0, 0, - 0, 161, 162, 5, 114, 0, 0, 162, 163, 5, 101, 0, 0, 163, 164, 5, 109, 0, - 0, 164, 165, 5, 97, 0, 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 110, 0, - 0, 167, 168, 5, 105, 0, 0, 168, 169, 5, 110, 0, 0, 169, 170, 5, 103, 0, - 0, 170, 28, 1, 0, 0, 0, 171, 172, 5, 97, 0, 0, 172, 173, 5, 108, 0, 0, - 173, 174, 5, 108, 0, 0, 174, 175, 5, 111, 0, 0, 175, 176, 5, 119, 0, 0, - 176, 177, 5, 105, 0, 0, 177, 178, 5, 110, 0, 0, 178, 179, 5, 103, 0, 0, - 179, 30, 1, 0, 0, 0, 180, 181, 5, 117, 0, 0, 181, 182, 5, 110, 0, 0, 182, - 183, 5, 98, 0, 0, 183, 184, 5, 111, 0, 0, 184, 185, 5, 117, 0, 0, 185, - 186, 5, 110, 0, 0, 186, 187, 5, 100, 0, 0, 187, 188, 5, 101, 0, 0, 188, - 189, 5, 100, 0, 0, 189, 32, 1, 0, 0, 0, 190, 191, 5, 111, 0, 0, 191, 192, - 5, 118, 0, 0, 192, 193, 5, 101, 0, 0, 193, 194, 5, 114, 0, 0, 194, 195, - 5, 100, 0, 0, 195, 196, 5, 114, 0, 0, 196, 197, 5, 97, 0, 0, 197, 198, - 5, 102, 0, 0, 198, 199, 5, 116, 0, 0, 199, 34, 1, 0, 0, 0, 200, 201, 5, - 107, 0, 0, 201, 202, 5, 101, 0, 0, 202, 203, 5, 112, 0, 0, 203, 204, 5, - 116, 0, 0, 204, 36, 1, 0, 0, 0, 205, 206, 5, 115, 0, 0, 206, 207, 5, 97, - 0, 0, 207, 208, 5, 118, 0, 0, 208, 209, 5, 101, 0, 0, 209, 38, 1, 0, 0, - 0, 210, 211, 5, 40, 0, 0, 211, 40, 1, 0, 0, 0, 212, 213, 5, 41, 0, 0, 213, - 42, 1, 0, 0, 0, 214, 215, 5, 91, 0, 0, 215, 44, 1, 0, 0, 0, 216, 217, 5, - 93, 0, 0, 217, 46, 1, 0, 0, 0, 218, 219, 5, 123, 0, 0, 219, 48, 1, 0, 0, - 0, 220, 221, 5, 125, 0, 0, 221, 50, 1, 0, 0, 0, 222, 223, 5, 44, 0, 0, - 223, 52, 1, 0, 0, 0, 224, 225, 5, 61, 0, 0, 225, 54, 1, 0, 0, 0, 226, 227, - 5, 42, 0, 0, 227, 56, 1, 0, 0, 0, 228, 229, 5, 45, 0, 0, 229, 58, 1, 0, - 0, 0, 230, 232, 7, 2, 0, 0, 231, 230, 1, 0, 0, 0, 232, 233, 1, 0, 0, 0, - 233, 231, 1, 0, 0, 0, 233, 234, 1, 0, 0, 0, 234, 236, 1, 0, 0, 0, 235, - 237, 7, 3, 0, 0, 236, 235, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, - 1, 0, 0, 0, 238, 240, 5, 47, 0, 0, 239, 241, 7, 3, 0, 0, 240, 239, 1, 0, - 0, 0, 240, 241, 1, 0, 0, 0, 241, 243, 1, 0, 0, 0, 242, 244, 7, 2, 0, 0, - 243, 242, 1, 0, 0, 0, 244, 245, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 245, - 246, 1, 0, 0, 0, 246, 60, 1, 0, 0, 0, 247, 249, 7, 2, 0, 0, 248, 247, 1, - 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, - 0, 251, 258, 1, 0, 0, 0, 252, 254, 5, 46, 0, 0, 253, 255, 7, 2, 0, 0, 254, - 253, 1, 0, 0, 0, 255, 256, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 256, 257, - 1, 0, 0, 0, 257, 259, 1, 0, 0, 0, 258, 252, 1, 0, 0, 0, 258, 259, 1, 0, - 0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 5, 37, 0, 0, 261, 62, 1, 0, 0, 0, - 262, 268, 5, 34, 0, 0, 263, 264, 5, 92, 0, 0, 264, 267, 5, 34, 0, 0, 265, - 267, 8, 4, 0, 0, 266, 263, 1, 0, 0, 0, 266, 265, 1, 0, 0, 0, 267, 270, - 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 271, 1, 0, - 0, 0, 270, 268, 1, 0, 0, 0, 271, 272, 5, 34, 0, 0, 272, 64, 1, 0, 0, 0, - 273, 275, 7, 5, 0, 0, 274, 273, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, - 274, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 281, 1, 0, 0, 0, 278, 280, - 7, 6, 0, 0, 279, 278, 1, 0, 0, 0, 280, 283, 1, 0, 0, 0, 281, 279, 1, 0, - 0, 0, 281, 282, 1, 0, 0, 0, 282, 66, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, - 284, 286, 3, 57, 28, 0, 285, 284, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, - 288, 1, 0, 0, 0, 287, 289, 7, 2, 0, 0, 288, 287, 1, 0, 0, 0, 289, 290, - 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 290, 291, 1, 0, 0, 0, 291, 68, 1, 0, - 0, 0, 292, 294, 5, 36, 0, 0, 293, 295, 7, 6, 0, 0, 294, 293, 1, 0, 0, 0, - 295, 296, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, - 301, 1, 0, 0, 0, 298, 300, 7, 7, 0, 0, 299, 298, 1, 0, 0, 0, 300, 303, - 1, 0, 0, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 70, 1, 0, - 0, 0, 303, 301, 1, 0, 0, 0, 304, 306, 5, 64, 0, 0, 305, 307, 7, 8, 0, 0, - 306, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, - 309, 1, 0, 0, 0, 309, 318, 1, 0, 0, 0, 310, 312, 5, 58, 0, 0, 311, 313, - 7, 8, 0, 0, 312, 311, 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 312, 1, 0, - 0, 0, 314, 315, 1, 0, 0, 0, 315, 317, 1, 0, 0, 0, 316, 310, 1, 0, 0, 0, - 317, 320, 1, 0, 0, 0, 318, 316, 1, 0, 0, 0, 318, 319, 1, 0, 0, 0, 319, - 72, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 321, 323, 7, 9, 0, 0, 322, 321, 1, - 0, 0, 0, 323, 324, 1, 0, 0, 0, 324, 322, 1, 0, 0, 0, 324, 325, 1, 0, 0, - 0, 325, 74, 1, 0, 0, 0, 25, 0, 80, 87, 94, 96, 110, 233, 236, 240, 245, - 250, 256, 258, 266, 268, 276, 281, 285, 290, 296, 301, 308, 314, 318, 324, - 1, 6, 0, 0, - } - deserializer := antlr.NewATNDeserializer(nil) - staticData.atn = deserializer.Deserialize(staticData.serializedATN) - atn := staticData.atn - staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) - decisionToDFA := staticData.decisionToDFA - for index, state := range atn.DecisionToState { - decisionToDFA[index] = antlr.NewDFA(state, index) - } -} - -// NumscriptLexerInit initializes any static state used to implement NumscriptLexer. By default the -// static state used to implement the lexer is lazily initialized during the first call to -// NewNumscriptLexer(). You can call this function if you wish to initialize the static state ahead -// of time. -func NumscriptLexerInit() { - staticData := &NumscriptLexerLexerStaticData - staticData.once.Do(numscriptlexerLexerInit) -} - -// NewNumscriptLexer produces a new lexer instance for the optional input antlr.CharStream. -func NewNumscriptLexer(input antlr.CharStream) *NumscriptLexer { - NumscriptLexerInit() - l := new(NumscriptLexer) - l.BaseLexer = antlr.NewBaseLexer(input) - staticData := &NumscriptLexerLexerStaticData - l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) - l.channelNames = staticData.ChannelNames - l.modeNames = staticData.ModeNames - l.RuleNames = staticData.RuleNames - l.LiteralNames = staticData.LiteralNames - l.SymbolicNames = staticData.SymbolicNames - l.GrammarFileName = "Numscript.g4" - // TODO: l.EOF = antlr.TokenEOF - - return l -} - -// NumscriptLexer tokens. -const ( - NumscriptLexerT__0 = 1 - NumscriptLexerWS = 2 - NumscriptLexerNEWLINE = 3 - NumscriptLexerMULTILINE_COMMENT = 4 - NumscriptLexerLINE_COMMENT = 5 - NumscriptLexerVARS = 6 - NumscriptLexerMAX = 7 - NumscriptLexerSOURCE = 8 - NumscriptLexerDESTINATION = 9 - NumscriptLexerSEND = 10 - NumscriptLexerFROM = 11 - NumscriptLexerUP = 12 - NumscriptLexerTO = 13 - NumscriptLexerREMAINING = 14 - NumscriptLexerALLOWING = 15 - NumscriptLexerUNBOUNDED = 16 - NumscriptLexerOVERDRAFT = 17 - NumscriptLexerKEPT = 18 - NumscriptLexerSAVE = 19 - NumscriptLexerLPARENS = 20 - NumscriptLexerRPARENS = 21 - NumscriptLexerLBRACKET = 22 - NumscriptLexerRBRACKET = 23 - NumscriptLexerLBRACE = 24 - NumscriptLexerRBRACE = 25 - NumscriptLexerCOMMA = 26 - NumscriptLexerEQ = 27 - NumscriptLexerSTAR = 28 - NumscriptLexerMINUS = 29 - NumscriptLexerRATIO_PORTION_LITERAL = 30 - NumscriptLexerPERCENTAGE_PORTION_LITERAL = 31 - NumscriptLexerSTRING = 32 - NumscriptLexerIDENTIFIER = 33 - NumscriptLexerNUMBER = 34 - NumscriptLexerVARIABLE_NAME = 35 - NumscriptLexerACCOUNT = 36 - NumscriptLexerASSET = 37 -) diff --git a/internal/parser/antlr/numscript_listener.go b/internal/parser/antlr/numscript_listener.go deleted file mode 100644 index e90c9e7..0000000 --- a/internal/parser/antlr/numscript_listener.go +++ /dev/null @@ -1,249 +0,0 @@ -// Code generated from Numscript.g4 by ANTLR 4.13.1. DO NOT EDIT. - -package parser // Numscript -import "github.com/antlr4-go/antlr/v4" - -// NumscriptListener is a complete listener for a parse tree produced by NumscriptParser. -type NumscriptListener interface { - antlr.ParseTreeListener - - // EnterMonetaryLit is called when entering the monetaryLit production. - EnterMonetaryLit(c *MonetaryLitContext) - - // EnterRatio is called when entering the ratio production. - EnterRatio(c *RatioContext) - - // EnterPercentage is called when entering the percentage production. - EnterPercentage(c *PercentageContext) - - // EnterVariableExpr is called when entering the variableExpr production. - EnterVariableExpr(c *VariableExprContext) - - // EnterPortionLiteral is called when entering the portionLiteral production. - EnterPortionLiteral(c *PortionLiteralContext) - - // EnterInfixExpr is called when entering the infixExpr production. - EnterInfixExpr(c *InfixExprContext) - - // EnterAssetLiteral is called when entering the assetLiteral production. - EnterAssetLiteral(c *AssetLiteralContext) - - // EnterStringLiteral is called when entering the stringLiteral production. - EnterStringLiteral(c *StringLiteralContext) - - // EnterAccountLiteral is called when entering the accountLiteral production. - EnterAccountLiteral(c *AccountLiteralContext) - - // EnterMonetaryLiteral is called when entering the monetaryLiteral production. - EnterMonetaryLiteral(c *MonetaryLiteralContext) - - // EnterNumberLiteral is called when entering the numberLiteral production. - EnterNumberLiteral(c *NumberLiteralContext) - - // EnterFunctionCallArgs is called when entering the functionCallArgs production. - EnterFunctionCallArgs(c *FunctionCallArgsContext) - - // EnterFunctionCall is called when entering the functionCall production. - EnterFunctionCall(c *FunctionCallContext) - - // EnterVarOrigin is called when entering the varOrigin production. - EnterVarOrigin(c *VarOriginContext) - - // EnterVarDeclaration is called when entering the varDeclaration production. - EnterVarDeclaration(c *VarDeclarationContext) - - // EnterVarsDeclaration is called when entering the varsDeclaration production. - EnterVarsDeclaration(c *VarsDeclarationContext) - - // EnterProgram is called when entering the program production. - EnterProgram(c *ProgramContext) - - // EnterSentAllLit is called when entering the sentAllLit production. - EnterSentAllLit(c *SentAllLitContext) - - // EnterPortionedAllotment is called when entering the portionedAllotment production. - EnterPortionedAllotment(c *PortionedAllotmentContext) - - // EnterPortionVariable is called when entering the portionVariable production. - EnterPortionVariable(c *PortionVariableContext) - - // EnterRemainingAllotment is called when entering the remainingAllotment production. - EnterRemainingAllotment(c *RemainingAllotmentContext) - - // EnterSrcAccountUnboundedOverdraft is called when entering the srcAccountUnboundedOverdraft production. - EnterSrcAccountUnboundedOverdraft(c *SrcAccountUnboundedOverdraftContext) - - // EnterSrcAccountBoundedOverdraft is called when entering the srcAccountBoundedOverdraft production. - EnterSrcAccountBoundedOverdraft(c *SrcAccountBoundedOverdraftContext) - - // EnterSrcAccount is called when entering the srcAccount production. - EnterSrcAccount(c *SrcAccountContext) - - // EnterSrcAllotment is called when entering the srcAllotment production. - EnterSrcAllotment(c *SrcAllotmentContext) - - // EnterSrcInorder is called when entering the srcInorder production. - EnterSrcInorder(c *SrcInorderContext) - - // EnterSrcCapped is called when entering the srcCapped production. - EnterSrcCapped(c *SrcCappedContext) - - // EnterAllotmentClauseSrc is called when entering the allotmentClauseSrc production. - EnterAllotmentClauseSrc(c *AllotmentClauseSrcContext) - - // EnterDestinationTo is called when entering the destinationTo production. - EnterDestinationTo(c *DestinationToContext) - - // EnterDestinationKept is called when entering the destinationKept production. - EnterDestinationKept(c *DestinationKeptContext) - - // EnterDestinationInOrderClause is called when entering the destinationInOrderClause production. - EnterDestinationInOrderClause(c *DestinationInOrderClauseContext) - - // EnterDestAccount is called when entering the destAccount production. - EnterDestAccount(c *DestAccountContext) - - // EnterDestAllotment is called when entering the destAllotment production. - EnterDestAllotment(c *DestAllotmentContext) - - // EnterDestInorder is called when entering the destInorder production. - EnterDestInorder(c *DestInorderContext) - - // EnterAllotmentClauseDest is called when entering the allotmentClauseDest production. - EnterAllotmentClauseDest(c *AllotmentClauseDestContext) - - // EnterSentLiteral is called when entering the sentLiteral production. - EnterSentLiteral(c *SentLiteralContext) - - // EnterSentAll is called when entering the sentAll production. - EnterSentAll(c *SentAllContext) - - // EnterSendStatement is called when entering the sendStatement production. - EnterSendStatement(c *SendStatementContext) - - // EnterSaveStatement is called when entering the saveStatement production. - EnterSaveStatement(c *SaveStatementContext) - - // EnterFnCallStatement is called when entering the fnCallStatement production. - EnterFnCallStatement(c *FnCallStatementContext) - - // ExitMonetaryLit is called when exiting the monetaryLit production. - ExitMonetaryLit(c *MonetaryLitContext) - - // ExitRatio is called when exiting the ratio production. - ExitRatio(c *RatioContext) - - // ExitPercentage is called when exiting the percentage production. - ExitPercentage(c *PercentageContext) - - // ExitVariableExpr is called when exiting the variableExpr production. - ExitVariableExpr(c *VariableExprContext) - - // ExitPortionLiteral is called when exiting the portionLiteral production. - ExitPortionLiteral(c *PortionLiteralContext) - - // ExitInfixExpr is called when exiting the infixExpr production. - ExitInfixExpr(c *InfixExprContext) - - // ExitAssetLiteral is called when exiting the assetLiteral production. - ExitAssetLiteral(c *AssetLiteralContext) - - // ExitStringLiteral is called when exiting the stringLiteral production. - ExitStringLiteral(c *StringLiteralContext) - - // ExitAccountLiteral is called when exiting the accountLiteral production. - ExitAccountLiteral(c *AccountLiteralContext) - - // ExitMonetaryLiteral is called when exiting the monetaryLiteral production. - ExitMonetaryLiteral(c *MonetaryLiteralContext) - - // ExitNumberLiteral is called when exiting the numberLiteral production. - ExitNumberLiteral(c *NumberLiteralContext) - - // ExitFunctionCallArgs is called when exiting the functionCallArgs production. - ExitFunctionCallArgs(c *FunctionCallArgsContext) - - // ExitFunctionCall is called when exiting the functionCall production. - ExitFunctionCall(c *FunctionCallContext) - - // ExitVarOrigin is called when exiting the varOrigin production. - ExitVarOrigin(c *VarOriginContext) - - // ExitVarDeclaration is called when exiting the varDeclaration production. - ExitVarDeclaration(c *VarDeclarationContext) - - // ExitVarsDeclaration is called when exiting the varsDeclaration production. - ExitVarsDeclaration(c *VarsDeclarationContext) - - // ExitProgram is called when exiting the program production. - ExitProgram(c *ProgramContext) - - // ExitSentAllLit is called when exiting the sentAllLit production. - ExitSentAllLit(c *SentAllLitContext) - - // ExitPortionedAllotment is called when exiting the portionedAllotment production. - ExitPortionedAllotment(c *PortionedAllotmentContext) - - // ExitPortionVariable is called when exiting the portionVariable production. - ExitPortionVariable(c *PortionVariableContext) - - // ExitRemainingAllotment is called when exiting the remainingAllotment production. - ExitRemainingAllotment(c *RemainingAllotmentContext) - - // ExitSrcAccountUnboundedOverdraft is called when exiting the srcAccountUnboundedOverdraft production. - ExitSrcAccountUnboundedOverdraft(c *SrcAccountUnboundedOverdraftContext) - - // ExitSrcAccountBoundedOverdraft is called when exiting the srcAccountBoundedOverdraft production. - ExitSrcAccountBoundedOverdraft(c *SrcAccountBoundedOverdraftContext) - - // ExitSrcAccount is called when exiting the srcAccount production. - ExitSrcAccount(c *SrcAccountContext) - - // ExitSrcAllotment is called when exiting the srcAllotment production. - ExitSrcAllotment(c *SrcAllotmentContext) - - // ExitSrcInorder is called when exiting the srcInorder production. - ExitSrcInorder(c *SrcInorderContext) - - // ExitSrcCapped is called when exiting the srcCapped production. - ExitSrcCapped(c *SrcCappedContext) - - // ExitAllotmentClauseSrc is called when exiting the allotmentClauseSrc production. - ExitAllotmentClauseSrc(c *AllotmentClauseSrcContext) - - // ExitDestinationTo is called when exiting the destinationTo production. - ExitDestinationTo(c *DestinationToContext) - - // ExitDestinationKept is called when exiting the destinationKept production. - ExitDestinationKept(c *DestinationKeptContext) - - // ExitDestinationInOrderClause is called when exiting the destinationInOrderClause production. - ExitDestinationInOrderClause(c *DestinationInOrderClauseContext) - - // ExitDestAccount is called when exiting the destAccount production. - ExitDestAccount(c *DestAccountContext) - - // ExitDestAllotment is called when exiting the destAllotment production. - ExitDestAllotment(c *DestAllotmentContext) - - // ExitDestInorder is called when exiting the destInorder production. - ExitDestInorder(c *DestInorderContext) - - // ExitAllotmentClauseDest is called when exiting the allotmentClauseDest production. - ExitAllotmentClauseDest(c *AllotmentClauseDestContext) - - // ExitSentLiteral is called when exiting the sentLiteral production. - ExitSentLiteral(c *SentLiteralContext) - - // ExitSentAll is called when exiting the sentAll production. - ExitSentAll(c *SentAllContext) - - // ExitSendStatement is called when exiting the sendStatement production. - ExitSendStatement(c *SendStatementContext) - - // ExitSaveStatement is called when exiting the saveStatement production. - ExitSaveStatement(c *SaveStatementContext) - - // ExitFnCallStatement is called when exiting the fnCallStatement production. - ExitFnCallStatement(c *FnCallStatementContext) -} diff --git a/internal/parser/antlr/numscript_parser.go b/internal/parser/antlr/numscript_parser.go deleted file mode 100644 index 66d52fc..0000000 --- a/internal/parser/antlr/numscript_parser.go +++ /dev/null @@ -1,4939 +0,0 @@ -// Code generated from Numscript.g4 by ANTLR 4.13.1. DO NOT EDIT. - -package parser // Numscript -import ( - "fmt" - "strconv" - "sync" - - "github.com/antlr4-go/antlr/v4" -) - -// Suppress unused import errors -var _ = fmt.Printf -var _ = strconv.Itoa -var _ = sync.Once{} - -type NumscriptParser struct { - *antlr.BaseParser -} - -var NumscriptParserStaticData struct { - once sync.Once - serializedATN []int32 - LiteralNames []string - SymbolicNames []string - RuleNames []string - PredictionContextCache *antlr.PredictionContextCache - atn *antlr.ATN - decisionToDFA []*antlr.DFA -} - -func numscriptParserInit() { - staticData := &NumscriptParserStaticData - staticData.LiteralNames = []string{ - "", "'+'", "", "", "", "", "'vars'", "'max'", "'source'", "'destination'", - "'send'", "'from'", "'up'", "'to'", "'remaining'", "'allowing'", "'unbounded'", - "'overdraft'", "'kept'", "'save'", "'('", "')'", "'['", "']'", "'{'", - "'}'", "','", "'='", "'*'", "'-'", - } - staticData.SymbolicNames = []string{ - "", "", "WS", "NEWLINE", "MULTILINE_COMMENT", "LINE_COMMENT", "VARS", - "MAX", "SOURCE", "DESTINATION", "SEND", "FROM", "UP", "TO", "REMAINING", - "ALLOWING", "UNBOUNDED", "OVERDRAFT", "KEPT", "SAVE", "LPARENS", "RPARENS", - "LBRACKET", "RBRACKET", "LBRACE", "RBRACE", "COMMA", "EQ", "STAR", "MINUS", - "RATIO_PORTION_LITERAL", "PERCENTAGE_PORTION_LITERAL", "STRING", "IDENTIFIER", - "NUMBER", "VARIABLE_NAME", "ACCOUNT", "ASSET", - } - staticData.RuleNames = []string{ - "monetaryLit", "portion", "valueExpr", "functionCallArgs", "functionCall", - "varOrigin", "varDeclaration", "varsDeclaration", "program", "sentAllLit", - "allotment", "source", "allotmentClauseSrc", "keptOrDestination", "destinationInOrderClause", - "destination", "allotmentClauseDest", "sentValue", "statement", - } - staticData.PredictionContextCache = antlr.NewPredictionContextCache() - staticData.serializedATN = []int32{ - 4, 1, 37, 217, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, - 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, - 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, - 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 1, 3, 1, 46, 8, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, - 2, 3, 2, 56, 8, 2, 1, 2, 1, 2, 1, 2, 5, 2, 61, 8, 2, 10, 2, 12, 2, 64, - 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 69, 8, 3, 10, 3, 12, 3, 72, 9, 3, 1, 4, 1, - 4, 1, 4, 3, 4, 77, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, - 3, 6, 87, 8, 6, 1, 7, 1, 7, 1, 7, 5, 7, 92, 8, 7, 10, 7, 12, 7, 95, 9, - 7, 1, 7, 1, 7, 1, 8, 3, 8, 100, 8, 8, 1, 8, 5, 8, 103, 8, 8, 10, 8, 12, - 8, 106, 9, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, - 10, 3, 10, 118, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, - 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 4, 11, 135, 8, - 11, 11, 11, 12, 11, 136, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 143, 8, 11, - 10, 11, 12, 11, 146, 9, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 3, - 11, 154, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 3, 13, - 163, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 4, 15, 172, - 8, 15, 11, 15, 12, 15, 173, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 180, 8, - 15, 10, 15, 12, 15, 183, 9, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 189, - 8, 15, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 196, 8, 17, 1, 18, 1, - 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, - 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 215, 8, 18, 1, 18, 0, 1, 4, 19, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, - 0, 1, 2, 0, 1, 1, 29, 29, 228, 0, 38, 1, 0, 0, 0, 2, 45, 1, 0, 0, 0, 4, - 55, 1, 0, 0, 0, 6, 65, 1, 0, 0, 0, 8, 73, 1, 0, 0, 0, 10, 80, 1, 0, 0, - 0, 12, 83, 1, 0, 0, 0, 14, 88, 1, 0, 0, 0, 16, 99, 1, 0, 0, 0, 18, 109, - 1, 0, 0, 0, 20, 117, 1, 0, 0, 0, 22, 153, 1, 0, 0, 0, 24, 155, 1, 0, 0, - 0, 26, 162, 1, 0, 0, 0, 28, 164, 1, 0, 0, 0, 30, 188, 1, 0, 0, 0, 32, 190, - 1, 0, 0, 0, 34, 195, 1, 0, 0, 0, 36, 214, 1, 0, 0, 0, 38, 39, 5, 22, 0, - 0, 39, 40, 3, 4, 2, 0, 40, 41, 3, 4, 2, 0, 41, 42, 5, 23, 0, 0, 42, 1, - 1, 0, 0, 0, 43, 46, 5, 30, 0, 0, 44, 46, 5, 31, 0, 0, 45, 43, 1, 0, 0, - 0, 45, 44, 1, 0, 0, 0, 46, 3, 1, 0, 0, 0, 47, 48, 6, 2, -1, 0, 48, 56, - 5, 35, 0, 0, 49, 56, 5, 37, 0, 0, 50, 56, 5, 32, 0, 0, 51, 56, 5, 36, 0, - 0, 52, 56, 5, 34, 0, 0, 53, 56, 3, 0, 0, 0, 54, 56, 3, 2, 1, 0, 55, 47, - 1, 0, 0, 0, 55, 49, 1, 0, 0, 0, 55, 50, 1, 0, 0, 0, 55, 51, 1, 0, 0, 0, - 55, 52, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 55, 54, 1, 0, 0, 0, 56, 62, 1, - 0, 0, 0, 57, 58, 10, 1, 0, 0, 58, 59, 7, 0, 0, 0, 59, 61, 3, 4, 2, 2, 60, - 57, 1, 0, 0, 0, 61, 64, 1, 0, 0, 0, 62, 60, 1, 0, 0, 0, 62, 63, 1, 0, 0, - 0, 63, 5, 1, 0, 0, 0, 64, 62, 1, 0, 0, 0, 65, 70, 3, 4, 2, 0, 66, 67, 5, - 26, 0, 0, 67, 69, 3, 4, 2, 0, 68, 66, 1, 0, 0, 0, 69, 72, 1, 0, 0, 0, 70, - 68, 1, 0, 0, 0, 70, 71, 1, 0, 0, 0, 71, 7, 1, 0, 0, 0, 72, 70, 1, 0, 0, - 0, 73, 74, 5, 33, 0, 0, 74, 76, 5, 20, 0, 0, 75, 77, 3, 6, 3, 0, 76, 75, - 1, 0, 0, 0, 76, 77, 1, 0, 0, 0, 77, 78, 1, 0, 0, 0, 78, 79, 5, 21, 0, 0, - 79, 9, 1, 0, 0, 0, 80, 81, 5, 27, 0, 0, 81, 82, 3, 8, 4, 0, 82, 11, 1, - 0, 0, 0, 83, 84, 5, 33, 0, 0, 84, 86, 5, 35, 0, 0, 85, 87, 3, 10, 5, 0, - 86, 85, 1, 0, 0, 0, 86, 87, 1, 0, 0, 0, 87, 13, 1, 0, 0, 0, 88, 89, 5, - 6, 0, 0, 89, 93, 5, 24, 0, 0, 90, 92, 3, 12, 6, 0, 91, 90, 1, 0, 0, 0, - 92, 95, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 96, 1, - 0, 0, 0, 95, 93, 1, 0, 0, 0, 96, 97, 5, 25, 0, 0, 97, 15, 1, 0, 0, 0, 98, - 100, 3, 14, 7, 0, 99, 98, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 104, 1, - 0, 0, 0, 101, 103, 3, 36, 18, 0, 102, 101, 1, 0, 0, 0, 103, 106, 1, 0, - 0, 0, 104, 102, 1, 0, 0, 0, 104, 105, 1, 0, 0, 0, 105, 107, 1, 0, 0, 0, - 106, 104, 1, 0, 0, 0, 107, 108, 5, 0, 0, 1, 108, 17, 1, 0, 0, 0, 109, 110, - 5, 22, 0, 0, 110, 111, 3, 4, 2, 0, 111, 112, 5, 28, 0, 0, 112, 113, 5, - 23, 0, 0, 113, 19, 1, 0, 0, 0, 114, 118, 3, 2, 1, 0, 115, 118, 5, 35, 0, - 0, 116, 118, 5, 14, 0, 0, 117, 114, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 117, - 116, 1, 0, 0, 0, 118, 21, 1, 0, 0, 0, 119, 120, 3, 4, 2, 0, 120, 121, 5, - 15, 0, 0, 121, 122, 5, 16, 0, 0, 122, 123, 5, 17, 0, 0, 123, 154, 1, 0, - 0, 0, 124, 125, 3, 4, 2, 0, 125, 126, 5, 15, 0, 0, 126, 127, 5, 17, 0, - 0, 127, 128, 5, 12, 0, 0, 128, 129, 5, 13, 0, 0, 129, 130, 3, 4, 2, 0, - 130, 154, 1, 0, 0, 0, 131, 154, 3, 4, 2, 0, 132, 134, 5, 24, 0, 0, 133, - 135, 3, 24, 12, 0, 134, 133, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 134, - 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 138, 1, 0, 0, 0, 138, 139, 5, 25, - 0, 0, 139, 154, 1, 0, 0, 0, 140, 144, 5, 24, 0, 0, 141, 143, 3, 22, 11, - 0, 142, 141, 1, 0, 0, 0, 143, 146, 1, 0, 0, 0, 144, 142, 1, 0, 0, 0, 144, - 145, 1, 0, 0, 0, 145, 147, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 147, 154, - 5, 25, 0, 0, 148, 149, 5, 7, 0, 0, 149, 150, 3, 4, 2, 0, 150, 151, 5, 11, - 0, 0, 151, 152, 3, 22, 11, 0, 152, 154, 1, 0, 0, 0, 153, 119, 1, 0, 0, - 0, 153, 124, 1, 0, 0, 0, 153, 131, 1, 0, 0, 0, 153, 132, 1, 0, 0, 0, 153, - 140, 1, 0, 0, 0, 153, 148, 1, 0, 0, 0, 154, 23, 1, 0, 0, 0, 155, 156, 3, - 20, 10, 0, 156, 157, 5, 11, 0, 0, 157, 158, 3, 22, 11, 0, 158, 25, 1, 0, - 0, 0, 159, 160, 5, 13, 0, 0, 160, 163, 3, 30, 15, 0, 161, 163, 5, 18, 0, - 0, 162, 159, 1, 0, 0, 0, 162, 161, 1, 0, 0, 0, 163, 27, 1, 0, 0, 0, 164, - 165, 5, 7, 0, 0, 165, 166, 3, 4, 2, 0, 166, 167, 3, 26, 13, 0, 167, 29, - 1, 0, 0, 0, 168, 189, 3, 4, 2, 0, 169, 171, 5, 24, 0, 0, 170, 172, 3, 32, - 16, 0, 171, 170, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 173, 171, 1, 0, 0, 0, - 173, 174, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 176, 5, 25, 0, 0, 176, - 189, 1, 0, 0, 0, 177, 181, 5, 24, 0, 0, 178, 180, 3, 28, 14, 0, 179, 178, - 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, - 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 185, 5, 14, 0, 0, - 185, 186, 3, 26, 13, 0, 186, 187, 5, 25, 0, 0, 187, 189, 1, 0, 0, 0, 188, - 168, 1, 0, 0, 0, 188, 169, 1, 0, 0, 0, 188, 177, 1, 0, 0, 0, 189, 31, 1, - 0, 0, 0, 190, 191, 3, 20, 10, 0, 191, 192, 3, 26, 13, 0, 192, 33, 1, 0, - 0, 0, 193, 196, 3, 4, 2, 0, 194, 196, 3, 18, 9, 0, 195, 193, 1, 0, 0, 0, - 195, 194, 1, 0, 0, 0, 196, 35, 1, 0, 0, 0, 197, 198, 5, 10, 0, 0, 198, - 199, 3, 34, 17, 0, 199, 200, 5, 20, 0, 0, 200, 201, 5, 8, 0, 0, 201, 202, - 5, 27, 0, 0, 202, 203, 3, 22, 11, 0, 203, 204, 5, 9, 0, 0, 204, 205, 5, - 27, 0, 0, 205, 206, 3, 30, 15, 0, 206, 207, 5, 21, 0, 0, 207, 215, 1, 0, - 0, 0, 208, 209, 5, 19, 0, 0, 209, 210, 3, 34, 17, 0, 210, 211, 5, 11, 0, - 0, 211, 212, 3, 4, 2, 0, 212, 215, 1, 0, 0, 0, 213, 215, 3, 8, 4, 0, 214, - 197, 1, 0, 0, 0, 214, 208, 1, 0, 0, 0, 214, 213, 1, 0, 0, 0, 215, 37, 1, - 0, 0, 0, 19, 45, 55, 62, 70, 76, 86, 93, 99, 104, 117, 136, 144, 153, 162, - 173, 181, 188, 195, 214, - } - deserializer := antlr.NewATNDeserializer(nil) - staticData.atn = deserializer.Deserialize(staticData.serializedATN) - atn := staticData.atn - staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState)) - decisionToDFA := staticData.decisionToDFA - for index, state := range atn.DecisionToState { - decisionToDFA[index] = antlr.NewDFA(state, index) - } -} - -// NumscriptParserInit initializes any static state used to implement NumscriptParser. By default the -// static state used to implement the parser is lazily initialized during the first call to -// NewNumscriptParser(). You can call this function if you wish to initialize the static state ahead -// of time. -func NumscriptParserInit() { - staticData := &NumscriptParserStaticData - staticData.once.Do(numscriptParserInit) -} - -// NewNumscriptParser produces a new parser instance for the optional input antlr.TokenStream. -func NewNumscriptParser(input antlr.TokenStream) *NumscriptParser { - NumscriptParserInit() - this := new(NumscriptParser) - this.BaseParser = antlr.NewBaseParser(input) - staticData := &NumscriptParserStaticData - this.Interpreter = antlr.NewParserATNSimulator(this, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache) - this.RuleNames = staticData.RuleNames - this.LiteralNames = staticData.LiteralNames - this.SymbolicNames = staticData.SymbolicNames - this.GrammarFileName = "Numscript.g4" - - return this -} - -// NumscriptParser tokens. -const ( - NumscriptParserEOF = antlr.TokenEOF - NumscriptParserT__0 = 1 - NumscriptParserWS = 2 - NumscriptParserNEWLINE = 3 - NumscriptParserMULTILINE_COMMENT = 4 - NumscriptParserLINE_COMMENT = 5 - NumscriptParserVARS = 6 - NumscriptParserMAX = 7 - NumscriptParserSOURCE = 8 - NumscriptParserDESTINATION = 9 - NumscriptParserSEND = 10 - NumscriptParserFROM = 11 - NumscriptParserUP = 12 - NumscriptParserTO = 13 - NumscriptParserREMAINING = 14 - NumscriptParserALLOWING = 15 - NumscriptParserUNBOUNDED = 16 - NumscriptParserOVERDRAFT = 17 - NumscriptParserKEPT = 18 - NumscriptParserSAVE = 19 - NumscriptParserLPARENS = 20 - NumscriptParserRPARENS = 21 - NumscriptParserLBRACKET = 22 - NumscriptParserRBRACKET = 23 - NumscriptParserLBRACE = 24 - NumscriptParserRBRACE = 25 - NumscriptParserCOMMA = 26 - NumscriptParserEQ = 27 - NumscriptParserSTAR = 28 - NumscriptParserMINUS = 29 - NumscriptParserRATIO_PORTION_LITERAL = 30 - NumscriptParserPERCENTAGE_PORTION_LITERAL = 31 - NumscriptParserSTRING = 32 - NumscriptParserIDENTIFIER = 33 - NumscriptParserNUMBER = 34 - NumscriptParserVARIABLE_NAME = 35 - NumscriptParserACCOUNT = 36 - NumscriptParserASSET = 37 -) - -// NumscriptParser rules. -const ( - NumscriptParserRULE_monetaryLit = 0 - NumscriptParserRULE_portion = 1 - NumscriptParserRULE_valueExpr = 2 - NumscriptParserRULE_functionCallArgs = 3 - NumscriptParserRULE_functionCall = 4 - NumscriptParserRULE_varOrigin = 5 - NumscriptParserRULE_varDeclaration = 6 - NumscriptParserRULE_varsDeclaration = 7 - NumscriptParserRULE_program = 8 - NumscriptParserRULE_sentAllLit = 9 - NumscriptParserRULE_allotment = 10 - NumscriptParserRULE_source = 11 - NumscriptParserRULE_allotmentClauseSrc = 12 - NumscriptParserRULE_keptOrDestination = 13 - NumscriptParserRULE_destinationInOrderClause = 14 - NumscriptParserRULE_destination = 15 - NumscriptParserRULE_allotmentClauseDest = 16 - NumscriptParserRULE_sentValue = 17 - NumscriptParserRULE_statement = 18 -) - -// IMonetaryLitContext is an interface to support dynamic dispatch. -type IMonetaryLitContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // GetAsset returns the asset rule contexts. - GetAsset() IValueExprContext - - // GetAmt returns the amt rule contexts. - GetAmt() IValueExprContext - - // SetAsset sets the asset rule contexts. - SetAsset(IValueExprContext) - - // SetAmt sets the amt rule contexts. - SetAmt(IValueExprContext) - - // Getter signatures - LBRACKET() antlr.TerminalNode - RBRACKET() antlr.TerminalNode - AllValueExpr() []IValueExprContext - ValueExpr(i int) IValueExprContext - - // IsMonetaryLitContext differentiates from other interfaces. - IsMonetaryLitContext() -} - -type MonetaryLitContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser - asset IValueExprContext - amt IValueExprContext -} - -func NewEmptyMonetaryLitContext() *MonetaryLitContext { - var p = new(MonetaryLitContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_monetaryLit - return p -} - -func InitEmptyMonetaryLitContext(p *MonetaryLitContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_monetaryLit -} - -func (*MonetaryLitContext) IsMonetaryLitContext() {} - -func NewMonetaryLitContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *MonetaryLitContext { - var p = new(MonetaryLitContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_monetaryLit - - return p -} - -func (s *MonetaryLitContext) GetParser() antlr.Parser { return s.parser } - -func (s *MonetaryLitContext) GetAsset() IValueExprContext { return s.asset } - -func (s *MonetaryLitContext) GetAmt() IValueExprContext { return s.amt } - -func (s *MonetaryLitContext) SetAsset(v IValueExprContext) { s.asset = v } - -func (s *MonetaryLitContext) SetAmt(v IValueExprContext) { s.amt = v } - -func (s *MonetaryLitContext) LBRACKET() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACKET, 0) -} - -func (s *MonetaryLitContext) RBRACKET() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACKET, 0) -} - -func (s *MonetaryLitContext) AllValueExpr() []IValueExprContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IValueExprContext); ok { - len++ - } - } - - tst := make([]IValueExprContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IValueExprContext); ok { - tst[i] = t.(IValueExprContext) - i++ - } - } - - return tst -} - -func (s *MonetaryLitContext) ValueExpr(i int) IValueExprContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *MonetaryLitContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *MonetaryLitContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *MonetaryLitContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterMonetaryLit(s) - } -} - -func (s *MonetaryLitContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitMonetaryLit(s) - } -} - -func (p *NumscriptParser) MonetaryLit() (localctx IMonetaryLitContext) { - localctx = NewMonetaryLitContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 0, NumscriptParserRULE_monetaryLit) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(38) - p.Match(NumscriptParserLBRACKET) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - { - p.SetState(39) - - var _x = p.valueExpr(0) - - localctx.(*MonetaryLitContext).asset = _x - } - - { - p.SetState(40) - - var _x = p.valueExpr(0) - - localctx.(*MonetaryLitContext).amt = _x - } - - { - p.SetState(41) - p.Match(NumscriptParserRBRACKET) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IPortionContext is an interface to support dynamic dispatch. -type IPortionContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsPortionContext differentiates from other interfaces. - IsPortionContext() -} - -type PortionContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyPortionContext() *PortionContext { - var p = new(PortionContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_portion - return p -} - -func InitEmptyPortionContext(p *PortionContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_portion -} - -func (*PortionContext) IsPortionContext() {} - -func NewPortionContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *PortionContext { - var p = new(PortionContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_portion - - return p -} - -func (s *PortionContext) GetParser() antlr.Parser { return s.parser } - -func (s *PortionContext) CopyAll(ctx *PortionContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *PortionContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *PortionContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type PercentageContext struct { - PortionContext -} - -func NewPercentageContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *PercentageContext { - var p = new(PercentageContext) - - InitEmptyPortionContext(&p.PortionContext) - p.parser = parser - p.CopyAll(ctx.(*PortionContext)) - - return p -} - -func (s *PercentageContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *PercentageContext) PERCENTAGE_PORTION_LITERAL() antlr.TerminalNode { - return s.GetToken(NumscriptParserPERCENTAGE_PORTION_LITERAL, 0) -} - -func (s *PercentageContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterPercentage(s) - } -} - -func (s *PercentageContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitPercentage(s) - } -} - -type RatioContext struct { - PortionContext -} - -func NewRatioContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *RatioContext { - var p = new(RatioContext) - - InitEmptyPortionContext(&p.PortionContext) - p.parser = parser - p.CopyAll(ctx.(*PortionContext)) - - return p -} - -func (s *RatioContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *RatioContext) RATIO_PORTION_LITERAL() antlr.TerminalNode { - return s.GetToken(NumscriptParserRATIO_PORTION_LITERAL, 0) -} - -func (s *RatioContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterRatio(s) - } -} - -func (s *RatioContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitRatio(s) - } -} - -func (p *NumscriptParser) Portion() (localctx IPortionContext) { - localctx = NewPortionContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 2, NumscriptParserRULE_portion) - p.SetState(45) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetTokenStream().LA(1) { - case NumscriptParserRATIO_PORTION_LITERAL: - localctx = NewRatioContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(43) - p.Match(NumscriptParserRATIO_PORTION_LITERAL) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserPERCENTAGE_PORTION_LITERAL: - localctx = NewPercentageContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(44) - p.Match(NumscriptParserPERCENTAGE_PORTION_LITERAL) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - default: - p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IValueExprContext is an interface to support dynamic dispatch. -type IValueExprContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsValueExprContext differentiates from other interfaces. - IsValueExprContext() -} - -type ValueExprContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyValueExprContext() *ValueExprContext { - var p = new(ValueExprContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_valueExpr - return p -} - -func InitEmptyValueExprContext(p *ValueExprContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_valueExpr -} - -func (*ValueExprContext) IsValueExprContext() {} - -func NewValueExprContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ValueExprContext { - var p = new(ValueExprContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_valueExpr - - return p -} - -func (s *ValueExprContext) GetParser() antlr.Parser { return s.parser } - -func (s *ValueExprContext) CopyAll(ctx *ValueExprContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *ValueExprContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *ValueExprContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type VariableExprContext struct { - ValueExprContext -} - -func NewVariableExprContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *VariableExprContext { - var p = new(VariableExprContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *VariableExprContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *VariableExprContext) VARIABLE_NAME() antlr.TerminalNode { - return s.GetToken(NumscriptParserVARIABLE_NAME, 0) -} - -func (s *VariableExprContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterVariableExpr(s) - } -} - -func (s *VariableExprContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitVariableExpr(s) - } -} - -type PortionLiteralContext struct { - ValueExprContext -} - -func NewPortionLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *PortionLiteralContext { - var p = new(PortionLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *PortionLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *PortionLiteralContext) Portion() IPortionContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IPortionContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IPortionContext) -} - -func (s *PortionLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterPortionLiteral(s) - } -} - -func (s *PortionLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitPortionLiteral(s) - } -} - -type InfixExprContext struct { - ValueExprContext - left IValueExprContext - op antlr.Token - right IValueExprContext -} - -func NewInfixExprContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *InfixExprContext { - var p = new(InfixExprContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *InfixExprContext) GetOp() antlr.Token { return s.op } - -func (s *InfixExprContext) SetOp(v antlr.Token) { s.op = v } - -func (s *InfixExprContext) GetLeft() IValueExprContext { return s.left } - -func (s *InfixExprContext) GetRight() IValueExprContext { return s.right } - -func (s *InfixExprContext) SetLeft(v IValueExprContext) { s.left = v } - -func (s *InfixExprContext) SetRight(v IValueExprContext) { s.right = v } - -func (s *InfixExprContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *InfixExprContext) AllValueExpr() []IValueExprContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IValueExprContext); ok { - len++ - } - } - - tst := make([]IValueExprContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IValueExprContext); ok { - tst[i] = t.(IValueExprContext) - i++ - } - } - - return tst -} - -func (s *InfixExprContext) ValueExpr(i int) IValueExprContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *InfixExprContext) MINUS() antlr.TerminalNode { - return s.GetToken(NumscriptParserMINUS, 0) -} - -func (s *InfixExprContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterInfixExpr(s) - } -} - -func (s *InfixExprContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitInfixExpr(s) - } -} - -type AssetLiteralContext struct { - ValueExprContext -} - -func NewAssetLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *AssetLiteralContext { - var p = new(AssetLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *AssetLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *AssetLiteralContext) ASSET() antlr.TerminalNode { - return s.GetToken(NumscriptParserASSET, 0) -} - -func (s *AssetLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterAssetLiteral(s) - } -} - -func (s *AssetLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitAssetLiteral(s) - } -} - -type StringLiteralContext struct { - ValueExprContext -} - -func NewStringLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *StringLiteralContext { - var p = new(StringLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *StringLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *StringLiteralContext) STRING() antlr.TerminalNode { - return s.GetToken(NumscriptParserSTRING, 0) -} - -func (s *StringLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterStringLiteral(s) - } -} - -func (s *StringLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitStringLiteral(s) - } -} - -type AccountLiteralContext struct { - ValueExprContext -} - -func NewAccountLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *AccountLiteralContext { - var p = new(AccountLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *AccountLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *AccountLiteralContext) ACCOUNT() antlr.TerminalNode { - return s.GetToken(NumscriptParserACCOUNT, 0) -} - -func (s *AccountLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterAccountLiteral(s) - } -} - -func (s *AccountLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitAccountLiteral(s) - } -} - -type MonetaryLiteralContext struct { - ValueExprContext -} - -func NewMonetaryLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *MonetaryLiteralContext { - var p = new(MonetaryLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *MonetaryLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *MonetaryLiteralContext) MonetaryLit() IMonetaryLitContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IMonetaryLitContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IMonetaryLitContext) -} - -func (s *MonetaryLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterMonetaryLiteral(s) - } -} - -func (s *MonetaryLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitMonetaryLiteral(s) - } -} - -type NumberLiteralContext struct { - ValueExprContext -} - -func NewNumberLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *NumberLiteralContext { - var p = new(NumberLiteralContext) - - InitEmptyValueExprContext(&p.ValueExprContext) - p.parser = parser - p.CopyAll(ctx.(*ValueExprContext)) - - return p -} - -func (s *NumberLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *NumberLiteralContext) NUMBER() antlr.TerminalNode { - return s.GetToken(NumscriptParserNUMBER, 0) -} - -func (s *NumberLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterNumberLiteral(s) - } -} - -func (s *NumberLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitNumberLiteral(s) - } -} - -func (p *NumscriptParser) ValueExpr() (localctx IValueExprContext) { - return p.valueExpr(0) -} - -func (p *NumscriptParser) valueExpr(_p int) (localctx IValueExprContext) { - var _parentctx antlr.ParserRuleContext = p.GetParserRuleContext() - - _parentState := p.GetState() - localctx = NewValueExprContext(p, p.GetParserRuleContext(), _parentState) - var _prevctx IValueExprContext = localctx - var _ antlr.ParserRuleContext = _prevctx // TODO: To prevent unused variable warning. - _startState := 4 - p.EnterRecursionRule(localctx, 4, NumscriptParserRULE_valueExpr, _p) - var _la int - - var _alt int - - p.EnterOuterAlt(localctx, 1) - p.SetState(55) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetTokenStream().LA(1) { - case NumscriptParserVARIABLE_NAME: - localctx = NewVariableExprContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - - { - p.SetState(48) - p.Match(NumscriptParserVARIABLE_NAME) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserASSET: - localctx = NewAssetLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(49) - p.Match(NumscriptParserASSET) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserSTRING: - localctx = NewStringLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(50) - p.Match(NumscriptParserSTRING) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserACCOUNT: - localctx = NewAccountLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(51) - p.Match(NumscriptParserACCOUNT) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserNUMBER: - localctx = NewNumberLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(52) - p.Match(NumscriptParserNUMBER) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserLBRACKET: - localctx = NewMonetaryLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(53) - p.MonetaryLit() - } - - case NumscriptParserRATIO_PORTION_LITERAL, NumscriptParserPERCENTAGE_PORTION_LITERAL: - localctx = NewPortionLiteralContext(p, localctx) - p.SetParserRuleContext(localctx) - _prevctx = localctx - { - p.SetState(54) - p.Portion() - } - - default: - p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) - goto errorExit - } - p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) - p.SetState(62) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 2, p.GetParserRuleContext()) - if p.HasError() { - goto errorExit - } - for _alt != 2 && _alt != antlr.ATNInvalidAltNumber { - if _alt == 1 { - if p.GetParseListeners() != nil { - p.TriggerExitRuleEvent() - } - _prevctx = localctx - localctx = NewInfixExprContext(p, NewValueExprContext(p, _parentctx, _parentState)) - localctx.(*InfixExprContext).left = _prevctx - - p.PushNewRecursionContext(localctx, _startState, NumscriptParserRULE_valueExpr) - p.SetState(57) - - if !(p.Precpred(p.GetParserRuleContext(), 1)) { - p.SetError(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 1)", "")) - goto errorExit - } - { - p.SetState(58) - - var _lt = p.GetTokenStream().LT(1) - - localctx.(*InfixExprContext).op = _lt - - _la = p.GetTokenStream().LA(1) - - if !(_la == NumscriptParserT__0 || _la == NumscriptParserMINUS) { - var _ri = p.GetErrorHandler().RecoverInline(p) - - localctx.(*InfixExprContext).op = _ri - } else { - p.GetErrorHandler().ReportMatch(p) - p.Consume() - } - } - { - p.SetState(59) - - var _x = p.valueExpr(2) - - localctx.(*InfixExprContext).right = _x - } - - } - p.SetState(64) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 2, p.GetParserRuleContext()) - if p.HasError() { - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.UnrollRecursionContexts(_parentctx) - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IFunctionCallArgsContext is an interface to support dynamic dispatch. -type IFunctionCallArgsContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - AllValueExpr() []IValueExprContext - ValueExpr(i int) IValueExprContext - AllCOMMA() []antlr.TerminalNode - COMMA(i int) antlr.TerminalNode - - // IsFunctionCallArgsContext differentiates from other interfaces. - IsFunctionCallArgsContext() -} - -type FunctionCallArgsContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyFunctionCallArgsContext() *FunctionCallArgsContext { - var p = new(FunctionCallArgsContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_functionCallArgs - return p -} - -func InitEmptyFunctionCallArgsContext(p *FunctionCallArgsContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_functionCallArgs -} - -func (*FunctionCallArgsContext) IsFunctionCallArgsContext() {} - -func NewFunctionCallArgsContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FunctionCallArgsContext { - var p = new(FunctionCallArgsContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_functionCallArgs - - return p -} - -func (s *FunctionCallArgsContext) GetParser() antlr.Parser { return s.parser } - -func (s *FunctionCallArgsContext) AllValueExpr() []IValueExprContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IValueExprContext); ok { - len++ - } - } - - tst := make([]IValueExprContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IValueExprContext); ok { - tst[i] = t.(IValueExprContext) - i++ - } - } - - return tst -} - -func (s *FunctionCallArgsContext) ValueExpr(i int) IValueExprContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *FunctionCallArgsContext) AllCOMMA() []antlr.TerminalNode { - return s.GetTokens(NumscriptParserCOMMA) -} - -func (s *FunctionCallArgsContext) COMMA(i int) antlr.TerminalNode { - return s.GetToken(NumscriptParserCOMMA, i) -} - -func (s *FunctionCallArgsContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *FunctionCallArgsContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *FunctionCallArgsContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterFunctionCallArgs(s) - } -} - -func (s *FunctionCallArgsContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitFunctionCallArgs(s) - } -} - -func (p *NumscriptParser) FunctionCallArgs() (localctx IFunctionCallArgsContext) { - localctx = NewFunctionCallArgsContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 6, NumscriptParserRULE_functionCallArgs) - var _la int - - p.EnterOuterAlt(localctx, 1) - { - p.SetState(65) - p.valueExpr(0) - } - p.SetState(70) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for _la == NumscriptParserCOMMA { - { - p.SetState(66) - p.Match(NumscriptParserCOMMA) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(67) - p.valueExpr(0) - } - - p.SetState(72) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IFunctionCallContext is an interface to support dynamic dispatch. -type IFunctionCallContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - IDENTIFIER() antlr.TerminalNode - LPARENS() antlr.TerminalNode - RPARENS() antlr.TerminalNode - FunctionCallArgs() IFunctionCallArgsContext - - // IsFunctionCallContext differentiates from other interfaces. - IsFunctionCallContext() -} - -type FunctionCallContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyFunctionCallContext() *FunctionCallContext { - var p = new(FunctionCallContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_functionCall - return p -} - -func InitEmptyFunctionCallContext(p *FunctionCallContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_functionCall -} - -func (*FunctionCallContext) IsFunctionCallContext() {} - -func NewFunctionCallContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *FunctionCallContext { - var p = new(FunctionCallContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_functionCall - - return p -} - -func (s *FunctionCallContext) GetParser() antlr.Parser { return s.parser } - -func (s *FunctionCallContext) IDENTIFIER() antlr.TerminalNode { - return s.GetToken(NumscriptParserIDENTIFIER, 0) -} - -func (s *FunctionCallContext) LPARENS() antlr.TerminalNode { - return s.GetToken(NumscriptParserLPARENS, 0) -} - -func (s *FunctionCallContext) RPARENS() antlr.TerminalNode { - return s.GetToken(NumscriptParserRPARENS, 0) -} - -func (s *FunctionCallContext) FunctionCallArgs() IFunctionCallArgsContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IFunctionCallArgsContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IFunctionCallArgsContext) -} - -func (s *FunctionCallContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *FunctionCallContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *FunctionCallContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterFunctionCall(s) - } -} - -func (s *FunctionCallContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitFunctionCall(s) - } -} - -func (p *NumscriptParser) FunctionCall() (localctx IFunctionCallContext) { - localctx = NewFunctionCallContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 8, NumscriptParserRULE_functionCall) - var _la int - - p.EnterOuterAlt(localctx, 1) - { - p.SetState(73) - p.Match(NumscriptParserIDENTIFIER) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(74) - p.Match(NumscriptParserLPARENS) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(76) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - if (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&265218424832) != 0 { - { - p.SetState(75) - p.FunctionCallArgs() - } - - } - { - p.SetState(78) - p.Match(NumscriptParserRPARENS) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IVarOriginContext is an interface to support dynamic dispatch. -type IVarOriginContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - EQ() antlr.TerminalNode - FunctionCall() IFunctionCallContext - - // IsVarOriginContext differentiates from other interfaces. - IsVarOriginContext() -} - -type VarOriginContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyVarOriginContext() *VarOriginContext { - var p = new(VarOriginContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varOrigin - return p -} - -func InitEmptyVarOriginContext(p *VarOriginContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varOrigin -} - -func (*VarOriginContext) IsVarOriginContext() {} - -func NewVarOriginContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *VarOriginContext { - var p = new(VarOriginContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_varOrigin - - return p -} - -func (s *VarOriginContext) GetParser() antlr.Parser { return s.parser } - -func (s *VarOriginContext) EQ() antlr.TerminalNode { - return s.GetToken(NumscriptParserEQ, 0) -} - -func (s *VarOriginContext) FunctionCall() IFunctionCallContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IFunctionCallContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IFunctionCallContext) -} - -func (s *VarOriginContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *VarOriginContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *VarOriginContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterVarOrigin(s) - } -} - -func (s *VarOriginContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitVarOrigin(s) - } -} - -func (p *NumscriptParser) VarOrigin() (localctx IVarOriginContext) { - localctx = NewVarOriginContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 10, NumscriptParserRULE_varOrigin) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(80) - p.Match(NumscriptParserEQ) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(81) - p.FunctionCall() - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IVarDeclarationContext is an interface to support dynamic dispatch. -type IVarDeclarationContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // GetType_ returns the type_ token. - GetType_() antlr.Token - - // GetName returns the name token. - GetName() antlr.Token - - // SetType_ sets the type_ token. - SetType_(antlr.Token) - - // SetName sets the name token. - SetName(antlr.Token) - - // Getter signatures - IDENTIFIER() antlr.TerminalNode - VARIABLE_NAME() antlr.TerminalNode - VarOrigin() IVarOriginContext - - // IsVarDeclarationContext differentiates from other interfaces. - IsVarDeclarationContext() -} - -type VarDeclarationContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser - type_ antlr.Token - name antlr.Token -} - -func NewEmptyVarDeclarationContext() *VarDeclarationContext { - var p = new(VarDeclarationContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varDeclaration - return p -} - -func InitEmptyVarDeclarationContext(p *VarDeclarationContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varDeclaration -} - -func (*VarDeclarationContext) IsVarDeclarationContext() {} - -func NewVarDeclarationContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *VarDeclarationContext { - var p = new(VarDeclarationContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_varDeclaration - - return p -} - -func (s *VarDeclarationContext) GetParser() antlr.Parser { return s.parser } - -func (s *VarDeclarationContext) GetType_() antlr.Token { return s.type_ } - -func (s *VarDeclarationContext) GetName() antlr.Token { return s.name } - -func (s *VarDeclarationContext) SetType_(v antlr.Token) { s.type_ = v } - -func (s *VarDeclarationContext) SetName(v antlr.Token) { s.name = v } - -func (s *VarDeclarationContext) IDENTIFIER() antlr.TerminalNode { - return s.GetToken(NumscriptParserIDENTIFIER, 0) -} - -func (s *VarDeclarationContext) VARIABLE_NAME() antlr.TerminalNode { - return s.GetToken(NumscriptParserVARIABLE_NAME, 0) -} - -func (s *VarDeclarationContext) VarOrigin() IVarOriginContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IVarOriginContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IVarOriginContext) -} - -func (s *VarDeclarationContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *VarDeclarationContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *VarDeclarationContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterVarDeclaration(s) - } -} - -func (s *VarDeclarationContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitVarDeclaration(s) - } -} - -func (p *NumscriptParser) VarDeclaration() (localctx IVarDeclarationContext) { - localctx = NewVarDeclarationContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 12, NumscriptParserRULE_varDeclaration) - var _la int - - p.EnterOuterAlt(localctx, 1) - { - p.SetState(83) - - var _m = p.Match(NumscriptParserIDENTIFIER) - - localctx.(*VarDeclarationContext).type_ = _m - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(84) - - var _m = p.Match(NumscriptParserVARIABLE_NAME) - - localctx.(*VarDeclarationContext).name = _m - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(86) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - if _la == NumscriptParserEQ { - { - p.SetState(85) - p.VarOrigin() - } - - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IVarsDeclarationContext is an interface to support dynamic dispatch. -type IVarsDeclarationContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - VARS() antlr.TerminalNode - LBRACE() antlr.TerminalNode - RBRACE() antlr.TerminalNode - AllVarDeclaration() []IVarDeclarationContext - VarDeclaration(i int) IVarDeclarationContext - - // IsVarsDeclarationContext differentiates from other interfaces. - IsVarsDeclarationContext() -} - -type VarsDeclarationContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyVarsDeclarationContext() *VarsDeclarationContext { - var p = new(VarsDeclarationContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varsDeclaration - return p -} - -func InitEmptyVarsDeclarationContext(p *VarsDeclarationContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_varsDeclaration -} - -func (*VarsDeclarationContext) IsVarsDeclarationContext() {} - -func NewVarsDeclarationContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *VarsDeclarationContext { - var p = new(VarsDeclarationContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_varsDeclaration - - return p -} - -func (s *VarsDeclarationContext) GetParser() antlr.Parser { return s.parser } - -func (s *VarsDeclarationContext) VARS() antlr.TerminalNode { - return s.GetToken(NumscriptParserVARS, 0) -} - -func (s *VarsDeclarationContext) LBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACE, 0) -} - -func (s *VarsDeclarationContext) RBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACE, 0) -} - -func (s *VarsDeclarationContext) AllVarDeclaration() []IVarDeclarationContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IVarDeclarationContext); ok { - len++ - } - } - - tst := make([]IVarDeclarationContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IVarDeclarationContext); ok { - tst[i] = t.(IVarDeclarationContext) - i++ - } - } - - return tst -} - -func (s *VarsDeclarationContext) VarDeclaration(i int) IVarDeclarationContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IVarDeclarationContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IVarDeclarationContext) -} - -func (s *VarsDeclarationContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *VarsDeclarationContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *VarsDeclarationContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterVarsDeclaration(s) - } -} - -func (s *VarsDeclarationContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitVarsDeclaration(s) - } -} - -func (p *NumscriptParser) VarsDeclaration() (localctx IVarsDeclarationContext) { - localctx = NewVarsDeclarationContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 14, NumscriptParserRULE_varsDeclaration) - var _la int - - p.EnterOuterAlt(localctx, 1) - { - p.SetState(88) - p.Match(NumscriptParserVARS) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(89) - p.Match(NumscriptParserLBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(93) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for _la == NumscriptParserIDENTIFIER { - { - p.SetState(90) - p.VarDeclaration() - } - - p.SetState(95) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(96) - p.Match(NumscriptParserRBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IProgramContext is an interface to support dynamic dispatch. -type IProgramContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - EOF() antlr.TerminalNode - VarsDeclaration() IVarsDeclarationContext - AllStatement() []IStatementContext - Statement(i int) IStatementContext - - // IsProgramContext differentiates from other interfaces. - IsProgramContext() -} - -type ProgramContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyProgramContext() *ProgramContext { - var p = new(ProgramContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_program - return p -} - -func InitEmptyProgramContext(p *ProgramContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_program -} - -func (*ProgramContext) IsProgramContext() {} - -func NewProgramContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *ProgramContext { - var p = new(ProgramContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_program - - return p -} - -func (s *ProgramContext) GetParser() antlr.Parser { return s.parser } - -func (s *ProgramContext) EOF() antlr.TerminalNode { - return s.GetToken(NumscriptParserEOF, 0) -} - -func (s *ProgramContext) VarsDeclaration() IVarsDeclarationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IVarsDeclarationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IVarsDeclarationContext) -} - -func (s *ProgramContext) AllStatement() []IStatementContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IStatementContext); ok { - len++ - } - } - - tst := make([]IStatementContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IStatementContext); ok { - tst[i] = t.(IStatementContext) - i++ - } - } - - return tst -} - -func (s *ProgramContext) Statement(i int) IStatementContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IStatementContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IStatementContext) -} - -func (s *ProgramContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *ProgramContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *ProgramContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterProgram(s) - } -} - -func (s *ProgramContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitProgram(s) - } -} - -func (p *NumscriptParser) Program() (localctx IProgramContext) { - localctx = NewProgramContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 16, NumscriptParserRULE_program) - var _la int - - p.EnterOuterAlt(localctx, 1) - p.SetState(99) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - if _la == NumscriptParserVARS { - { - p.SetState(98) - p.VarsDeclaration() - } - - } - p.SetState(104) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&8590459904) != 0 { - { - p.SetState(101) - p.Statement() - } - - p.SetState(106) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(107) - p.Match(NumscriptParserEOF) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// ISentAllLitContext is an interface to support dynamic dispatch. -type ISentAllLitContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // GetAsset returns the asset rule contexts. - GetAsset() IValueExprContext - - // SetAsset sets the asset rule contexts. - SetAsset(IValueExprContext) - - // Getter signatures - LBRACKET() antlr.TerminalNode - STAR() antlr.TerminalNode - RBRACKET() antlr.TerminalNode - ValueExpr() IValueExprContext - - // IsSentAllLitContext differentiates from other interfaces. - IsSentAllLitContext() -} - -type SentAllLitContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser - asset IValueExprContext -} - -func NewEmptySentAllLitContext() *SentAllLitContext { - var p = new(SentAllLitContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_sentAllLit - return p -} - -func InitEmptySentAllLitContext(p *SentAllLitContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_sentAllLit -} - -func (*SentAllLitContext) IsSentAllLitContext() {} - -func NewSentAllLitContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SentAllLitContext { - var p = new(SentAllLitContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_sentAllLit - - return p -} - -func (s *SentAllLitContext) GetParser() antlr.Parser { return s.parser } - -func (s *SentAllLitContext) GetAsset() IValueExprContext { return s.asset } - -func (s *SentAllLitContext) SetAsset(v IValueExprContext) { s.asset = v } - -func (s *SentAllLitContext) LBRACKET() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACKET, 0) -} - -func (s *SentAllLitContext) STAR() antlr.TerminalNode { - return s.GetToken(NumscriptParserSTAR, 0) -} - -func (s *SentAllLitContext) RBRACKET() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACKET, 0) -} - -func (s *SentAllLitContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SentAllLitContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SentAllLitContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *SentAllLitContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSentAllLit(s) - } -} - -func (s *SentAllLitContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSentAllLit(s) - } -} - -func (p *NumscriptParser) SentAllLit() (localctx ISentAllLitContext) { - localctx = NewSentAllLitContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 18, NumscriptParserRULE_sentAllLit) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(109) - p.Match(NumscriptParserLBRACKET) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - { - p.SetState(110) - - var _x = p.valueExpr(0) - - localctx.(*SentAllLitContext).asset = _x - } - - { - p.SetState(111) - p.Match(NumscriptParserSTAR) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(112) - p.Match(NumscriptParserRBRACKET) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IAllotmentContext is an interface to support dynamic dispatch. -type IAllotmentContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsAllotmentContext differentiates from other interfaces. - IsAllotmentContext() -} - -type AllotmentContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyAllotmentContext() *AllotmentContext { - var p = new(AllotmentContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotment - return p -} - -func InitEmptyAllotmentContext(p *AllotmentContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotment -} - -func (*AllotmentContext) IsAllotmentContext() {} - -func NewAllotmentContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AllotmentContext { - var p = new(AllotmentContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_allotment - - return p -} - -func (s *AllotmentContext) GetParser() antlr.Parser { return s.parser } - -func (s *AllotmentContext) CopyAll(ctx *AllotmentContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *AllotmentContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *AllotmentContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type RemainingAllotmentContext struct { - AllotmentContext -} - -func NewRemainingAllotmentContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *RemainingAllotmentContext { - var p = new(RemainingAllotmentContext) - - InitEmptyAllotmentContext(&p.AllotmentContext) - p.parser = parser - p.CopyAll(ctx.(*AllotmentContext)) - - return p -} - -func (s *RemainingAllotmentContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *RemainingAllotmentContext) REMAINING() antlr.TerminalNode { - return s.GetToken(NumscriptParserREMAINING, 0) -} - -func (s *RemainingAllotmentContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterRemainingAllotment(s) - } -} - -func (s *RemainingAllotmentContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitRemainingAllotment(s) - } -} - -type PortionedAllotmentContext struct { - AllotmentContext -} - -func NewPortionedAllotmentContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *PortionedAllotmentContext { - var p = new(PortionedAllotmentContext) - - InitEmptyAllotmentContext(&p.AllotmentContext) - p.parser = parser - p.CopyAll(ctx.(*AllotmentContext)) - - return p -} - -func (s *PortionedAllotmentContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *PortionedAllotmentContext) Portion() IPortionContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IPortionContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IPortionContext) -} - -func (s *PortionedAllotmentContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterPortionedAllotment(s) - } -} - -func (s *PortionedAllotmentContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitPortionedAllotment(s) - } -} - -type PortionVariableContext struct { - AllotmentContext -} - -func NewPortionVariableContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *PortionVariableContext { - var p = new(PortionVariableContext) - - InitEmptyAllotmentContext(&p.AllotmentContext) - p.parser = parser - p.CopyAll(ctx.(*AllotmentContext)) - - return p -} - -func (s *PortionVariableContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *PortionVariableContext) VARIABLE_NAME() antlr.TerminalNode { - return s.GetToken(NumscriptParserVARIABLE_NAME, 0) -} - -func (s *PortionVariableContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterPortionVariable(s) - } -} - -func (s *PortionVariableContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitPortionVariable(s) - } -} - -func (p *NumscriptParser) Allotment() (localctx IAllotmentContext) { - localctx = NewAllotmentContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 20, NumscriptParserRULE_allotment) - p.SetState(117) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetTokenStream().LA(1) { - case NumscriptParserRATIO_PORTION_LITERAL, NumscriptParserPERCENTAGE_PORTION_LITERAL: - localctx = NewPortionedAllotmentContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(114) - p.Portion() - } - - case NumscriptParserVARIABLE_NAME: - localctx = NewPortionVariableContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(115) - p.Match(NumscriptParserVARIABLE_NAME) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserREMAINING: - localctx = NewRemainingAllotmentContext(p, localctx) - p.EnterOuterAlt(localctx, 3) - { - p.SetState(116) - p.Match(NumscriptParserREMAINING) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - default: - p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// ISourceContext is an interface to support dynamic dispatch. -type ISourceContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsSourceContext differentiates from other interfaces. - IsSourceContext() -} - -type SourceContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptySourceContext() *SourceContext { - var p = new(SourceContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_source - return p -} - -func InitEmptySourceContext(p *SourceContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_source -} - -func (*SourceContext) IsSourceContext() {} - -func NewSourceContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SourceContext { - var p = new(SourceContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_source - - return p -} - -func (s *SourceContext) GetParser() antlr.Parser { return s.parser } - -func (s *SourceContext) CopyAll(ctx *SourceContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *SourceContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SourceContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type SrcAccountBoundedOverdraftContext struct { - SourceContext - address IValueExprContext - maxOvedraft IValueExprContext -} - -func NewSrcAccountBoundedOverdraftContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcAccountBoundedOverdraftContext { - var p = new(SrcAccountBoundedOverdraftContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcAccountBoundedOverdraftContext) GetAddress() IValueExprContext { return s.address } - -func (s *SrcAccountBoundedOverdraftContext) GetMaxOvedraft() IValueExprContext { return s.maxOvedraft } - -func (s *SrcAccountBoundedOverdraftContext) SetAddress(v IValueExprContext) { s.address = v } - -func (s *SrcAccountBoundedOverdraftContext) SetMaxOvedraft(v IValueExprContext) { s.maxOvedraft = v } - -func (s *SrcAccountBoundedOverdraftContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcAccountBoundedOverdraftContext) ALLOWING() antlr.TerminalNode { - return s.GetToken(NumscriptParserALLOWING, 0) -} - -func (s *SrcAccountBoundedOverdraftContext) OVERDRAFT() antlr.TerminalNode { - return s.GetToken(NumscriptParserOVERDRAFT, 0) -} - -func (s *SrcAccountBoundedOverdraftContext) UP() antlr.TerminalNode { - return s.GetToken(NumscriptParserUP, 0) -} - -func (s *SrcAccountBoundedOverdraftContext) TO() antlr.TerminalNode { - return s.GetToken(NumscriptParserTO, 0) -} - -func (s *SrcAccountBoundedOverdraftContext) AllValueExpr() []IValueExprContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IValueExprContext); ok { - len++ - } - } - - tst := make([]IValueExprContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IValueExprContext); ok { - tst[i] = t.(IValueExprContext) - i++ - } - } - - return tst -} - -func (s *SrcAccountBoundedOverdraftContext) ValueExpr(i int) IValueExprContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SrcAccountBoundedOverdraftContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcAccountBoundedOverdraft(s) - } -} - -func (s *SrcAccountBoundedOverdraftContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcAccountBoundedOverdraft(s) - } -} - -type SrcAccountUnboundedOverdraftContext struct { - SourceContext - address IValueExprContext -} - -func NewSrcAccountUnboundedOverdraftContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcAccountUnboundedOverdraftContext { - var p = new(SrcAccountUnboundedOverdraftContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcAccountUnboundedOverdraftContext) GetAddress() IValueExprContext { return s.address } - -func (s *SrcAccountUnboundedOverdraftContext) SetAddress(v IValueExprContext) { s.address = v } - -func (s *SrcAccountUnboundedOverdraftContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcAccountUnboundedOverdraftContext) ALLOWING() antlr.TerminalNode { - return s.GetToken(NumscriptParserALLOWING, 0) -} - -func (s *SrcAccountUnboundedOverdraftContext) UNBOUNDED() antlr.TerminalNode { - return s.GetToken(NumscriptParserUNBOUNDED, 0) -} - -func (s *SrcAccountUnboundedOverdraftContext) OVERDRAFT() antlr.TerminalNode { - return s.GetToken(NumscriptParserOVERDRAFT, 0) -} - -func (s *SrcAccountUnboundedOverdraftContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SrcAccountUnboundedOverdraftContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcAccountUnboundedOverdraft(s) - } -} - -func (s *SrcAccountUnboundedOverdraftContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcAccountUnboundedOverdraft(s) - } -} - -type SrcAllotmentContext struct { - SourceContext -} - -func NewSrcAllotmentContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcAllotmentContext { - var p = new(SrcAllotmentContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcAllotmentContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcAllotmentContext) LBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACE, 0) -} - -func (s *SrcAllotmentContext) RBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACE, 0) -} - -func (s *SrcAllotmentContext) AllAllotmentClauseSrc() []IAllotmentClauseSrcContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IAllotmentClauseSrcContext); ok { - len++ - } - } - - tst := make([]IAllotmentClauseSrcContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IAllotmentClauseSrcContext); ok { - tst[i] = t.(IAllotmentClauseSrcContext) - i++ - } - } - - return tst -} - -func (s *SrcAllotmentContext) AllotmentClauseSrc(i int) IAllotmentClauseSrcContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IAllotmentClauseSrcContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IAllotmentClauseSrcContext) -} - -func (s *SrcAllotmentContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcAllotment(s) - } -} - -func (s *SrcAllotmentContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcAllotment(s) - } -} - -type SrcInorderContext struct { - SourceContext -} - -func NewSrcInorderContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcInorderContext { - var p = new(SrcInorderContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcInorderContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcInorderContext) LBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACE, 0) -} - -func (s *SrcInorderContext) RBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACE, 0) -} - -func (s *SrcInorderContext) AllSource() []ISourceContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(ISourceContext); ok { - len++ - } - } - - tst := make([]ISourceContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(ISourceContext); ok { - tst[i] = t.(ISourceContext) - i++ - } - } - - return tst -} - -func (s *SrcInorderContext) Source(i int) ISourceContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISourceContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(ISourceContext) -} - -func (s *SrcInorderContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcInorder(s) - } -} - -func (s *SrcInorderContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcInorder(s) - } -} - -type SrcCappedContext struct { - SourceContext - cap_ IValueExprContext -} - -func NewSrcCappedContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcCappedContext { - var p = new(SrcCappedContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcCappedContext) GetCap_() IValueExprContext { return s.cap_ } - -func (s *SrcCappedContext) SetCap_(v IValueExprContext) { s.cap_ = v } - -func (s *SrcCappedContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcCappedContext) MAX() antlr.TerminalNode { - return s.GetToken(NumscriptParserMAX, 0) -} - -func (s *SrcCappedContext) FROM() antlr.TerminalNode { - return s.GetToken(NumscriptParserFROM, 0) -} - -func (s *SrcCappedContext) Source() ISourceContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISourceContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISourceContext) -} - -func (s *SrcCappedContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SrcCappedContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcCapped(s) - } -} - -func (s *SrcCappedContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcCapped(s) - } -} - -type SrcAccountContext struct { - SourceContext -} - -func NewSrcAccountContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SrcAccountContext { - var p = new(SrcAccountContext) - - InitEmptySourceContext(&p.SourceContext) - p.parser = parser - p.CopyAll(ctx.(*SourceContext)) - - return p -} - -func (s *SrcAccountContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SrcAccountContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SrcAccountContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSrcAccount(s) - } -} - -func (s *SrcAccountContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSrcAccount(s) - } -} - -func (p *NumscriptParser) Source() (localctx ISourceContext) { - localctx = NewSourceContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 22, NumscriptParserRULE_source) - var _la int - - p.SetState(153) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 12, p.GetParserRuleContext()) { - case 1: - localctx = NewSrcAccountUnboundedOverdraftContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(119) - - var _x = p.valueExpr(0) - - localctx.(*SrcAccountUnboundedOverdraftContext).address = _x - } - { - p.SetState(120) - p.Match(NumscriptParserALLOWING) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(121) - p.Match(NumscriptParserUNBOUNDED) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(122) - p.Match(NumscriptParserOVERDRAFT) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case 2: - localctx = NewSrcAccountBoundedOverdraftContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(124) - - var _x = p.valueExpr(0) - - localctx.(*SrcAccountBoundedOverdraftContext).address = _x - } - { - p.SetState(125) - p.Match(NumscriptParserALLOWING) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(126) - p.Match(NumscriptParserOVERDRAFT) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(127) - p.Match(NumscriptParserUP) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(128) - p.Match(NumscriptParserTO) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(129) - - var _x = p.valueExpr(0) - - localctx.(*SrcAccountBoundedOverdraftContext).maxOvedraft = _x - } - - case 3: - localctx = NewSrcAccountContext(p, localctx) - p.EnterOuterAlt(localctx, 3) - { - p.SetState(131) - p.valueExpr(0) - } - - case 4: - localctx = NewSrcAllotmentContext(p, localctx) - p.EnterOuterAlt(localctx, 4) - { - p.SetState(132) - p.Match(NumscriptParserLBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(134) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for ok := true; ok; ok = ((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&37580980224) != 0) { - { - p.SetState(133) - p.AllotmentClauseSrc() - } - - p.SetState(136) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(138) - p.Match(NumscriptParserRBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case 5: - localctx = NewSrcInorderContext(p, localctx) - p.EnterOuterAlt(localctx, 5) - { - p.SetState(140) - p.Match(NumscriptParserLBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(144) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for (int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&265235202176) != 0 { - { - p.SetState(141) - p.Source() - } - - p.SetState(146) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(147) - p.Match(NumscriptParserRBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case 6: - localctx = NewSrcCappedContext(p, localctx) - p.EnterOuterAlt(localctx, 6) - { - p.SetState(148) - p.Match(NumscriptParserMAX) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(149) - - var _x = p.valueExpr(0) - - localctx.(*SrcCappedContext).cap_ = _x - } - { - p.SetState(150) - p.Match(NumscriptParserFROM) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(151) - p.Source() - } - - case antlr.ATNInvalidAltNumber: - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IAllotmentClauseSrcContext is an interface to support dynamic dispatch. -type IAllotmentClauseSrcContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - Allotment() IAllotmentContext - FROM() antlr.TerminalNode - Source() ISourceContext - - // IsAllotmentClauseSrcContext differentiates from other interfaces. - IsAllotmentClauseSrcContext() -} - -type AllotmentClauseSrcContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyAllotmentClauseSrcContext() *AllotmentClauseSrcContext { - var p = new(AllotmentClauseSrcContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotmentClauseSrc - return p -} - -func InitEmptyAllotmentClauseSrcContext(p *AllotmentClauseSrcContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotmentClauseSrc -} - -func (*AllotmentClauseSrcContext) IsAllotmentClauseSrcContext() {} - -func NewAllotmentClauseSrcContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AllotmentClauseSrcContext { - var p = new(AllotmentClauseSrcContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_allotmentClauseSrc - - return p -} - -func (s *AllotmentClauseSrcContext) GetParser() antlr.Parser { return s.parser } - -func (s *AllotmentClauseSrcContext) Allotment() IAllotmentContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IAllotmentContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IAllotmentContext) -} - -func (s *AllotmentClauseSrcContext) FROM() antlr.TerminalNode { - return s.GetToken(NumscriptParserFROM, 0) -} - -func (s *AllotmentClauseSrcContext) Source() ISourceContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISourceContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISourceContext) -} - -func (s *AllotmentClauseSrcContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *AllotmentClauseSrcContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *AllotmentClauseSrcContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterAllotmentClauseSrc(s) - } -} - -func (s *AllotmentClauseSrcContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitAllotmentClauseSrc(s) - } -} - -func (p *NumscriptParser) AllotmentClauseSrc() (localctx IAllotmentClauseSrcContext) { - localctx = NewAllotmentClauseSrcContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 24, NumscriptParserRULE_allotmentClauseSrc) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(155) - p.Allotment() - } - { - p.SetState(156) - p.Match(NumscriptParserFROM) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(157) - p.Source() - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IKeptOrDestinationContext is an interface to support dynamic dispatch. -type IKeptOrDestinationContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsKeptOrDestinationContext differentiates from other interfaces. - IsKeptOrDestinationContext() -} - -type KeptOrDestinationContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyKeptOrDestinationContext() *KeptOrDestinationContext { - var p = new(KeptOrDestinationContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_keptOrDestination - return p -} - -func InitEmptyKeptOrDestinationContext(p *KeptOrDestinationContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_keptOrDestination -} - -func (*KeptOrDestinationContext) IsKeptOrDestinationContext() {} - -func NewKeptOrDestinationContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *KeptOrDestinationContext { - var p = new(KeptOrDestinationContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_keptOrDestination - - return p -} - -func (s *KeptOrDestinationContext) GetParser() antlr.Parser { return s.parser } - -func (s *KeptOrDestinationContext) CopyAll(ctx *KeptOrDestinationContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *KeptOrDestinationContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *KeptOrDestinationContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type DestinationKeptContext struct { - KeptOrDestinationContext -} - -func NewDestinationKeptContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *DestinationKeptContext { - var p = new(DestinationKeptContext) - - InitEmptyKeptOrDestinationContext(&p.KeptOrDestinationContext) - p.parser = parser - p.CopyAll(ctx.(*KeptOrDestinationContext)) - - return p -} - -func (s *DestinationKeptContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestinationKeptContext) KEPT() antlr.TerminalNode { - return s.GetToken(NumscriptParserKEPT, 0) -} - -func (s *DestinationKeptContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestinationKept(s) - } -} - -func (s *DestinationKeptContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestinationKept(s) - } -} - -type DestinationToContext struct { - KeptOrDestinationContext -} - -func NewDestinationToContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *DestinationToContext { - var p = new(DestinationToContext) - - InitEmptyKeptOrDestinationContext(&p.KeptOrDestinationContext) - p.parser = parser - p.CopyAll(ctx.(*KeptOrDestinationContext)) - - return p -} - -func (s *DestinationToContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestinationToContext) TO() antlr.TerminalNode { - return s.GetToken(NumscriptParserTO, 0) -} - -func (s *DestinationToContext) Destination() IDestinationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IDestinationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IDestinationContext) -} - -func (s *DestinationToContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestinationTo(s) - } -} - -func (s *DestinationToContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestinationTo(s) - } -} - -func (p *NumscriptParser) KeptOrDestination() (localctx IKeptOrDestinationContext) { - localctx = NewKeptOrDestinationContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 26, NumscriptParserRULE_keptOrDestination) - p.SetState(162) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetTokenStream().LA(1) { - case NumscriptParserTO: - localctx = NewDestinationToContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(159) - p.Match(NumscriptParserTO) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(160) - p.Destination() - } - - case NumscriptParserKEPT: - localctx = NewDestinationKeptContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(161) - p.Match(NumscriptParserKEPT) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - default: - p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IDestinationInOrderClauseContext is an interface to support dynamic dispatch. -type IDestinationInOrderClauseContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - MAX() antlr.TerminalNode - ValueExpr() IValueExprContext - KeptOrDestination() IKeptOrDestinationContext - - // IsDestinationInOrderClauseContext differentiates from other interfaces. - IsDestinationInOrderClauseContext() -} - -type DestinationInOrderClauseContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyDestinationInOrderClauseContext() *DestinationInOrderClauseContext { - var p = new(DestinationInOrderClauseContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_destinationInOrderClause - return p -} - -func InitEmptyDestinationInOrderClauseContext(p *DestinationInOrderClauseContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_destinationInOrderClause -} - -func (*DestinationInOrderClauseContext) IsDestinationInOrderClauseContext() {} - -func NewDestinationInOrderClauseContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *DestinationInOrderClauseContext { - var p = new(DestinationInOrderClauseContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_destinationInOrderClause - - return p -} - -func (s *DestinationInOrderClauseContext) GetParser() antlr.Parser { return s.parser } - -func (s *DestinationInOrderClauseContext) MAX() antlr.TerminalNode { - return s.GetToken(NumscriptParserMAX, 0) -} - -func (s *DestinationInOrderClauseContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *DestinationInOrderClauseContext) KeptOrDestination() IKeptOrDestinationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IKeptOrDestinationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IKeptOrDestinationContext) -} - -func (s *DestinationInOrderClauseContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestinationInOrderClauseContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *DestinationInOrderClauseContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestinationInOrderClause(s) - } -} - -func (s *DestinationInOrderClauseContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestinationInOrderClause(s) - } -} - -func (p *NumscriptParser) DestinationInOrderClause() (localctx IDestinationInOrderClauseContext) { - localctx = NewDestinationInOrderClauseContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 28, NumscriptParserRULE_destinationInOrderClause) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(164) - p.Match(NumscriptParserMAX) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(165) - p.valueExpr(0) - } - { - p.SetState(166) - p.KeptOrDestination() - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IDestinationContext is an interface to support dynamic dispatch. -type IDestinationContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsDestinationContext differentiates from other interfaces. - IsDestinationContext() -} - -type DestinationContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyDestinationContext() *DestinationContext { - var p = new(DestinationContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_destination - return p -} - -func InitEmptyDestinationContext(p *DestinationContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_destination -} - -func (*DestinationContext) IsDestinationContext() {} - -func NewDestinationContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *DestinationContext { - var p = new(DestinationContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_destination - - return p -} - -func (s *DestinationContext) GetParser() antlr.Parser { return s.parser } - -func (s *DestinationContext) CopyAll(ctx *DestinationContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *DestinationContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestinationContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type DestInorderContext struct { - DestinationContext -} - -func NewDestInorderContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *DestInorderContext { - var p = new(DestInorderContext) - - InitEmptyDestinationContext(&p.DestinationContext) - p.parser = parser - p.CopyAll(ctx.(*DestinationContext)) - - return p -} - -func (s *DestInorderContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestInorderContext) LBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACE, 0) -} - -func (s *DestInorderContext) REMAINING() antlr.TerminalNode { - return s.GetToken(NumscriptParserREMAINING, 0) -} - -func (s *DestInorderContext) KeptOrDestination() IKeptOrDestinationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IKeptOrDestinationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IKeptOrDestinationContext) -} - -func (s *DestInorderContext) RBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACE, 0) -} - -func (s *DestInorderContext) AllDestinationInOrderClause() []IDestinationInOrderClauseContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IDestinationInOrderClauseContext); ok { - len++ - } - } - - tst := make([]IDestinationInOrderClauseContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IDestinationInOrderClauseContext); ok { - tst[i] = t.(IDestinationInOrderClauseContext) - i++ - } - } - - return tst -} - -func (s *DestInorderContext) DestinationInOrderClause(i int) IDestinationInOrderClauseContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IDestinationInOrderClauseContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IDestinationInOrderClauseContext) -} - -func (s *DestInorderContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestInorder(s) - } -} - -func (s *DestInorderContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestInorder(s) - } -} - -type DestAccountContext struct { - DestinationContext -} - -func NewDestAccountContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *DestAccountContext { - var p = new(DestAccountContext) - - InitEmptyDestinationContext(&p.DestinationContext) - p.parser = parser - p.CopyAll(ctx.(*DestinationContext)) - - return p -} - -func (s *DestAccountContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestAccountContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *DestAccountContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestAccount(s) - } -} - -func (s *DestAccountContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestAccount(s) - } -} - -type DestAllotmentContext struct { - DestinationContext -} - -func NewDestAllotmentContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *DestAllotmentContext { - var p = new(DestAllotmentContext) - - InitEmptyDestinationContext(&p.DestinationContext) - p.parser = parser - p.CopyAll(ctx.(*DestinationContext)) - - return p -} - -func (s *DestAllotmentContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *DestAllotmentContext) LBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserLBRACE, 0) -} - -func (s *DestAllotmentContext) RBRACE() antlr.TerminalNode { - return s.GetToken(NumscriptParserRBRACE, 0) -} - -func (s *DestAllotmentContext) AllAllotmentClauseDest() []IAllotmentClauseDestContext { - children := s.GetChildren() - len := 0 - for _, ctx := range children { - if _, ok := ctx.(IAllotmentClauseDestContext); ok { - len++ - } - } - - tst := make([]IAllotmentClauseDestContext, len) - i := 0 - for _, ctx := range children { - if t, ok := ctx.(IAllotmentClauseDestContext); ok { - tst[i] = t.(IAllotmentClauseDestContext) - i++ - } - } - - return tst -} - -func (s *DestAllotmentContext) AllotmentClauseDest(i int) IAllotmentClauseDestContext { - var t antlr.RuleContext - j := 0 - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IAllotmentClauseDestContext); ok { - if j == i { - t = ctx.(antlr.RuleContext) - break - } - j++ - } - } - - if t == nil { - return nil - } - - return t.(IAllotmentClauseDestContext) -} - -func (s *DestAllotmentContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterDestAllotment(s) - } -} - -func (s *DestAllotmentContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitDestAllotment(s) - } -} - -func (p *NumscriptParser) Destination() (localctx IDestinationContext) { - localctx = NewDestinationContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 30, NumscriptParserRULE_destination) - var _la int - - p.SetState(188) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 16, p.GetParserRuleContext()) { - case 1: - localctx = NewDestAccountContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(168) - p.valueExpr(0) - } - - case 2: - localctx = NewDestAllotmentContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(169) - p.Match(NumscriptParserLBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(171) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for ok := true; ok; ok = ((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&37580980224) != 0) { - { - p.SetState(170) - p.AllotmentClauseDest() - } - - p.SetState(173) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(175) - p.Match(NumscriptParserRBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case 3: - localctx = NewDestInorderContext(p, localctx) - p.EnterOuterAlt(localctx, 3) - { - p.SetState(177) - p.Match(NumscriptParserLBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - p.SetState(181) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - - for _la == NumscriptParserMAX { - { - p.SetState(178) - p.DestinationInOrderClause() - } - - p.SetState(183) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - _la = p.GetTokenStream().LA(1) - } - { - p.SetState(184) - p.Match(NumscriptParserREMAINING) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(185) - p.KeptOrDestination() - } - { - p.SetState(186) - p.Match(NumscriptParserRBRACE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case antlr.ATNInvalidAltNumber: - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IAllotmentClauseDestContext is an interface to support dynamic dispatch. -type IAllotmentClauseDestContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - - // Getter signatures - Allotment() IAllotmentContext - KeptOrDestination() IKeptOrDestinationContext - - // IsAllotmentClauseDestContext differentiates from other interfaces. - IsAllotmentClauseDestContext() -} - -type AllotmentClauseDestContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyAllotmentClauseDestContext() *AllotmentClauseDestContext { - var p = new(AllotmentClauseDestContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotmentClauseDest - return p -} - -func InitEmptyAllotmentClauseDestContext(p *AllotmentClauseDestContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_allotmentClauseDest -} - -func (*AllotmentClauseDestContext) IsAllotmentClauseDestContext() {} - -func NewAllotmentClauseDestContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *AllotmentClauseDestContext { - var p = new(AllotmentClauseDestContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_allotmentClauseDest - - return p -} - -func (s *AllotmentClauseDestContext) GetParser() antlr.Parser { return s.parser } - -func (s *AllotmentClauseDestContext) Allotment() IAllotmentContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IAllotmentContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IAllotmentContext) -} - -func (s *AllotmentClauseDestContext) KeptOrDestination() IKeptOrDestinationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IKeptOrDestinationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IKeptOrDestinationContext) -} - -func (s *AllotmentClauseDestContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *AllotmentClauseDestContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -func (s *AllotmentClauseDestContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterAllotmentClauseDest(s) - } -} - -func (s *AllotmentClauseDestContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitAllotmentClauseDest(s) - } -} - -func (p *NumscriptParser) AllotmentClauseDest() (localctx IAllotmentClauseDestContext) { - localctx = NewAllotmentClauseDestContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 32, NumscriptParserRULE_allotmentClauseDest) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(190) - p.Allotment() - } - { - p.SetState(191) - p.KeptOrDestination() - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// ISentValueContext is an interface to support dynamic dispatch. -type ISentValueContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsSentValueContext differentiates from other interfaces. - IsSentValueContext() -} - -type SentValueContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptySentValueContext() *SentValueContext { - var p = new(SentValueContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_sentValue - return p -} - -func InitEmptySentValueContext(p *SentValueContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_sentValue -} - -func (*SentValueContext) IsSentValueContext() {} - -func NewSentValueContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *SentValueContext { - var p = new(SentValueContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_sentValue - - return p -} - -func (s *SentValueContext) GetParser() antlr.Parser { return s.parser } - -func (s *SentValueContext) CopyAll(ctx *SentValueContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *SentValueContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SentValueContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type SentAllContext struct { - SentValueContext -} - -func NewSentAllContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SentAllContext { - var p = new(SentAllContext) - - InitEmptySentValueContext(&p.SentValueContext) - p.parser = parser - p.CopyAll(ctx.(*SentValueContext)) - - return p -} - -func (s *SentAllContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SentAllContext) SentAllLit() ISentAllLitContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISentAllLitContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISentAllLitContext) -} - -func (s *SentAllContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSentAll(s) - } -} - -func (s *SentAllContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSentAll(s) - } -} - -type SentLiteralContext struct { - SentValueContext -} - -func NewSentLiteralContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SentLiteralContext { - var p = new(SentLiteralContext) - - InitEmptySentValueContext(&p.SentValueContext) - p.parser = parser - p.CopyAll(ctx.(*SentValueContext)) - - return p -} - -func (s *SentLiteralContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SentLiteralContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SentLiteralContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSentLiteral(s) - } -} - -func (s *SentLiteralContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSentLiteral(s) - } -} - -func (p *NumscriptParser) SentValue() (localctx ISentValueContext) { - localctx = NewSentValueContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 34, NumscriptParserRULE_sentValue) - p.SetState(195) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 17, p.GetParserRuleContext()) { - case 1: - localctx = NewSentLiteralContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(193) - p.valueExpr(0) - } - - case 2: - localctx = NewSentAllContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(194) - p.SentAllLit() - } - - case antlr.ATNInvalidAltNumber: - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -// IStatementContext is an interface to support dynamic dispatch. -type IStatementContext interface { - antlr.ParserRuleContext - - // GetParser returns the parser. - GetParser() antlr.Parser - // IsStatementContext differentiates from other interfaces. - IsStatementContext() -} - -type StatementContext struct { - antlr.BaseParserRuleContext - parser antlr.Parser -} - -func NewEmptyStatementContext() *StatementContext { - var p = new(StatementContext) - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_statement - return p -} - -func InitEmptyStatementContext(p *StatementContext) { - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, nil, -1) - p.RuleIndex = NumscriptParserRULE_statement -} - -func (*StatementContext) IsStatementContext() {} - -func NewStatementContext(parser antlr.Parser, parent antlr.ParserRuleContext, invokingState int) *StatementContext { - var p = new(StatementContext) - - antlr.InitBaseParserRuleContext(&p.BaseParserRuleContext, parent, invokingState) - - p.parser = parser - p.RuleIndex = NumscriptParserRULE_statement - - return p -} - -func (s *StatementContext) GetParser() antlr.Parser { return s.parser } - -func (s *StatementContext) CopyAll(ctx *StatementContext) { - s.CopyFrom(&ctx.BaseParserRuleContext) -} - -func (s *StatementContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *StatementContext) ToStringTree(ruleNames []string, recog antlr.Recognizer) string { - return antlr.TreesStringTree(s, ruleNames, recog) -} - -type SendStatementContext struct { - StatementContext -} - -func NewSendStatementContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SendStatementContext { - var p = new(SendStatementContext) - - InitEmptyStatementContext(&p.StatementContext) - p.parser = parser - p.CopyAll(ctx.(*StatementContext)) - - return p -} - -func (s *SendStatementContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SendStatementContext) SEND() antlr.TerminalNode { - return s.GetToken(NumscriptParserSEND, 0) -} - -func (s *SendStatementContext) SentValue() ISentValueContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISentValueContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISentValueContext) -} - -func (s *SendStatementContext) LPARENS() antlr.TerminalNode { - return s.GetToken(NumscriptParserLPARENS, 0) -} - -func (s *SendStatementContext) SOURCE() antlr.TerminalNode { - return s.GetToken(NumscriptParserSOURCE, 0) -} - -func (s *SendStatementContext) AllEQ() []antlr.TerminalNode { - return s.GetTokens(NumscriptParserEQ) -} - -func (s *SendStatementContext) EQ(i int) antlr.TerminalNode { - return s.GetToken(NumscriptParserEQ, i) -} - -func (s *SendStatementContext) Source() ISourceContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISourceContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISourceContext) -} - -func (s *SendStatementContext) DESTINATION() antlr.TerminalNode { - return s.GetToken(NumscriptParserDESTINATION, 0) -} - -func (s *SendStatementContext) Destination() IDestinationContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IDestinationContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IDestinationContext) -} - -func (s *SendStatementContext) RPARENS() antlr.TerminalNode { - return s.GetToken(NumscriptParserRPARENS, 0) -} - -func (s *SendStatementContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSendStatement(s) - } -} - -func (s *SendStatementContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSendStatement(s) - } -} - -type SaveStatementContext struct { - StatementContext -} - -func NewSaveStatementContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *SaveStatementContext { - var p = new(SaveStatementContext) - - InitEmptyStatementContext(&p.StatementContext) - p.parser = parser - p.CopyAll(ctx.(*StatementContext)) - - return p -} - -func (s *SaveStatementContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *SaveStatementContext) SAVE() antlr.TerminalNode { - return s.GetToken(NumscriptParserSAVE, 0) -} - -func (s *SaveStatementContext) SentValue() ISentValueContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(ISentValueContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(ISentValueContext) -} - -func (s *SaveStatementContext) FROM() antlr.TerminalNode { - return s.GetToken(NumscriptParserFROM, 0) -} - -func (s *SaveStatementContext) ValueExpr() IValueExprContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IValueExprContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IValueExprContext) -} - -func (s *SaveStatementContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterSaveStatement(s) - } -} - -func (s *SaveStatementContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitSaveStatement(s) - } -} - -type FnCallStatementContext struct { - StatementContext -} - -func NewFnCallStatementContext(parser antlr.Parser, ctx antlr.ParserRuleContext) *FnCallStatementContext { - var p = new(FnCallStatementContext) - - InitEmptyStatementContext(&p.StatementContext) - p.parser = parser - p.CopyAll(ctx.(*StatementContext)) - - return p -} - -func (s *FnCallStatementContext) GetRuleContext() antlr.RuleContext { - return s -} - -func (s *FnCallStatementContext) FunctionCall() IFunctionCallContext { - var t antlr.RuleContext - for _, ctx := range s.GetChildren() { - if _, ok := ctx.(IFunctionCallContext); ok { - t = ctx.(antlr.RuleContext) - break - } - } - - if t == nil { - return nil - } - - return t.(IFunctionCallContext) -} - -func (s *FnCallStatementContext) EnterRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.EnterFnCallStatement(s) - } -} - -func (s *FnCallStatementContext) ExitRule(listener antlr.ParseTreeListener) { - if listenerT, ok := listener.(NumscriptListener); ok { - listenerT.ExitFnCallStatement(s) - } -} - -func (p *NumscriptParser) Statement() (localctx IStatementContext) { - localctx = NewStatementContext(p, p.GetParserRuleContext(), p.GetState()) - p.EnterRule(localctx, 36, NumscriptParserRULE_statement) - p.SetState(214) - p.GetErrorHandler().Sync(p) - if p.HasError() { - goto errorExit - } - - switch p.GetTokenStream().LA(1) { - case NumscriptParserSEND: - localctx = NewSendStatementContext(p, localctx) - p.EnterOuterAlt(localctx, 1) - { - p.SetState(197) - p.Match(NumscriptParserSEND) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(198) - p.SentValue() - } - { - p.SetState(199) - p.Match(NumscriptParserLPARENS) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(200) - p.Match(NumscriptParserSOURCE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(201) - p.Match(NumscriptParserEQ) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(202) - p.Source() - } - { - p.SetState(203) - p.Match(NumscriptParserDESTINATION) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(204) - p.Match(NumscriptParserEQ) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(205) - p.Destination() - } - { - p.SetState(206) - p.Match(NumscriptParserRPARENS) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - - case NumscriptParserSAVE: - localctx = NewSaveStatementContext(p, localctx) - p.EnterOuterAlt(localctx, 2) - { - p.SetState(208) - p.Match(NumscriptParserSAVE) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(209) - p.SentValue() - } - { - p.SetState(210) - p.Match(NumscriptParserFROM) - if p.HasError() { - // Recognition error - abort rule - goto errorExit - } - } - { - p.SetState(211) - p.valueExpr(0) - } - - case NumscriptParserIDENTIFIER: - localctx = NewFnCallStatementContext(p, localctx) - p.EnterOuterAlt(localctx, 3) - { - p.SetState(213) - p.FunctionCall() - } - - default: - p.SetError(antlr.NewNoViableAltException(p, nil, nil, nil, nil, nil)) - goto errorExit - } - -errorExit: - if p.HasError() { - v := p.GetError() - localctx.SetException(v) - p.GetErrorHandler().ReportError(p, v) - p.GetErrorHandler().Recover(p, v) - p.SetError(nil) - } - p.ExitRule() - return localctx - goto errorExit // Trick to prevent compiler error if the label is not used -} - -func (p *NumscriptParser) Sempred(localctx antlr.RuleContext, ruleIndex, predIndex int) bool { - switch ruleIndex { - case 2: - var t *ValueExprContext = nil - if localctx != nil { - t = localctx.(*ValueExprContext) - } - return p.ValueExpr_Sempred(t, predIndex) - - default: - panic("No predicate with index: " + fmt.Sprint(ruleIndex)) - } -} - -func (p *NumscriptParser) ValueExpr_Sempred(localctx antlr.RuleContext, predIndex int) bool { - switch predIndex { - case 0: - return p.Precpred(p.GetParserRuleContext(), 1) - - default: - panic("No predicate with index: " + fmt.Sprint(predIndex)) - } -} diff --git a/internal/parser/ast.go b/internal/parser/ast.go deleted file mode 100644 index 7e70de8..0000000 --- a/internal/parser/ast.go +++ /dev/null @@ -1,261 +0,0 @@ -package parser - -import ( - "math/big" -) - -type ValueExpr interface { - Ranged - valueExpr() -} - -func (*Variable) valueExpr() {} -func (*AssetLiteral) valueExpr() {} -func (*MonetaryLiteral) valueExpr() {} -func (*AccountLiteral) valueExpr() {} -func (*RatioLiteral) valueExpr() {} -func (*NumberLiteral) valueExpr() {} -func (*StringLiteral) valueExpr() {} -func (*BinaryInfix) valueExpr() {} - -type InfixOperator string - -const ( - InfixOperatorPlus InfixOperator = "+" - InfixOperatorMinus InfixOperator = "-" -) - -type ( - AssetLiteral struct { - Range - Asset string - } - - NumberLiteral struct { - Range - Number int - } - - StringLiteral struct { - Range - String string - } - - MonetaryLiteral struct { - Range - Asset ValueExpr - Amount ValueExpr - } - - AccountLiteral struct { - Range - Name string - } - - RatioLiteral struct { - Range - Numerator *big.Int - Denominator *big.Int - } - - Variable struct { - Range - Name string - } - - BinaryInfix struct { - Range - Operator InfixOperator - Left ValueExpr - Right ValueExpr - } -) - -func (r RatioLiteral) ToRatio() *big.Rat { - return new(big.Rat).SetFrac(r.Numerator, r.Denominator) -} - -func (a *AccountLiteral) IsWorld() bool { - return a.Name == "world" -} - -// Source exprs - -type Source interface { - source() - GetRange() Range -} - -func (*SourceInorder) source() {} -func (*SourceAllotment) source() {} -func (*SourceAccount) source() {} -func (*SourceCapped) source() {} -func (*SourceOverdraft) source() {} - -type ( - SourceAccount struct { - ValueExpr - } - - SourceInorder struct { - Range - Sources []Source - } - SourceAllotment struct { - Range - Items []SourceAllotmentItem - } - - SourceAllotmentItem struct { - Range - Allotment AllotmentValue - From Source - } - - SourceCapped struct { - Range - From Source - Cap ValueExpr - } - - SourceOverdraft struct { - Range - Address ValueExpr - Bounded *ValueExpr - } -) - -type AllotmentValue interface{ allotmentValue() } - -func (*RemainingAllotment) allotmentValue() {} -func (*RatioLiteral) allotmentValue() {} -func (*Variable) allotmentValue() {} - -type RemainingAllotment struct { - Range -} - -// Destination exprs -type Destination interface { - destination() - Ranged -} - -func (*DestinationAccount) destination() {} -func (*DestinationInorder) destination() {} -func (*DestinationAllotment) destination() {} - -type ( - DestinationAccount struct { - ValueExpr - } - - DestinationInorder struct { - Range - Clauses []DestinationInorderClause - Remaining KeptOrDestination - } - - DestinationInorderClause struct { - Range - Cap ValueExpr - To KeptOrDestination - } - - DestinationAllotment struct { - Range - Items []DestinationAllotmentItem - } - - DestinationAllotmentItem struct { - Range - Allotment AllotmentValue - To KeptOrDestination - } -) - -type KeptOrDestination interface { - keptOrDestination() -} - -func (*DestinationKept) keptOrDestination() {} -func (*DestinationTo) keptOrDestination() {} - -type ( - DestinationKept struct { - Range - } - - DestinationTo struct { - Destination Destination - } -) - -// Statements - -type Statement interface { - statement() - Ranged -} - -func (*FnCall) statement() {} -func (*SendStatement) statement() {} -func (*SaveStatement) statement() {} - -type FnCallIdentifier struct { - Range - Name string -} - -type FnCall struct { - Range - Caller *FnCallIdentifier - Args []ValueExpr -} - -type SentValue interface { - sentValue() - Ranged -} - -type SentValueLiteral struct { - Range - Monetary ValueExpr -} -type SentValueAll struct { - Range - Asset ValueExpr -} - -func (*SentValueLiteral) sentValue() {} -func (*SentValueAll) sentValue() {} - -type SendStatement struct { - Range - SentValue SentValue - Source Source - Destination Destination -} - -type SaveStatement struct { - Range - SentValue SentValue - Amount ValueExpr -} - -type TypeDecl struct { - Range - Name string -} - -type VarDeclaration struct { - Range - Name *Variable - Type *TypeDecl - Origin *FnCall -} - -type Program struct { - Vars []VarDeclaration - Statements []Statement -} diff --git a/internal/parser/parser.go b/internal/parser/parser.go deleted file mode 100644 index 48fc3ba..0000000 --- a/internal/parser/parser.go +++ /dev/null @@ -1,641 +0,0 @@ -package parser - -import ( - "math" - "math/big" - "strconv" - "strings" - - parser "github.com/PagoPlus/numscript-wasm/internal/parser/antlr" - "github.com/PagoPlus/numscript-wasm/internal/utils" - - "github.com/antlr4-go/antlr/v4" -) - -type ParserError struct { - Range Range - Msg string -} - -type ParseResult struct { - Source string - Value Program - Errors []ParserError -} - -type ErrorListener struct { - antlr.DefaultErrorListener - Errors []ParserError -} - -func (l *ErrorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, startL, startC int, msg string, e antlr.RecognitionException) { - length := 1 - if token, ok := offendingSymbol.(antlr.Token); ok { - length = len(token.GetText()) - } - endL := startL - endC := startC + length - 1 // -1 so that end character is inside the offending token - l.Errors = append(l.Errors, ParserError{ - Msg: msg, - Range: Range{ - Start: Position{Character: startC, Line: startL - 1}, - End: Position{Character: endC, Line: endL - 1}, - }, - }) -} - -func Parse(input string) ParseResult { - // TODO handle lexer errors - listener := &ErrorListener{} - - is := antlr.NewInputStream(input) - lexer := parser.NewNumscriptLexer(is) - lexer.RemoveErrorListeners() - lexer.AddErrorListener(listener) - - stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) - - parser := parser.NewNumscriptParser(stream) - parser.RemoveErrorListeners() - parser.AddErrorListener(listener) - - parsed := parseProgram(parser.Program()) - - return ParseResult{ - Source: input, - Value: parsed, - Errors: listener.Errors, - } -} - -func ParseErrorsToString(errors []ParserError, source string) string { - buf := "Got errors while parsing:\n" - for _, err := range errors { - buf += err.Msg + "\n" + err.Range.ShowOnSource(source) + "\n" - } - return buf -} - -func parseVarsDeclaration(varsCtx parser.IVarsDeclarationContext) []VarDeclaration { - if varsCtx == nil { - return nil - } - - var vars []VarDeclaration - for _, varDecl := range varsCtx.AllVarDeclaration() { - decl := parseVarDeclaration(varDecl) - if decl != nil { - vars = append(vars, *decl) - } - } - return vars -} - -func parseProgram(programCtx parser.IProgramContext) Program { - vars := parseVarsDeclaration(programCtx.VarsDeclaration()) - - var statements []Statement - for _, statementCtx := range programCtx.AllStatement() { - statements = append(statements, parseStatement(statementCtx)) - } - - return Program{ - Statements: statements, - Vars: vars, - } -} - -func parseVarDeclaration(varDecl parser.IVarDeclarationContext) *VarDeclaration { - if varDecl == nil { - return nil - } - - var fnCallStatement *FnCall - if varDecl.VarOrigin() != nil { - fnCallStatement = parseFnCall(varDecl.VarOrigin().FunctionCall()) - } - - return &VarDeclaration{ - Range: ctxToRange(varDecl), - Type: parseVarType(varDecl.GetType_()), - Name: parseVarLiteral(varDecl.GetName()), - Origin: fnCallStatement, - } -} - -func parseVarLiteral(tk antlr.Token) *Variable { - if tk == nil || tk.GetTokenIndex() == -1 { - return nil - } - - name := tk.GetText()[1:] - - return &Variable{ - Range: tokenToRange(tk), - Name: name, - } -} - -func parseVarType(tk antlr.Token) *TypeDecl { - if tk == nil || tk.GetTokenIndex() == -1 { - return nil - } - - return &TypeDecl{ - Range: tokenToRange(tk), - Name: tk.GetText(), - } -} - -func parseSource(sourceCtx parser.ISourceContext) Source { - if sourceCtx == nil { - return nil - } - - range_ := ctxToRange(sourceCtx) - - switch sourceCtx := sourceCtx.(type) { - case *parser.SrcAccountContext: - return &SourceAccount{ - ValueExpr: parseValueExpr(sourceCtx.ValueExpr()), - } - - case *parser.SrcInorderContext: - var sources []Source - for _, sourceCtx := range sourceCtx.AllSource() { - sources = append(sources, parseSource(sourceCtx)) - } - return &SourceInorder{ - Range: range_, - Sources: sources, - } - - case *parser.SrcAllotmentContext: - var items []SourceAllotmentItem - for _, itemCtx := range sourceCtx.AllAllotmentClauseSrc() { - item := SourceAllotmentItem{ - Range: ctxToRange(itemCtx), - Allotment: parseAllotment(itemCtx.Allotment()), - From: parseSource(itemCtx.Source()), - } - items = append(items, item) - } - return &SourceAllotment{ - Range: range_, - Items: items, - } - - case *parser.SrcCappedContext: - return &SourceCapped{ - Range: range_, - From: parseSource(sourceCtx.Source()), - Cap: parseValueExpr(sourceCtx.GetCap_()), - } - - case *parser.SrcAccountUnboundedOverdraftContext: - return &SourceOverdraft{ - Range: ctxToRange(sourceCtx), - Address: parseValueExpr(sourceCtx.GetAddress()), - } - - case *parser.SrcAccountBoundedOverdraftContext: - varMon := parseValueExpr(sourceCtx.GetMaxOvedraft()) - - return &SourceOverdraft{ - Range: ctxToRange(sourceCtx), - Address: parseValueExpr(sourceCtx.GetAddress()), - Bounded: &varMon, - } - - case *parser.SourceContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[Source](sourceCtx.GetText()) - } -} - -func unsafeParseBigInt(s string) *big.Int { - s = strings.TrimSpace(s) - i, ok := new(big.Int).SetString(s, 10) - if !ok { - panic("invalid int: " + s) - } - return i -} - -func parseRatio(source string, range_ Range) *RatioLiteral { - split := strings.Split(source, "/") - - num := unsafeParseBigInt(split[0]) - den := unsafeParseBigInt(split[1]) - - return &RatioLiteral{ - Range: range_, - Numerator: num, - Denominator: den, - } -} - -// TODO actually handle big int -func ParsePercentageRatio(source string) (*big.Int, *big.Int, error) { - str := strings.TrimSuffix(source, "%") - num, err := strconv.ParseUint(strings.Replace(str, ".", "", -1), 0, 64) - if err != nil { - return nil, nil, err - } - - var denominator uint64 - split := strings.Split(str, ".") - if len(split) > 1 { - // TODO verify this is always correct - floatingDigits := len(split[1]) - denominator = (uint64)(math.Pow10(2 + floatingDigits)) - } else { - denominator = 100 - } - - return big.NewInt(int64(num)), big.NewInt(int64(denominator)), nil -} - -func parsePercentageRatio(source string, range_ Range) *RatioLiteral { - num, denominator, err := ParsePercentageRatio(source) - if err != nil { - panic(err) - } - - return &RatioLiteral{ - Range: range_, - Numerator: num, - Denominator: denominator, - } -} - -func parseAllotment(allotmentCtx parser.IAllotmentContext) AllotmentValue { - switch allotmentCtx := allotmentCtx.(type) { - case *parser.PortionedAllotmentContext: - return parsePortionSource(allotmentCtx.Portion()) - - case *parser.RemainingAllotmentContext: - return &RemainingAllotment{ - Range: ctxToRange(allotmentCtx), - } - - case *parser.PortionVariableContext: - return variableLiteralFromCtx(allotmentCtx) - - case *parser.AllotmentContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[AllotmentValue](allotmentCtx.GetText()) - } -} - -func parseStringLiteralCtx(stringCtx *parser.StringLiteralContext) *StringLiteral { - rawStr := stringCtx.GetText() - // Remove leading and trailing '"' - innerStr := rawStr[1 : len(rawStr)-1] - return &StringLiteral{ - Range: ctxToRange(stringCtx), - String: innerStr, - } -} - -func parseValueExpr(valueExprCtx parser.IValueExprContext) ValueExpr { - switch valueExprCtx := valueExprCtx.(type) { - case *parser.AccountLiteralContext: - return &AccountLiteral{ - Range: ctxToRange(valueExprCtx), - // Discard the '@' - Name: valueExprCtx.GetText()[1:], - } - - case *parser.MonetaryLiteralContext: - return parseMonetaryLit(valueExprCtx.MonetaryLit()) - - case *parser.AssetLiteralContext: - return &AssetLiteral{ - Range: ctxToRange(valueExprCtx), - Asset: valueExprCtx.GetText(), - } - - case *parser.NumberLiteralContext: - return parseNumberLiteral(valueExprCtx.NUMBER()) - - case *parser.PortionLiteralContext: - return parsePortionSource(valueExprCtx.Portion()) - - case *parser.VariableExprContext: - return variableLiteralFromCtx(valueExprCtx) - - case *parser.StringLiteralContext: - return parseStringLiteralCtx(valueExprCtx) - - case *parser.InfixExprContext: - return &BinaryInfix{ - Range: ctxToRange(valueExprCtx), - Operator: InfixOperator(valueExprCtx.GetOp().GetText()), - Left: parseValueExpr(valueExprCtx.GetLeft()), - Right: parseValueExpr(valueExprCtx.GetRight()), - } - - case nil, *parser.ValueExprContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[ValueExpr](valueExprCtx.GetText()) - } -} - -func variableLiteralFromCtx(ctx antlr.ParserRuleContext) *Variable { - // Discard the '$' - name := ctx.GetText()[1:] - - return &Variable{ - Range: ctxToRange(ctx), - Name: name, - } -} - -func parsePortionSource(portionCtx parser.IPortionContext) *RatioLiteral { - switch portionCtx.(type) { - case *parser.RatioContext: - return parseRatio(portionCtx.GetText(), ctxToRange(portionCtx)) - - case *parser.PercentageContext: - return parsePercentageRatio(portionCtx.GetText(), ctxToRange(portionCtx)) - - case *parser.PortionContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[*RatioLiteral](portionCtx.GetText()) - } -} - -func parseDestination(destCtx parser.IDestinationContext) Destination { - if destCtx == nil { - return nil - } - - range_ := ctxToRange(destCtx) - - switch destCtx := destCtx.(type) { - case *parser.DestAccountContext: - return &DestinationAccount{ - ValueExpr: parseValueExpr(destCtx.ValueExpr()), - } - - case *parser.DestInorderContext: - var inorderClauses []DestinationInorderClause - for _, destInorderClause := range destCtx.AllDestinationInOrderClause() { - inorderClauses = append(inorderClauses, parseDestinationInorderClause(destInorderClause)) - } - - return &DestinationInorder{ - Range: range_, - Clauses: inorderClauses, - Remaining: parseKeptOrDestination(destCtx.KeptOrDestination()), - } - - case *parser.DestAllotmentContext: - var items []DestinationAllotmentItem - for _, itemCtx := range destCtx.AllAllotmentClauseDest() { - item := DestinationAllotmentItem{ - Range: ctxToRange(itemCtx), - Allotment: parseDestinationAllotment(itemCtx.Allotment()), - To: parseKeptOrDestination(itemCtx.KeptOrDestination()), - } - items = append(items, item) - } - return &DestinationAllotment{ - Range: range_, - Items: items, - } - - case *parser.DestinationContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[Destination](destCtx.GetText()) - } - -} - -func parseDestinationInorderClause(clauseCtx parser.IDestinationInOrderClauseContext) DestinationInorderClause { - return DestinationInorderClause{ - Range: ctxToRange(clauseCtx), - Cap: parseValueExpr(clauseCtx.ValueExpr()), - To: parseKeptOrDestination(clauseCtx.KeptOrDestination()), - } -} - -func parseKeptOrDestination(clauseCtx parser.IKeptOrDestinationContext) KeptOrDestination { - if clauseCtx == nil { - return nil - } - - switch clauseCtx := clauseCtx.(type) { - case *parser.DestinationToContext: - return &DestinationTo{ - Destination: parseDestination(clauseCtx.Destination()), - } - case *parser.DestinationKeptContext: - return &DestinationKept{ - Range: ctxToRange(clauseCtx), - } - case *parser.KeptOrDestinationContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[KeptOrDestination](clauseCtx.GetText()) - } - -} - -func parseDestinationAllotment(allotmentCtx parser.IAllotmentContext) AllotmentValue { - switch allotmentCtx := allotmentCtx.(type) { - case *parser.RemainingAllotmentContext: - return &RemainingAllotment{ - Range: ctxToRange(allotmentCtx), - } - - case *parser.PortionedAllotmentContext: - return parseDestinationPortion(allotmentCtx.Portion()) - - case *parser.PortionVariableContext: - return variableLiteralFromCtx(allotmentCtx) - - case *parser.AllotmentContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[AllotmentValue](allotmentCtx.GetText()) - } -} - -func parseDestinationPortion(portionCtx parser.IPortionContext) AllotmentValue { - switch portionCtx.(type) { - case *parser.RatioContext: - return parseRatio(portionCtx.GetText(), ctxToRange(portionCtx)) - - case *parser.PercentageContext: - return parsePercentageRatio(portionCtx.GetText(), ctxToRange(portionCtx)) - - case *parser.PortionContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[AllotmentValue](portionCtx.GetText()) - } -} - -func parseFnArgs(fnCallArgCtx parser.IFunctionCallArgsContext) []ValueExpr { - if fnCallArgCtx == nil { - return nil - } - - var args []ValueExpr - for _, valueExpr := range fnCallArgCtx.AllValueExpr() { - args = append(args, parseValueExpr(valueExpr)) - } - return args -} - -func parseFnCall(fnCallCtx parser.IFunctionCallContext) *FnCall { - if fnCallCtx == nil { - return nil - } - - ident := fnCallCtx.IDENTIFIER() - if ident == nil { - return nil - } - - allArgs := fnCallCtx.FunctionCallArgs() - - return &FnCall{ - Range: ctxToRange(fnCallCtx), - Caller: &FnCallIdentifier{ - Range: tokenToRange(ident.GetSymbol()), - Name: ident.GetSymbol().GetText(), - }, - Args: parseFnArgs(allArgs), - } -} - -func parseSaveStatement(saveCtx *parser.SaveStatementContext) *SaveStatement { - return &SaveStatement{ - Range: ctxToRange(saveCtx), - SentValue: parseSentValue(saveCtx.SentValue()), - Amount: parseValueExpr(saveCtx.ValueExpr()), - } -} - -func parseStatement(statementCtx parser.IStatementContext) Statement { - switch statementCtx := statementCtx.(type) { - case *parser.SendStatementContext: - return parseSendStatement(statementCtx) - - case *parser.SaveStatementContext: - return parseSaveStatement(statementCtx) - - case *parser.FnCallStatementContext: - return parseFnCall(statementCtx.FunctionCall()) - - case *parser.StatementContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[Statement](statementCtx.GetText()) - } -} - -func parseSentValue(statementCtx parser.ISentValueContext) SentValue { - switch statementCtx := statementCtx.(type) { - case *parser.SentLiteralContext: - return &SentValueLiteral{ - Range: ctxToRange(statementCtx), - Monetary: parseValueExpr(statementCtx.ValueExpr()), - } - case *parser.SentAllContext: - return &SentValueAll{ - Range: ctxToRange(statementCtx), - Asset: parseValueExpr(statementCtx.SentAllLit().GetAsset()), - } - - case *parser.SentValueContext: - return nil - - default: - return utils.NonExhaustiveMatchPanic[SentValue](statementCtx.GetText()) - } - -} - -func parseSendStatement(statementCtx *parser.SendStatementContext) *SendStatement { - return &SendStatement{ - Source: parseSource(statementCtx.Source()), - Destination: parseDestination(statementCtx.Destination()), - Range: ctxToRange(statementCtx), - SentValue: parseSentValue(statementCtx.SentValue()), - } -} - -func parseNumberLiteral(numNode antlr.TerminalNode) *NumberLiteral { - amtStr := numNode.GetText() - - amt, err := strconv.Atoi(amtStr) - if err != nil { - panic("Invalid number: " + amtStr) - } - - return &NumberLiteral{ - Range: tokenToRange(numNode.GetSymbol()), - Number: amt, - } -} - -func parseMonetaryLit(monetaryLitCtx parser.IMonetaryLitContext) *MonetaryLiteral { - if monetaryLitCtx.GetAmt() == nil { - return nil - } - - return &MonetaryLiteral{ - Range: ctxToRange(monetaryLitCtx), - Asset: parseValueExpr(monetaryLitCtx.GetAsset()), - Amount: parseValueExpr(monetaryLitCtx.GetAmt()), - } -} - -func ctxToRange(ctx antlr.ParserRuleContext) Range { - startTk := ctx.GetStart() - endTk := ctx.GetStop() - - return Range{ - Start: Position{ - Line: startTk.GetLine() - 1, - Character: startTk.GetColumn(), - }, - End: Position{ - Line: endTk.GetLine() - 1, - - // this is based on the assumption that a token cannot span multiple lines - Character: endTk.GetColumn() + len(endTk.GetText()), - }, - } -} - -func tokenToRange(tk antlr.Token) Range { - return Range{ - Start: Position{ - Line: tk.GetLine() - 1, - Character: tk.GetColumn(), - }, - End: Position{ - Line: tk.GetLine() - 1, - Character: tk.GetColumn() + len(tk.GetText()), - }, - } -} diff --git a/internal/parser/parser_fault_tolerance_test.go b/internal/parser/parser_fault_tolerance_test.go deleted file mode 100644 index c90a719..0000000 --- a/internal/parser/parser_fault_tolerance_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package parser_test - -import ( - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/gkampitakis/go-snaps/snaps" - "github.com/stretchr/testify/assert" -) - -func TestFaultToleranceVarName(t *testing.T) { - p := parser.Parse(`vars { monetary 42 }`) - snaps.MatchSnapshot(t, p.Value) - assert.NotEmpty(t, p.Errors) -} - -func TestFaultToleranceSend(t *testing.T) { - p := parser.Parse(`send `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceMonetary(t *testing.T) { - p := parser.Parse(`send [COIN]`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceNoAddr(t *testing.T) { - p := parser.Parse(`send ( - source = { - @ - } - destination = @ -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceInvalidDest(t *testing.T) { - p := parser.Parse(`send [COIN 10] ( - source = @a - destination = -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceInvalidSrcTk(t *testing.T) { - p := parser.Parse(`send [COIN 10] ( - source = max - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceTrailingComma(t *testing.T) { - p := parser.Parse(`set_tx_meta(1, )`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceDestinationNoRemainingMispelledFrom(t *testing.T) { - p := parser.Parse(`send [COIN 10] ( - source = @a - destination = { - max [COIN 10] from @x - } - ) - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceIncompleteOrigin(t *testing.T) { - p := parser.Parse(` -vars { - asset $a = -} - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceIncompleteSave(t *testing.T) { - p := parser.Parse(` -save - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceIncompleteSave2(t *testing.T) { - p := parser.Parse(` -save [COIN 10] - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestFaultToleranceIncompleteSave3(t *testing.T) { - p := parser.Parse(` -save [COIN 10] from - `) - snaps.MatchSnapshot(t, p.Value) -} diff --git a/internal/parser/parser_test.go b/internal/parser/parser_test.go deleted file mode 100644 index 9c268d3..0000000 --- a/internal/parser/parser_test.go +++ /dev/null @@ -1,316 +0,0 @@ -package parser_test - -import ( - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - - "github.com/gkampitakis/go-snaps/snaps" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestShowErrorLines(t *testing.T) { - script := `send [EUR/2 100] ( - source = err - destination = ee -)` - p := parser.Parse(script) - snaps.MatchSnapshot(t, parser.ParseErrorsToString(p.Errors, script)) -} - -func TestPlainAddress(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = @src - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestMultipleSends(t *testing.T) { - p := parser.Parse(` - send [COIN 10] ( source = @src destination = @dest ) - send [COIN 20] ( source = @src destination = @dest ) - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestVariable(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = $example_var_src - destination = $example_var_dest -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestVariableMonetary(t *testing.T) { - p := parser.Parse(`send $example ( - source = @a - destination = @b -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestInorderSource(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { @s1 @s2 } - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestNegativeNumberLit(t *testing.T) { - p := parser.Parse(`send [EUR/2 -100] ( - source = @src - destination = @dest -)`) - require.Nil(t, p.Errors) - snaps.MatchSnapshot(t, p.Value) -} - -func TestInorderDestination(t *testing.T) { - p := parser.Parse(`send $amt ( - source = @s - destination = { - max $m1 to @d1 - max [C 42] kept - remaining to @d3 - } -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestAllotment(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { 1/3 from @s1 } - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentPerc(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { - 42% from @s1 - 1/2 from @s2 - remaining from @s3 - } - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentPercFloating(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { 2.42% from @s } - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentVariableSource(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { - $x from @a - } - destination = @d -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentDest(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = @s - destination = { 1/2 to @d } -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentDestRemaining(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = @s - destination = { - 1/2 to @d - remaining to @d2 - } -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestAllotmentDestKept(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = @s - destination = { 1/2 kept } -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestCapped(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = max [EUR/2 10] from @src - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestCappedVariable(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = max $my_var from @src - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestNested(t *testing.T) { - p := parser.Parse(`send [EUR/2 100] ( - source = { - max [COIN 42] from @src - @a - @b - } - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) -} - -func TestEmptyVars(t *testing.T) { - p := parser.Parse(`vars { }`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestSingleVar(t *testing.T) { - p := parser.Parse(`vars { monetary $my_var }`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestOverdraftUnbounded(t *testing.T) { - p := parser.Parse(`send $x ( - source = @src allowing unbounded overdraft - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestOverdraftUnboundedVariable(t *testing.T) { - p := parser.Parse(`send $x ( - source = $my_src_var allowing unbounded overdraft - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestBoundedOverdraft(t *testing.T) { - p := parser.Parse(`send $x ( - source = $my_src_var allowing overdraft up to [COIN 100] - destination = @dest -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestFunctionCallNoArgs(t *testing.T) { - p := parser.Parse(`example_fn()`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestFunctionCallOneArg(t *testing.T) { - p := parser.Parse(`example_fn(@example)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestFunctionCallManyArgs(t *testing.T) { - p := parser.Parse(` -example_fn( - [COIN 42], - 100, - 1/2, - $my_var, - "example_str" -)`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestVarOrigin(t *testing.T) { - p := parser.Parse(` -vars { - monetary $my_var = origin_fn(@my_account, "str") -} -`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestSendAll(t *testing.T) { - p := parser.Parse(`send [ASSET *] ( - source = @a - destination = @b -) -`) - snaps.MatchSnapshot(t, p.Value) - assert.Empty(t, p.Errors) -} - -func TestWhitespaceInRatio(t *testing.T) { - p := parser.Parse(` -send $var ( - source = @world - destination = { - 1 / 6 to @player:1 - } -) - `) - snaps.MatchSnapshot(t, p.Value) -} - -func TestSaveStatementSimple(t *testing.T) { - p := parser.Parse(` -save [EUR/2 100] from @alice - `) - require.Len(t, p.Errors, 0) - snaps.MatchSnapshot(t, p.Value) -} - -func TestSaveAllStatement(t *testing.T) { - p := parser.Parse(` -save [EUR/2 *] from @alice - `) - require.Len(t, p.Errors, 0) - snaps.MatchSnapshot(t, p.Value) -} - -func TestSaveStatementVar(t *testing.T) { - p := parser.Parse(` -save $amt from $acc - `) - require.Len(t, p.Errors, 0) - snaps.MatchSnapshot(t, p.Value) -} - -func TestInfix(t *testing.T) { - p := parser.Parse(` -set_tx_meta("k1", 1 + "invalid arg") -set_tx_meta("k2", 1/2 - [COIN 10]) - `) - require.Len(t, p.Errors, 0) - snaps.MatchSnapshot(t, p.Value) -} - -func TestInfixPrec(t *testing.T) { - // 1 + 2 - 3 - // should be the same as - // (1 + 2) - 3 - p := parser.Parse(` -set_tx_meta("k1", 1 + 2 - 3) - `) - require.Len(t, p.Errors, 0) - snaps.MatchSnapshot(t, p.Value) -} diff --git a/internal/parser/range.go b/internal/parser/range.go deleted file mode 100644 index 32454a1..0000000 --- a/internal/parser/range.go +++ /dev/null @@ -1,164 +0,0 @@ -package parser - -import ( - "fmt" - "strings" -) - -type Position struct { - Character int - Line int -} - -type Range struct { - Start Position - End Position -} - -type Ranged interface { - GetRange() Range -} - -func (r Range) GetRange() Range { return r } - -func (p1 *Position) GtEq(p2 Position) bool { - if p1.Line == p2.Line { - return p1.Character >= p2.Character - } - - return p1.Line > p2.Line -} - -func (p *Position) AsRange() Range { - // position >= r.Start && r.End >= position - return Range{Start: *p, End: *p} -} - -func (r Range) Contains(position Position) bool { - // position >= r.Start && r.End >= position - return position.GtEq(r.Start) && r.End.GtEq(position) -} - -// Pre: valid range (e.g. start <= end) -func (r Range) ShowOnSource(source string) string { - lines := strings.Split(source, "\n") - errorLines := lines[r.Start.Line : r.End.Line+1] - - separator := " | " - - showLine := func(index int, line string) string { - // %3d creates left (whitespace) padding so that the width is at least 3 - digit := fmt.Sprintf("%3d", index) - - // code line - return digit + separator + line + "\n" - } - - showError := func(lineOffset int, line string) string { - digitPadding := strings.Repeat(" ", 3) - - srcLine := r.Start.Line + lineOffset - var errStartChar int - if r.Start.Line == srcLine { - errStartChar = r.Start.Character - } else { - errStartChar = 0 - } - - var errEndChar int - if r.End.Line == srcLine { - errEndChar = r.End.Character - } else { - errEndChar = len(line) - } - - errorIndicator := strings.Repeat("~", errEndChar-errStartChar) - - leftWs := strings.Repeat(" ", errStartChar) - - return digitPadding + separator + leftWs + errorIndicator - } - - buf := "" - for lineOffset, line := range errorLines { - // Separate previous result with a newline - if lineOffset != 0 { - buf += "\n" - } - srcLine := r.Start.Line + lineOffset - - if srcLine != 0 && lineOffset == 0 { - buf += showLine(srcLine-1, lines[srcLine-1]) - } - - buf += showLine(srcLine, line) - buf += showError(lineOffset, line) - - if srcLine != len(lines)-1 && lineOffset == len(errorLines)-1 { - buf += "\n" + showLine(srcLine+1, lines[srcLine+1]) - } - - } - - return buf -} - -// Those functions are mostly used as test utilities -func indexOfOccurrence(src string, substr string, occurence int) int { - // TODO this function can probably be simplified - offset := strings.Index(src, substr) - if offset == -1 { - return -1 - } - - for ; occurence > 0; occurence-- { - shift := offset + len(substr) - shiftedOffset := strings.Index(src[shift:], substr) - if shiftedOffset == -1 { - return -1 - } - - offset += shiftedOffset + len(substr) - } - - return offset -} - -func PositionOf(src string, substr string) *Position { - return PositionOfIndexed(src, substr, 0) -} - -func PositionOfIndexed(src string, substr string, occurrence int) *Position { - // TODO make offset to position utility - offset := indexOfOccurrence(src, substr, occurrence) - if offset == -1 { - return nil - } - - pos := Position{} - for thisOffset, rune := range src { - if thisOffset == offset { - break - } - - if rune == '\n' { - pos.Line++ - pos.Character = 0 - } else { - pos.Character++ - } - } - - return &pos -} - -func RangeOfIndexed(src string, substr string, occurrence int) Range { - start := *PositionOfIndexed(src, substr, occurrence) - end := start - end.Character += len(substr) - - return Range{ - Start: start, - End: end, - } -} diff --git a/internal/parser/range_test.go b/internal/parser/range_test.go deleted file mode 100644 index 6b311f4..0000000 --- a/internal/parser/range_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package parser_test - -import ( - "testing" - - "github.com/PagoPlus/numscript-wasm/internal/parser" - "github.com/gkampitakis/go-snaps/snaps" - "github.com/stretchr/testify/assert" -) - -func TestPositionGt(t *testing.T) { - t.Parallel() - - assert.True(t, (&parser.Position{ - Line: 10, - Character: 20, - }).GtEq(parser.Position{ - Line: 10, - Character: 20, - }), "a position is GtEq to itself") - - assert.True(t, (&parser.Position{ - Line: 100, - Character: 0, - }).GtEq(parser.Position{ - Line: 10, - Character: 20, - }), "x is GtEq to y when x line is greater") - - assert.False(t, (&parser.Position{ - Line: 10, - Character: 0, - }).GtEq(parser.Position{ - Line: 100, - Character: 20, - }), "x is not GtEq to y when x line is greater") - - assert.True(t, (&parser.Position{ - Line: 0, - Character: 100, - }).GtEq(parser.Position{ - Line: 0, - Character: 20, - }), "x is GtEq to y when they are in the same line and the char is higher") - - assert.False(t, (&parser.Position{ - Line: 0, - Character: 19, - }).GtEq(parser.Position{ - Line: 0, - Character: 20, - }), "x is not GtEq to y when they are in the same line and the char is lower") - -} - -func TestContainsSameLine(t *testing.T) { - t.Parallel() - - rng := parser.Range{ - Start: parser.Position{Line: 42, Character: 5}, - End: parser.Position{Line: 42, Character: 10}, - } - - assert.True(t, rng.Contains(parser.Position{ - Line: 42, - Character: 8, - }), "contains position within the same line") - - assert.True(t, rng.Contains(parser.Position{ - Line: 42, - Character: 5, - }), "contains position with same start") - - assert.True(t, rng.Contains(parser.Position{ - Line: 42, - Character: 10, - }), "contains position with same end") - - assert.False(t, rng.Contains(parser.Position{ - Line: 42, - Character: 4, - }), "does not contain position before the start") - - assert.False(t, rng.Contains(parser.Position{ - Line: 42, - Character: 12, - }), "does not contain position after the end") - - assert.False(t, rng.Contains(parser.Position{ - Line: 10, - Character: 8, - }), "does not contain position before the line") - - assert.False(t, rng.Contains(parser.Position{ - Line: 100, - Character: 8, - }), "does not contain position after the line") -} - -func TestContainsManyLines(t *testing.T) { - t.Parallel() - - rng := parser.Range{ - Start: parser.Position{Line: 10, Character: 5}, - End: parser.Position{Line: 100, Character: 10}, - } - - assert.True(t, rng.Contains(parser.Position{ - Line: 50, - Character: 0, - }), "contains position between the lines even if char is before end") - - assert.True(t, rng.Contains(parser.Position{ - Line: 50, - Character: 99, - }), "contains position between the lines even if char is after end") -} - -func TestPositionOf(t *testing.T) { - t.Parallel() - - assert.Equal(t, - &parser.Position{Character: 0}, - parser.PositionOf("abc", "a"), - ) - - assert.Equal(t, - &parser.Position{Character: 1}, - parser.PositionOf("abc", "b"), - ) - - assert.Equal(t, - &parser.Position{Line: 1, Character: 0}, - parser.PositionOf("a\nbc", "b"), - ) - - assert.Equal(t, - &parser.Position{Line: 2, Character: 1}, - parser.PositionOf("a\nb\ncd", "d"), - ) -} - -func TestPositionOfIndexed(t *testing.T) { - t.Parallel() - - assert.Equal(t, - &parser.Position{Character: 2}, - parser.PositionOfIndexed("aba", "a", 1), - ) - - assert.Equal(t, - &parser.Position{Line: 2, Character: 1}, - parser.PositionOfIndexed("a\nd\ncd", "d", 1), - ) -} - -func TestShowRangeOnSourceSameLine(t *testing.T) { - src := `example error end of line` - - errorRange := parser.RangeOfIndexed(src, "error", 0) - - snaps.MatchSnapshot(t, errorRange.ShowOnSource(src)) -} - -func TestShowRangeOnMultilineRanges(t *testing.T) { - src := `example err -or spanning 2 lines` - - pos1 := parser.PositionOfIndexed(src, "err", 0) - - rng := parser.Range{ - Start: *pos1, - End: parser.Position{ - Line: 1, - Character: 2, - }, - } - - snaps.MatchSnapshot(t, rng.ShowOnSource(src)) -} - -func TestShowRangeComplex(t *testing.T) { - t.Parallel() - - src := ` -example err -or that spans more -lines and then other -words with no error -at all` - - rng := parser.Range{ - Start: parser.Position{ - Line: 1, - Character: 3, - }, - End: parser.Position{ - Line: 3, - Character: 5, - }, - } - - snaps.MatchSnapshot(t, rng.ShowOnSource(src)) -} diff --git a/internal/utils/utils.go b/internal/utils/utils.go deleted file mode 100644 index 46d3294..0000000 --- a/internal/utils/utils.go +++ /dev/null @@ -1,22 +0,0 @@ -package utils - -import ( - "fmt" - "math/big" -) - -func NonExhaustiveMatchPanic[T any](value any) T { - panic(fmt.Sprintf("Non exhaustive match (got '%#v')", value)) -} - -func MinBigInt(a *big.Int, b *big.Int) *big.Int { - var min big.Int - - if a.Cmp(b) == -1 { - min.Set(a) - } else { - min.Set(b) - } - - return &min -} diff --git a/main.go b/main.go new file mode 100644 index 0000000..a559238 --- /dev/null +++ b/main.go @@ -0,0 +1,125 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "io" + "os" + + "github.com/formancehq/numscript" + "github.com/spf13/cobra" +) + +var Version string + +func version() string { + if Version == "" { + return "dev" + } else { + return Version + } +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Shows the app version", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + fmt.Print(version()) + }, +} + +type RunInputOpts struct { + Script string `json:"script"` + Variables map[string]string `json:"variables"` + Meta numscript.AccountsMetadata `json:"metadata"` + Balances numscript.Balances `json:"balances"` + FeatureFlags map[string]struct{} `json:"featureFlags"` +} + +func run() { + opt := RunInputOpts{ + Variables: make(map[string]string), + Meta: make(numscript.AccountsMetadata), + Balances: make(numscript.Balances), + FeatureFlags: make(map[string]struct{}), + } + + bytes, err := io.ReadAll(os.Stdin) + if err != nil { + os.Stderr.Write([]byte(err.Error())) + panic(err) + } + + err = json.Unmarshal(bytes, &opt) + if err != nil { + os.Stderr.Write([]byte(err.Error())) + panic(err) + } + + parsedResult := numscript.Parse(opt.Script) + errors := parsedResult.GetParsingErrors() + + if len(errors) != 0 { + os.Stderr.Write([]byte(numscript.ParseErrorsToString(errors, opt.Script))) + panic(fmt.Errorf("parsing errors")) + } + + result, err := parsedResult.RunWithFeatureFlags( + context.Background(), + opt.Variables, + numscript.StaticStore{ + Balances: opt.Balances, + Meta: opt.Meta, + }, + opt.FeatureFlags, + ) + + if err != nil { + os.Stderr.Write([]byte(err.Error())) + panic(err) + } + + out, err := json.Marshal(result) + if err != nil { + os.Stderr.Write([]byte(err.Error())) + panic(err) + } + + os.Stdout.Write(out) +} + +var runCmd = &cobra.Command{ + Use: "run", + Short: "Execute a numscript", + Long: "Execute a numscript using the balances, the current metadata, and the variables values as input. Also accept feature flags to enable experimental features.", + Run: func(cmd *cobra.Command, args []string) { + run() + }, +} + +var rootCmd = &cobra.Command{ + Use: "numscript", + Short: "Numscript CLI", + Long: "Numscript CLI", + Version: version(), + CompletionOptions: cobra.CompletionOptions{ + DisableDefaultCmd: true, + }, +} + +func main() { + defer func() { + if err := recover(); err != nil { + fmt.Fprintf(os.Stderr, "Exception: %v\n", err) + os.Exit(1) + } + }() + + rootCmd.SetVersionTemplate(rootCmd.Version) + + rootCmd.AddCommand(versionCmd) + rootCmd.AddCommand(runCmd) + rootCmd.Execute() +} diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..66c5975 --- /dev/null +++ b/main_test.go @@ -0,0 +1,495 @@ +package main + +import ( + "bytes" + "encoding/json" + "io" + "os" + "testing" +) + +func TestVersionCommand(t *testing.T) { + tests := []struct { + name string + versionVar string + expectedOutput string + }{ + { + name: "version set", + versionVar: "1.0.0", + expectedOutput: "1.0.0", + }, + { + name: "version empty", + versionVar: "", + expectedOutput: "dev", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Set version variable + oldVersion := Version + Version = tt.versionVar + defer func() { Version = oldVersion }() + + // Capture output + output := captureOutput(func() { + versionCmd.Run(versionCmd, []string{}) + }) + + if output != tt.expectedOutput { + t.Errorf("expected %q, got %q", tt.expectedOutput, output) + } + }) + } +} + +func TestVersionFunction(t *testing.T) { + tests := []struct { + name string + versionVar string + expected string + }{ + { + name: "version set", + versionVar: "1.2.3", + expected: "1.2.3", + }, + { + name: "version empty", + versionVar: "", + expected: "dev", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + oldVersion := Version + Version = tt.versionVar + defer func() { Version = oldVersion }() + + result := version() + if result != tt.expected { + t.Errorf("expected %q, got %q", tt.expected, result) + } + }) + } +} + +func TestRunCommand(t *testing.T) { + tests := []struct { + name string + inputJSON string + expectedOutputJSON string + }{ + { + name: "valid simple script", + inputJSON: `{ + "script": "send [USD/2 100] (source = @foo destination = @bar)", + "variables": {}, + "metadata": {}, + "balances": { + "foo": { + "USD/2": 100, + "EUR/2": 100 + } + }, + "featureFlags": {} + }`, + expectedOutputJSON: `{ + "postings": [ + { + "source": "foo", + "destination": "bar", + "amount": 100, + "asset": "USD/2" + } + ], + "txMeta": {}, + "accountsMeta": {} + }`, + }, + { + name: "valid script with feature flag", + inputJSON: `{ + "script": "vars { monetary $mon = [USD/2 100] \n number $n = get_amount($mon) \n } send [USD/2 $n] ( source = { oneof { @foo @bar } } destination = @dest )", + "variables": {}, + "metadata": {}, + "balances": { + "foo": { + "USD/2": 100, + "EUR/2": 100 + } + }, + "featureFlags": { + "experimental-oneof": {}, + "experimental-get-amount-function": {}, + "experimental-mid-script-function-call": {} + } + }`, + expectedOutputJSON: `{ + "postings": [ + { + "source": "foo", + "destination": "dest", + "amount": 100, + "asset": "USD/2" + } + ], + "txMeta": {}, + "accountsMeta": {} + }`, + }, + { + name: "empty script", + inputJSON: `{ + "script": "", + "variables": {}, + "metadata": {}, + "balances": { + "foo": { + "USD/2": 100 + } + }, + "featureFlags": {} + }`, + expectedOutputJSON: `{ + "postings": [], + "txMeta": {}, + "accountsMeta": {} + }`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + inputJSON := []byte(tt.inputJSON) + + // Create a pipe to simulate stdin + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("failed to create pipe: %v", err) + } + + // Save original stdin + originalStdin := os.Stdin + defer func() { os.Stdin = originalStdin }() + + // Set our pipe as stdin + os.Stdin = r + + // Write input to pipe + go func() { + defer w.Close() + w.Write(inputJSON) + }() + + // Capture stdout and stderr + var stdout, stderr bytes.Buffer + originalStdout := os.Stdout + originalStderr := os.Stderr + defer func() { + os.Stdout = originalStdout + os.Stderr = originalStderr + }() + + // Create pipes for stdout and stderr + rOut, wOut, _ := os.Pipe() + rErr, wErr, _ := os.Pipe() + os.Stdout = wOut + os.Stderr = wErr + + // Capture output in goroutines with proper synchronization + stdoutDone := make(chan bool) + stderrDone := make(chan bool) + + go func() { + io.Copy(&stdout, rOut) + rOut.Close() + stdoutDone <- true + }() + go func() { + io.Copy(&stderr, rErr) + rErr.Close() + stderrDone <- true + }() + + // Run the function in a goroutine to handle panics + done := make(chan bool) + go func() { + defer func() { + if r := recover(); r != nil { + // Handle panic from run() + // It is empty because the error is already captured by stderr + } + done <- true + }() + run() + }() + + // Wait for completion + <-done + + // Close write ends to flush + wOut.Close() + wErr.Close() + + // Wait for all copying to complete + <-stdoutDone + <-stderrDone + + // Check results + if stderr.Len() > 0 { + t.Errorf("unexpected error output: %s", stderr.String()) + } + + if stdout.Len() > 0 { + // Parse actual output + var actualResult map[string]any + err := json.Unmarshal(stdout.Bytes(), &actualResult) + if err != nil { + t.Errorf("actual output is not valid JSON: %v\nOutput: %s", err, stdout.String()) + return + } + + // Parse expected output + var expectedResult map[string]any + err = json.Unmarshal([]byte(tt.expectedOutputJSON), &expectedResult) + if err != nil { + t.Errorf("expected output is not valid JSON: %v", err) + return + } + + // Compare the structures + if !compareJSONObjects(actualResult, expectedResult) { + actualJSON, _ := json.MarshalIndent(actualResult, "", " ") + expectedJSON, _ := json.MarshalIndent(expectedResult, "", " ") + t.Errorf("Output mismatch:\nActual:\n%s\n\nExpected:\n%s", actualJSON, expectedJSON) + } + } else { + t.Error("expected output, got none") + } + }) + } +} + +func TestRunCommandWithInvalidInput(t *testing.T) { + tests := []struct { + name string + inputJSON string + expectedError string + }{ + { + name: "invalid JSON", + inputJSON: "invalid json", + expectedError: "invalid character 'i' looking for beginning of value", + }, + { + name: "malformed JSON object", + inputJSON: `{"script": "send [USD 100]", invalid}`, + expectedError: "invalid character 'i' looking for beginning of object key string", + }, + { + name: "invalid script", + inputJSON: `{ + "script": "send [USD/2 100] (source @foo destination = @bar)", + "variables": {}, + "metadata": {}, + "balances": { + "foo": { + "USD/2": 100, + "EUR/2": 100 + } + }, + "featureFlags": {} + }`, + expectedError: "Got errors while parsing:\nmissing '=' at '@'\n 0 | send [USD/2 100] (source @foo destination = @bar)\n | \n", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + inputJSON := []byte(tt.inputJSON) + + // Create a pipe to simulate stdin + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("failed to create pipe: %v", err) + } + + // Save original stdin + originalStdin := os.Stdin + defer func() { os.Stdin = originalStdin }() + + // Set our pipe as stdin + os.Stdin = r + + // Write input to pipe + go func() { + defer w.Close() + w.Write(inputJSON) + }() + + // Capture stdout and stderr + var stdout, stderr bytes.Buffer + originalStdout := os.Stdout + originalStderr := os.Stderr + defer func() { + os.Stdout = originalStdout + os.Stderr = originalStderr + }() + + // Create pipes for stdout and stderr + rOut, wOut, _ := os.Pipe() + rErr, wErr, _ := os.Pipe() + os.Stdout = wOut + os.Stderr = wErr + + // Capture output in goroutines with proper synchronization + stdoutDone := make(chan bool) + stderrDone := make(chan bool) + + go func() { + io.Copy(&stdout, rOut) + rOut.Close() + stdoutDone <- true + }() + go func() { + io.Copy(&stderr, rErr) + rErr.Close() + stderrDone <- true + }() + + // Run the function in a goroutine to handle panics + done := make(chan bool) + go func() { + defer func() { + if r := recover(); r != nil { + // Handle panic from run() + // It is empty because the error is already captured by stderr + } + done <- true + }() + run() + }() + + // Wait for completion + <-done + + // Close write ends to flush + wOut.Close() + wErr.Close() + + // Wait for all copying to complete + <-stdoutDone + <-stderrDone + + // Check results + if stderr.Len() > 0 { + errorOutput := stderr.String() + if errorOutput != tt.expectedError { + t.Errorf("Error output mismatch.\nExpected: %s\nActual: %s", tt.expectedError, errorOutput) + } + } else { + t.Error("expected error output, got none") + } + }) + } +} + +// Helper function to compare JSON objects deeply +func compareJSONObjects(actual, expected map[string]any) bool { + if len(actual) != len(expected) { + return false + } + + for key, expectedValue := range expected { + actualValue, exists := actual[key] + if !exists { + return false + } + + if !compareJSONValues(actualValue, expectedValue) { + return false + } + } + + return true +} + +// Helper function to compare JSON values of any type +func compareJSONValues(actual, expected any) bool { + switch expectedVal := expected.(type) { + case map[string]any: + actualMap, ok := actual.(map[string]any) + if !ok { + return false + } + return compareJSONObjects(actualMap, expectedVal) + case []any: + actualArray, ok := actual.([]any) + if !ok { + return false + } + if len(actualArray) != len(expectedVal) { + return false + } + for i, expectedItem := range expectedVal { + if !compareJSONValues(actualArray[i], expectedItem) { + return false + } + } + return true + default: + return actual == expected + } +} + +// Helper function to capture output from a function +func captureOutput(f func()) string { + var stdout, stderr bytes.Buffer + originalStdout := os.Stdout + originalStderr := os.Stderr + defer func() { + os.Stdout = originalStdout + os.Stderr = originalStderr + }() + + rOut, wOut, err := os.Pipe() + if err != nil { + panic(err) + } + rErr, wErr, err := os.Pipe() + if err != nil { + panic(err) + } + + os.Stdout = wOut + os.Stderr = wErr + + stdoutDone := make(chan bool) + stderrDone := make(chan bool) + + go func() { + io.Copy(&stdout, rOut) + rOut.Close() + stdoutDone <- true + }() + go func() { + io.Copy(&stderr, rErr) + rErr.Close() + stderrDone <- true + }() + + f() + wOut.Close() + wErr.Close() + + <-stdoutDone + <-stderrDone + + // Return combined output (stdout first, then stderr) + combined := stdout.String() + stderr.String() + return combined +} diff --git a/numscript.go b/numscript.go deleted file mode 100644 index e34ad34..0000000 --- a/numscript.go +++ /dev/null @@ -1,81 +0,0 @@ -package numscript - -import ( - "context" - - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - "github.com/PagoPlus/numscript-wasm/internal/parser" -) - -// This struct represents a parsed numscript source code -type ParseResult struct { - parseResult parser.ParseResult -} - -// ---- TODO useful for the playground -// func (*ParseResult) GetNeededVariables() map[string]ValueType {} -// func (*ParseResult) GetDiagnostics() []Diagnostic {} - -type ParserError = parser.ParserError - -func Parse(code string) ParseResult { - return ParseResult{parseResult: parser.Parse(code)} -} - -var ParseErrorsToString = parser.ParseErrorsToString - -func (p ParseResult) GetParsingErrors() []ParserError { - return p.parseResult.Errors -} - -type ( - VariablesMap = interpreter.VariablesMap - Posting = interpreter.Posting - ExecutionResult = interpreter.ExecutionResult - // For each account, list of the needed assets - BalanceQuery = interpreter.BalanceQuery - MetadataQuery = interpreter.MetadataQuery - AccountBalance = interpreter.AccountBalance - Balances = interpreter.Balances - - AccountMetadata = interpreter.AccountMetadata - - // The newly defined account metadata after the execution - AccountsMetadata = interpreter.AccountsMetadata - - // The transaction metadata, set by set_tx_meta() - Metadata = interpreter.Metadata - - Store = interpreter.Store - - StaticStore = interpreter.StaticStore - - Value = interpreter.Value - - InterpreterError = interpreter.InterpreterError -) - -func (p ParseResult) Run(ctx context.Context, vars VariablesMap, store Store) (ExecutionResult, InterpreterError) { - return p.RunWithFeatureFlags(ctx, vars, store, nil) -} - -func (p ParseResult) RunWithFeatureFlags( - ctx context.Context, - vars VariablesMap, - store Store, - featureFlags map[string]struct{}, -) (ExecutionResult, InterpreterError) { - if featureFlags == nil { - featureFlags = make(map[string]struct{}) - } - - res, err := interpreter.RunProgram(ctx, p.parseResult.Value, vars, store, featureFlags) - if err != nil { - return ExecutionResult{}, err - } - return *res, nil -} - -func (p ParseResult) GetSource() string { - return p.parseResult.Source -} diff --git a/numscript_test.go b/numscript_test.go deleted file mode 100644 index 5772364..0000000 --- a/numscript_test.go +++ /dev/null @@ -1,362 +0,0 @@ -package numscript_test - -import ( - "context" - "errors" - "math/big" - "testing" - - numscript "github.com/PagoPlus/numscript-wasm" - "github.com/PagoPlus/numscript-wasm/internal/interpreter" - "github.com/stretchr/testify/require" -) - -func TestDoNotGetWorldBalance(t *testing.T) { - parseResult := numscript.Parse(`send [COIN 100] ( - source = @world - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - store := ObservableStore{ - StaticStore: interpreter.StaticStore{ - Balances: interpreter.Balances{}, - Meta: interpreter.AccountsMetadata{}, - }, - } - _, err := parseResult.Run(context.Background(), numscript.VariablesMap{}, - &store, - ) - require.Nil(t, err) - - require.Equal(t, - ([]numscript.BalanceQuery)(nil), - store.GetBalancesCalls) -} - -func TestGetBalancesInorder(t *testing.T) { - parseResult := numscript.Parse(`vars { - account $s1 - account $s2 = meta(@account_that_needs_meta, "k") - number $b = balance(@account_that_needs_balance, USD/2) -} - -send [COIN 100] ( - source = { - $s1 - $s2 - @source3 - @world - } - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - store := ObservableStore{ - StaticStore: interpreter.StaticStore{ - Balances: interpreter.Balances{}, - Meta: interpreter.AccountsMetadata{"account_that_needs_meta": {"k": "source2"}}, - }, - } - _, err := parseResult.Run(context.Background(), numscript.VariablesMap{ - "s1": "source1", - }, - &store, - ) - require.Nil(t, err) - - require.Equal(t, - []numscript.MetadataQuery{ - { - "account_that_needs_meta": {"k"}, - }, - }, - store.GetMetadataCalls) - - require.Equal(t, - []numscript.BalanceQuery{ - // TODO maybe those calls can be batched together - { - // this is required by the balance() call - "account_that_needs_balance": {"USD/2"}, - }, - { - // this is defined in the variables - "source1": {"COIN"}, - - // this is defined in account metadata - "source2": {"COIN"}, - - // this appears as literal - "source3": {"COIN"}, - }, - }, - store.GetBalancesCalls) -} - -func TestDoNotGetBalancesTwice(t *testing.T) { - parseResult := numscript.Parse(`send [COIN 100] ( - source = { - @alice - @alice - @world - } - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - store := ObservableStore{ - StaticStore: interpreter.StaticStore{ - Balances: interpreter.Balances{}, - }, - } - _, err := parseResult.Run(context.Background(), numscript.VariablesMap{}, &store) - require.Nil(t, err) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "alice": {"COIN"}, - }, - }, - store.GetBalancesCalls) -} - -func TestGetBalancesAllotment(t *testing.T) { - parseResult := numscript.Parse(`send [COIN 100] ( - source = { - 1/2 from @a - remaining from @b - } - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - store := ObservableStore{ - StaticStore: interpreter.StaticStore{ - Balances: interpreter.Balances{ - "a": {"COIN": big.NewInt(10000)}, - "b": {"COIN": big.NewInt(10000)}, - }, - }, - } - - _, err := parseResult.Run(context.Background(), - numscript.VariablesMap{}, - &store, - ) - require.Nil(t, err) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "a": {"COIN"}, - "b": {"COIN"}, - }, - }, - store.GetBalancesCalls) -} - -func TestGetBalancesOverdraft(t *testing.T) { - parseResult := numscript.Parse(`send [COIN 100] ( - source = { - @a allowing overdraft up to [COIN 10] - @b allowing unbounded overdraft - } - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - store := ObservableStore{} - - _, err := parseResult.Run(context.Background(), interpreter.VariablesMap{}, &store) - require.Nil(t, err) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "a": {"COIN"}, - }, - }, - store.GetBalancesCalls) -} - -func TestDoNotFetchBalanceTwice(t *testing.T) { - parseResult := numscript.Parse(`vars { monetary $v = balance(@src, COIN) } - - send $v ( - source = @src - destination = @dest - )`) - - store := ObservableStore{} - parseResult.Run(context.Background(), nil, &store) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "src": {"COIN"}, - }, - }, - store.GetBalancesCalls, - ) - -} - -func TestDoNotFetchBalanceTwice2(t *testing.T) { - // same test as before, but this time the second batch is not empty - parseResult := numscript.Parse(`vars { monetary $v = balance(@src1, COIN) } - - send $v ( - source = { - @src1 - @src2 - } - destination = @dest - )`) - - store := ObservableStore{} - parseResult.Run(context.Background(), nil, &store) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "src1": {"COIN"}, - }, - { - "src2": {"COIN"}, - }, - }, - store.GetBalancesCalls, - ) - -} - -func TestDoNotFetchBalanceTwice3(t *testing.T) { - // same test as before, but this time the second batch requires a _different asset_ - parseResult := numscript.Parse(`vars { monetary $eur_m = balance(@src, EUR/2) } - - - send [USD/2 100] ( - // note here we are fetching a different currency - source = @src - destination = @dest - ) -`) - - store := ObservableStore{} - parseResult.Run(context.Background(), nil, &store) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "src": {"EUR/2"}, - }, - { - "src": {"USD/2"}, - }, - }, - store.GetBalancesCalls, - ) - -} - -func TestQueryBalanceErr(t *testing.T) { - parseResult := numscript.Parse(`send [COIN 100] ( - source = @src - destination = @dest -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - _, err := parseResult.Run(context.Background(), interpreter.VariablesMap{}, &ErrorStore{}) - require.IsType(t, err, interpreter.QueryBalanceError{}) -} - -func TestMetadataFetchErr(t *testing.T) { - parseResult := numscript.Parse(`vars { - number $x = meta(@acc, "k") -}`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - _, err := parseResult.Run(context.Background(), interpreter.VariablesMap{}, &ErrorStore{}) - require.IsType(t, err, interpreter.QueryMetadataError{}) -} - -func TestBalanceFunctionErr(t *testing.T) { - parseResult := numscript.Parse(`vars { - monetary $x = balance(@acc, USD/2) -}`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - _, err := parseResult.Run(context.Background(), interpreter.VariablesMap{}, &ErrorStore{}) - require.IsType(t, err, interpreter.QueryBalanceError{}) -} - -func TestSaveQuery(t *testing.T) { - parseResult := numscript.Parse(` -save [USD/2 10] from @alice - -send [USD/2 30] ( - source = { - @alice - @world - } - destination = @bob -) -`) - - require.Empty(t, parseResult.GetParsingErrors(), "There should not be parsing errors") - - store := ObservableStore{} - parseResult.Run(context.Background(), nil, &store) - - require.Equal(t, - []numscript.BalanceQuery{ - { - "alice": {"USD/2"}, - }, - }, - store.GetBalancesCalls, - ) - -} - -type ObservableStore struct { - StaticStore interpreter.StaticStore - GetBalancesCalls []numscript.BalanceQuery - GetMetadataCalls []numscript.MetadataQuery -} - -func (os *ObservableStore) GetBalances(ctx context.Context, q interpreter.BalanceQuery) (interpreter.Balances, error) { - os.GetBalancesCalls = append(os.GetBalancesCalls, q) - return os.StaticStore.GetBalances(ctx, q) - -} - -func (os *ObservableStore) GetAccountsMetadata(ctx context.Context, q interpreter.MetadataQuery) (interpreter.AccountsMetadata, error) { - os.GetMetadataCalls = append(os.GetMetadataCalls, q) - return os.StaticStore.GetAccountsMetadata(ctx, q) -} - -type ErrorStore struct{} - -func (*ErrorStore) GetBalances(ctx context.Context, q interpreter.BalanceQuery) (interpreter.Balances, error) { - return nil, errors.New("Error while fetching balances") -} - -func (*ErrorStore) GetAccountsMetadata(ctx context.Context, q interpreter.MetadataQuery) (interpreter.AccountsMetadata, error) { - return nil, errors.New("Error while fetching metadata") -}