diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 2700635531..a6be162cda 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -13,7 +13,7 @@ on: - 'v**' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9601b694a2..5a5e483d72 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ on: - 'v**' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index eab3c6b3f8..f7be868fdf 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,7 +13,7 @@ on: - 'v**' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} diff --git a/.github/workflows/compatibility-check-template.yml b/.github/workflows/compatibility-check-template.yml index d406cc9db7..fb849eafda 100644 --- a/.github/workflows/compatibility-check-template.yml +++ b/.github/workflows/compatibility-check-template.yml @@ -21,7 +21,7 @@ on: type: string env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ inputs.base-branch || github.run_id }}-${{ inputs.chain }} @@ -113,6 +113,5 @@ jobs: # Check Diff - name: Check diff - working-directory: ./tools/compatibility-check run: | - go run ./cmd/check_diff/main.go ../../tmp/output-old.txt ../../tmp/output-new.txt + diff -u --color ./tmp/output-old.txt ./tmp/output-new.txt diff --git a/.github/workflows/compatibility-check.yml b/.github/workflows/compatibility-check.yml index 98456f56c3..7c79e5ce10 100644 --- a/.github/workflows/compatibility-check.yml +++ b/.github/workflows/compatibility-check.yml @@ -23,7 +23,7 @@ on: - 'v**' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ inputs.base || github.run_id }} @@ -53,7 +53,7 @@ jobs: echo "branch=`(echo "${{ github.event.pull_request.head.sha }}")`" >> $GITHUB_OUTPUT echo "base=`(echo "${{ github.base_ref }}")`" >> $GITHUB_OUTPUT else - echo "repo=`(echo "${{ inputs.repo || 'onflow/cadence' }}")`" >> $GITHUB_OUTPUT + echo "repo=`(echo "${{ inputs.repo || github.repository }}")`" >> $GITHUB_OUTPUT echo "branch=`(echo "${{ inputs.branch }}")`" >> $GITHUB_OUTPUT echo "base=`(echo "${{ inputs.base }}")`" >> $GITHUB_OUTPUT fi diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index aafb3c40a8..bcdb98447a 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -13,7 +13,7 @@ on: - 'v**' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} @@ -39,7 +39,7 @@ jobs: run: sh crypto_setup.sh - name: Update Cadence - run: go mod edit -replace github.com/onflow/cadence=github.com/${{ github.event.pull_request.head.repo.full_name }}@${{ github.event.pull_request.head.sha }} + run: go mod edit -replace github.com/onflow/cadence=github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}@${{ github.event.pull_request.head.sha || github.sha }} - name: Tidy up run: go mod tidy @@ -63,7 +63,7 @@ jobs: cache: true - name: Update Cadence - run: go mod edit -replace github.com/onflow/cadence=github.com/${{ github.event.pull_request.head.repo.full_name }}@${{ github.event.pull_request.head.sha }} + run: go mod edit -replace github.com/onflow/cadence=github.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}@${{ github.event.pull_request.head.sha || github.sha }} - name: Tidy up run: go mod tidy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b51740600f..d79b11148c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ on: default: 'master' env: - GO_VERSION: '1.19.2' + GO_VERSION: '1.20' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} diff --git a/encoding/json/decode.go b/encoding/json/decode.go index 3768d3df7f..1c7d25997c 100644 --- a/encoding/json/decode.go +++ b/encoding/json/decode.go @@ -301,7 +301,7 @@ func (d *Decoder) decodeAddress(valueJSON any) cadence.Address { actualPrefix := v[:prefixLength] if actualPrefix != addressPrefix { panic(errors.NewDefaultUserError( - "invalid address prefix: expected `%s`, got `%s`", + "invalid address prefix: (shown as hex) expected %x, got %x", // hex encoding user input (actualPrefix) avoids invalid UTF-8. addressPrefix, actualPrefix, )) diff --git a/encoding/json/encoding_test.go b/encoding/json/encoding_test.go index 1a5ed48b4c..65afb32b94 100644 --- a/encoding/json/encoding_test.go +++ b/encoding/json/encoding_test.go @@ -197,6 +197,16 @@ func TestEncodeAddress(t *testing.T) { ) } +func TestDecodeInvalidAddress(t *testing.T) { + + t.Parallel() + + msg := `{"type":"Address","value":"000000000102030405"}` + + _, err := json.Decode(nil, []byte(msg)) + require.ErrorContains(t, err, "invalid address prefix: (shown as hex) expected 3078, got 3030") +} + func TestEncodeInt(t *testing.T) { t.Parallel() diff --git a/go.cap b/go.cap index 34dba49742..bb341c9fa6 100644 --- a/go.cap +++ b/go.cap @@ -10,3 +10,4 @@ github.com/stretchr/testify/require (network) github.com/texttheater/golang-levenshtein/levenshtein (file) github.com/zeebo/blake3/internal/consts (file) golang.org/x/xerrors (runtime) +github.com/onflow/cadence/runtime/interpreter (runtime) diff --git a/go.mod b/go.mod index dcfe9cae70..6dfc1fb807 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/cadence -go 1.18 +go 1.20 require ( github.com/bits-and-blooms/bitset v1.5.0 diff --git a/meetings/2023-08-15.md b/meetings/2023-08-15.md new file mode 100644 index 0000000000..f215b35d68 --- /dev/null +++ b/meetings/2023-08-15.md @@ -0,0 +1,167 @@ +# Aug 14th, 2023 + +## Ways to contribute + +* Participate in [FLIP (Flow Improvement Proposal) discussions](https://github.com/onflow/flips) +* Contribute to Cadence implementation: ➑️[GitHub issues](https://github.com/onflow/cadence/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Good+First+Issue%22) +* Contribute Cadence tools: ➑️[GitHub issues](https://github.com/onflow/cadence-tools/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Good+First+Issue%22) + +## FLIPs + +### Interface Conformance Improvements + +* FLIP: [https://github.com/onflow/flips/pull/83](https://github.com/onflow/flips/pull/83) +* Status: + * FLIP approved and merged πŸŽ‰ + +### Remove pub, pub(set) and priv + +* FLIP: [https://github.com/onflow/flips/pull/84](https://github.com/onflow/flips/pull/84) +* Status: + * FLIP approved and merged πŸŽ‰ + +### Emit events from function conditions, allow concrete events in interfaces + +* FLIP: [https://github.com/onflow/flips/pull/111](https://github.com/onflow/flips/pull/111) +* Status: + * FLIP approved and merged πŸŽ‰ + +### Remove restricted types, interface set types + +* FLIP: [https://github.com/onflow/flips/pull/85](https://github.com/onflow/flips/pull/85) +* Status: + * FLIP approved and merged πŸŽ‰ + +### Add Range type + +* FLIP: [https://github.com/onflow/flips/pull/96](https://github.com/onflow/flips/pull/96) +* Status: + * FLIP approved and merged πŸŽ‰ + +### External Mutability + +* Vision: [https://github.com/onflow/flips/pull/97](https://github.com/onflow/flips/pull/97) +* FLIPs: + * **Change member access semantic** + * FLIP: [https://github.com/onflow/flips/pull/89](https://github.com/onflow/flips/pull/89) + * Status: + * FLIP approved and merged πŸŽ‰ + * **Improve entitlement mappings** + * FLIP: [https://github.com/onflow/flips/pull/94](https://github.com/onflow/flips/pull/94) + * Status: + * FLIP approved and merged πŸŽ‰ + * **Introduce built-in mutability entitlements** + * FLIP: [https://github.com/onflow/flips/pull/86](https://github.com/onflow/flips/pull/86) + * Status: + * Positive sentiment + * No new feedback in last few weeks + * Implementation and documentation ready + * Last conversation was about naming convention for entitlements + * Open problems: + * None + * Next steps: + * **Approved** + +### Account Type + +* FLIP: [https://github.com/onflow/flips/pull/92](https://github.com/onflow/flips/pull/92) +* Status: + * Positive sentiment + * No new feedback in last few weeks + * Implementation ready +* Open problems: + * None +* Next steps: + * **Approved** + +### Remove nested type requirements + +* FLIP: [https://github.com/onflow/flips/pull/118](https://github.com/onflow/flips/pull/118) +* Overview: + * Remove nested type requirements + * Allow declaration of events in interfaces as concrete types (used in core contracts) +* Status: + * Positive sentiment + * No new feedback in last few weeks + * Implementation ready (2 PRs) +* Open problems: + * None +* Next steps: + * **Approved** + +### Random function + +* FLIP: [https://github.com/onflow/flips/pull/118](https://github.com/onflow/flips/pull/118) +* Overview: + * Rename unsafeRandom to random, underlying implementation has been secured using Flow protocol native random beacon + * Update the interface to a safer and more convenient one (generalized types and a modulo parameter) + * Rollout: add random, deprecate unsafeRandom, finally remove in SC release +* Status: + * Positive sentiment for random +* Open problems: + * Behavior in scripts + * Should not panic + * Several options + * Naming: + * Potential for misuse by developers. Unsafe β†’ safe renaming might be confusing + * Maybe addressed by commit-reveal scheme FLIP: [https://github.com/onflow/flips/pull/123](https://github.com/onflow/flips/pull/123) +* Next steps: + * Determine script behavior, maybe propose in separate FLIP + * Schedule breakout session + * Deniz + * You? Leave a comment! +* Feedback: + * Just switch unsafeRandom to safe random generator for now + * Different name/indicator to prevent misuse? + * Trigger developers to check documentation, see/use commit-reveal scheme design pattern to use returned safe random properly + * `random(iReadTheDocs: Bool)` + * Our bar is very high, other systems isn't + +### Commit-reveal scheme for non-reverted randomness + +* FLIP: [https://github.com/onflow/flips/pull/123](https://github.com/onflow/flips/pull/123) +* Overview: + * Provide a safe pattern to address transaction abortion after a random is revealed + * Commit to block + * In the future, query history of past randoms + * Use past, committed seed for new random +* Status: + * Positive sentiment + * Waiting for feedback +* Open problems: + * None +* Next steps: + * Gather more feedback + +### Remove custom destructors + +* FLIP: [https://github.com/onflow/flips/pull/131](https://github.com/onflow/flips/pull/131) +* Overview: + * Proposal to address inability for users to destroy resources they own + * One of the discussed options (others: try/catch, etc.) + * Originated from attachments feature (attachment might prevent destruction of whole resource) + * Remove destroy + * Allows users to always destroy resources +* Status: + * New + * Very much an RFC! +* Open problems: + * Philosophical question (sending to "burner account") + * Existing code / applications + * "Migration" path for use-cases like FT total supply +* Next steps: + * Discuss + * Breakout session + * You? Leave a comment! + * Publish resource destruction options document, add to FLIP +* Feedback: + * Provide details on impact on applications, e.g. core contracts like FT/NFT + * Chicken-and-egg problem: need more data on how feature is used, can then figure out if/what alternative is + * Even if exploit vector isn’t used today, it should be addressed/prevented + * If important use-case exists, also not worth it to remove + * Emitting events could maybe be allowed + * Given impact, reach out to more developers / gather more feedback + +## Related FLIPs / forum discussions + +* [https://forum.onflow.org/t/storage-fees-improvements-and-few-random-ideas-on-the-way/5104](https://forum.onflow.org/t/storage-fees-improvements-and-few-random-ideas-on-the-way/5104) \ No newline at end of file diff --git a/npm-packages/cadence-parser/package.json b/npm-packages/cadence-parser/package.json index c33546050b..eb05dc83e8 100644 --- a/npm-packages/cadence-parser/package.json +++ b/npm-packages/cadence-parser/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/cadence-parser", - "version": "0.39.12", + "version": "0.40.0", "description": "The Cadence parser", "homepage": "https://github.com/onflow/cadence", "repository": { diff --git a/runtime/account_test.go b/runtime/account_test.go index a38777893a..a16a731a70 100644 --- a/runtime/account_test.go +++ b/runtime/account_test.go @@ -2361,7 +2361,7 @@ func TestGetAuthAccount(t *testing.T) { errs := checker.RequireCheckerErrors(t, err, 1) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.InsufficientArgumentsError{}, errs[0]) }) t.Run("too many args", func(t *testing.T) { @@ -2388,7 +2388,7 @@ func TestGetAuthAccount(t *testing.T) { ) errs := checker.RequireCheckerErrors(t, err, 1) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.ExcessiveArgumentsError{}, errs[0]) }) t.Run("transaction", func(t *testing.T) { diff --git a/runtime/capabilitycontrollers_test.go b/runtime/capabilitycontrollers_test.go index 916fa950b2..fcdbabe440 100644 --- a/runtime/capabilitycontrollers_test.go +++ b/runtime/capabilitycontrollers_test.go @@ -2500,6 +2500,43 @@ func TestRuntimeCapabilityControllers(t *testing.T) { t.Parallel() + t.Run("capability", func(t *testing.T) { + t.Parallel() + + err, _ := test( + // language=cadence + ` + import Test from 0x1 + + transaction { + prepare(signer: AuthAccount) { + let storagePath = /storage/r + let resourceID = 42 + + // Arrange + Test.createAndSaveR(id: resourceID, storagePath: storagePath) + + let issuedCap: Capability<&Test.R> = + signer.capabilities.storage.issue<&Test.R>(storagePath) + let controller1: &StorageCapabilityController = + signer.capabilities.storage.getController(byCapabilityID: issuedCap.id)! + let controller2: &StorageCapabilityController = + signer.capabilities.storage.getController(byCapabilityID: issuedCap.id)! + + // Act + let controller1Cap = controller1.capability + let controller2Cap = controller2.capability + + // Assert + assert(controller1Cap.borrow<&Test.R>() != nil) + assert(controller2Cap.borrow<&Test.R>() != nil) + } + } + `, + ) + require.NoError(t, err) + }) + t.Run("tag", func(t *testing.T) { t.Parallel() @@ -2981,6 +3018,39 @@ func TestRuntimeCapabilityControllers(t *testing.T) { t.Parallel() + t.Run("capability", func(t *testing.T) { + t.Parallel() + + err, _ := test( + // language=cadence + ` + import Test from 0x1 + + transaction { + prepare(signer: AuthAccount) { + + // Arrange + let issuedCap: Capability<&AuthAccount> = + signer.capabilities.account.issue<&AuthAccount>() + let controller1: &AccountCapabilityController = + signer.capabilities.account.getController(byCapabilityID: issuedCap.id)! + let controller2: &AccountCapabilityController = + signer.capabilities.account.getController(byCapabilityID: issuedCap.id)! + + // Act + let controller1Cap = controller1.capability + let controller2Cap = controller2.capability + + // Assert + assert(controller1Cap.borrow<&AuthAccount>() != nil) + assert(controller2Cap.borrow<&AuthAccount>() != nil) + } + } + `, + ) + require.NoError(t, err) + }) + t.Run("tag", func(t *testing.T) { t.Parallel() diff --git a/runtime/environment.go b/runtime/environment.go index 631d8456db..153d2ed217 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -219,8 +219,8 @@ func (e *interpreterEnvironment) ProgramLog(message string) error { return e.runtimeInterface.ProgramLog(message) } -func (e *interpreterEnvironment) UnsafeRandom() (uint64, error) { - return e.runtimeInterface.UnsafeRandom() +func (e *interpreterEnvironment) ReadRandom(buffer []byte) error { + return e.runtimeInterface.ReadRandom(buffer) } func (e *interpreterEnvironment) GetBlockAtHeight(height uint64) (block stdlib.Block, exists bool, err error) { @@ -431,6 +431,10 @@ func (e *interpreterEnvironment) newLocationHandler() sema.LocationHandlerFunc { errors.WrapPanic(func() { res, err = e.runtimeInterface.ResolveLocation(identifiers, location) }) + + if err != nil { + err = interpreter.WrappedExternalError(err) + } return } } @@ -560,6 +564,11 @@ func (e *interpreterEnvironment) getProgram( if panicErr != nil { return nil, panicErr } + + if err != nil { + err = interpreter.WrappedExternalError(err) + } + return }) }) @@ -577,6 +586,11 @@ func (e *interpreterEnvironment) getCode(location common.Location) (code []byte, code, err = e.runtimeInterface.GetCode(location) }) } + + if err != nil { + err = interpreter.WrappedExternalError(err) + } + return } @@ -745,6 +759,10 @@ func (e *interpreterEnvironment) newUUIDHandler() interpreter.UUIDHandlerFunc { errors.WrapPanic(func() { uuid, err = e.runtimeInterface.GenerateUUID() }) + + if err != nil { + err = interpreter.WrappedExternalError(err) + } return } } @@ -941,7 +959,7 @@ func (e *interpreterEnvironment) newOnMeterComputation() interpreter.OnMeterComp err = e.runtimeInterface.MeterComputation(compKind, intensity) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } } } diff --git a/runtime/error_test.go b/runtime/error_test.go index 4b3eacd749..1d02f014c3 100644 --- a/runtime/error_test.go +++ b/runtime/error_test.go @@ -25,9 +25,12 @@ import ( "github.com/stretchr/testify/require" + "github.com/onflow/cadence" "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" + "github.com/onflow/cadence/runtime/stdlib" ) func TestRuntimeError(t *testing.T) { @@ -493,3 +496,259 @@ func TestRuntimeError(t *testing.T) { }) } + +func TestRuntimeDefaultFunctionConflictPrintingError(t *testing.T) { + t.Parallel() + + runtime := newTestInterpreterRuntime() + + makeDeployTransaction := func(name, code string) []byte { + return []byte(fmt.Sprintf( + ` + transaction { + prepare(signer: AuthAccount) { + let acct = AuthAccount(payer: signer) + acct.contracts.add(name: "%s", code: "%s".decodeHex()) + } + } + `, + name, + hex.EncodeToString([]byte(code)), + )) + } + + contractInterfaceCode := ` + access(all) contract TestInterfaces { + + access(all) resource interface A { + access(all) fun foo() { + let x = 3 + } + } + + access(all) resource interface B { + access(all) fun foo() + } + } + ` + + contractCode := ` + import TestInterfaces from 0x2 + access(all) contract TestContract { + access(all) resource R: TestInterfaces.A, TestInterfaces.B {} + // fill space + // fill space + // fill space + // fill space + // fill space + // fill space + // filling lots of space + // filling lots of space + // filling lots of space + } + ` + + accountCodes := map[Location][]byte{} + var events []cadence.Event + + var nextAccount byte = 0x2 + + runtimeInterface := &testRuntimeInterface{ + getCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + storage: newTestLedger(nil, nil), + createAccount: func(payer Address) (address Address, err error) { + result := interpreter.NewUnmeteredAddressValueFromBytes([]byte{nextAccount}) + nextAccount++ + return result.ToAddress(), nil + }, + getSigningAccounts: func() ([]Address, error) { + return []Address{{0x1}}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + deployTransaction := makeDeployTransaction("TestInterfaces", contractInterfaceCode) + err := runtime.ExecuteTransaction( + Script{ + Source: deployTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + deployTransaction = makeDeployTransaction("TestContract", contractCode) + err = runtime.ExecuteTransaction( + Script{ + Source: deployTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.Error(t, err) + require.Contains(t, err.Error(), "access(all) resource R: TestInterfaces.A, TestInterfaces.B {}") + + var errType *sema.CheckerError + require.ErrorAs(t, err, &errType) + + checkerErr := err.(Error). + Err.(interpreter.Error). + Err.(*stdlib.InvalidContractDeploymentError). + Err.(*ParsingCheckingError). + Err.(*sema.CheckerError) + + var specificErrType *sema.DefaultFunctionConflictError + require.ErrorAs(t, checkerErr.Errors[0], &specificErrType) + + errorRange := checkerErr.Errors[0].(*sema.DefaultFunctionConflictError).Range + + require.Equal(t, errorRange.StartPos.Line, 4) +} + +func TestRuntimeMultipleInterfaceDefaultImplementationsError(t *testing.T) { + t.Parallel() + + runtime := newTestInterpreterRuntime() + + makeDeployTransaction := func(name, code string) []byte { + return []byte(fmt.Sprintf( + ` + transaction { + prepare(signer: AuthAccount) { + let acct = AuthAccount(payer: signer) + acct.contracts.add(name: "%s", code: "%s".decodeHex()) + } + } + `, + name, + hex.EncodeToString([]byte(code)), + )) + } + + contractInterfaceCode := ` + access(all) contract TestInterfaces { + + access(all) resource interface A { + access(all) fun foo() { + let x = 3 + } + } + + access(all) resource interface B { + access(all) fun foo() { + let x = 4 + } + } + } + ` + + contractCode := ` + import TestInterfaces from 0x2 + access(all) contract TestContract { + access(all) resource R: TestInterfaces.A, TestInterfaces.B {} + // fill space + // fill space + // fill space + // fill space + // fill space + // fill space + // filling lots of space + // filling lots of space + // filling lots of space + } + ` + + accountCodes := map[Location][]byte{} + var events []cadence.Event + + var nextAccount byte = 0x2 + + runtimeInterface := &testRuntimeInterface{ + getCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + storage: newTestLedger(nil, nil), + createAccount: func(payer Address) (address Address, err error) { + result := interpreter.NewUnmeteredAddressValueFromBytes([]byte{nextAccount}) + nextAccount++ + return result.ToAddress(), nil + }, + getSigningAccounts: func() ([]Address, error) { + return []Address{{0x1}}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + deployTransaction := makeDeployTransaction("TestInterfaces", contractInterfaceCode) + err := runtime.ExecuteTransaction( + Script{ + Source: deployTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + deployTransaction = makeDeployTransaction("TestContract", contractCode) + err = runtime.ExecuteTransaction( + Script{ + Source: deployTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.Error(t, err) + require.Contains(t, err.Error(), "access(all) resource R: TestInterfaces.A, TestInterfaces.B {}") + + var errType *sema.CheckerError + require.ErrorAs(t, err, &errType) + + checkerErr := err.(Error). + Err.(interpreter.Error). + Err.(*stdlib.InvalidContractDeploymentError). + Err.(*ParsingCheckingError). + Err.(*sema.CheckerError) + + var specificErrType *sema.MultipleInterfaceDefaultImplementationsError + require.ErrorAs(t, checkerErr.Errors[0], &specificErrType) + + errorRange := checkerErr.Errors[0].(*sema.MultipleInterfaceDefaultImplementationsError).Range + + require.Equal(t, errorRange.StartPos.Line, 4) +} diff --git a/runtime/events.go b/runtime/events.go index 86e01ebe37..4738902bc8 100644 --- a/runtime/events.go +++ b/runtime/events.go @@ -81,6 +81,6 @@ func emitEventFields( err = emitEvent(exportedEvent) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } } diff --git a/runtime/interface.go b/runtime/interface.go index 8048171af1..1a45aad7d4 100644 --- a/runtime/interface.go +++ b/runtime/interface.go @@ -102,9 +102,8 @@ type Interface interface { GetCurrentBlockHeight() (uint64, error) // GetBlockAtHeight returns the block at the given height. GetBlockAtHeight(height uint64) (block Block, exists bool, err error) - // UnsafeRandom returns a random uint64, where the process of random number derivation is not cryptographically - // secure. - UnsafeRandom() (uint64, error) + // ReadRandom reads pseudo-random bytes into the input slice, using distributed randomness. + ReadRandom([]byte) error // VerifySignature returns true if the given signature was produced by signing the given tag + data // using the given public key, signature algorithm, and hash algorithm. VerifySignature( diff --git a/runtime/interpreter/errors.go b/runtime/interpreter/errors.go index f47c12b4da..5b57ea8fe6 100644 --- a/runtime/interpreter/errors.go +++ b/runtime/interpreter/errors.go @@ -20,6 +20,7 @@ package interpreter import ( "fmt" + "runtime" "strings" "github.com/onflow/cadence/runtime/ast" @@ -975,3 +976,35 @@ func (AccountLinkingForbiddenError) IsUserError() {} func (e AccountLinkingForbiddenError) Error() string { return "account linking is not allowed" } + +// RecursiveTransferError +type RecursiveTransferError struct { + LocationRange +} + +var _ errors.UserError = RecursiveTransferError{} + +func (RecursiveTransferError) IsUserError() {} + +func (RecursiveTransferError) Error() string { + return "recursive transfer of value" +} + +func WrappedExternalError(err error) error { + switch err := err.(type) { + case + // If the error is a go-runtime error, don't wrap. + // These are crashers. + runtime.Error, + + // If the error is already a cadence error, then avoid redundant wrapping. + errors.InternalError, + errors.UserError, + errors.ExternalError, + Error: + return err + + default: + return errors.NewExternalError(err) + } +} diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 3791f68676..22d73df311 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -423,12 +423,15 @@ func (interpreter *Interpreter) InvokeExternally( if argumentCount != parameterCount { - // if the function has defined optional parameters, - // then the provided arguments must be equal to or greater than - // the number of required parameters. - if functionType.RequiredArgumentCount == nil || - argumentCount < *functionType.RequiredArgumentCount { + if argumentCount < functionType.Arity.MinCount(parameterCount) { + return nil, ArgumentCountError{ + ParameterCount: parameterCount, + ArgumentCount: argumentCount, + } + } + maxCount := functionType.Arity.MaxCount(parameterCount) + if maxCount != nil && argumentCount > *maxCount { return nil, ArgumentCountError{ ParameterCount: parameterCount, ArgumentCount: argumentCount, @@ -515,20 +518,8 @@ func (interpreter *Interpreter) InvokeTransaction(index int, arguments ...Value) func (interpreter *Interpreter) RecoverErrors(onError func(error)) { if r := recover(); r != nil { - var err error - // Recover all errors, because interpreter can be directly invoked by FVM. - switch r := r.(type) { - case Error, - errors.ExternalError, - errors.InternalError, - errors.UserError: - err = r.(error) - case error: - err = errors.NewUnexpectedErrorFromCause(r) - default: - err = errors.NewUnexpectedError("%s", r) - } + err := asCadenceError(r) // if the error is not yet an interpreter error, wrap it if _, ok := err.(Error); !ok { @@ -558,6 +549,31 @@ func (interpreter *Interpreter) RecoverErrors(onError func(error)) { } } +func asCadenceError(r any) error { + err, isError := r.(error) + if !isError { + return errors.NewUnexpectedError("%s", r) + } + + rootError := err + + for { + switch typedError := err.(type) { + case Error, + errors.ExternalError, + errors.InternalError, + errors.UserError: + return typedError + case xerrors.Wrapper: + err = typedError.Unwrap() + case error: + return errors.NewUnexpectedErrorFromCause(rootError) + default: + return errors.NewUnexpectedErrorFromCause(rootError) + } + } +} + func (interpreter *Interpreter) CallStack() []Invocation { return interpreter.SharedState.callStack.Invocations[:] } @@ -1065,7 +1081,6 @@ func (interpreter *Interpreter) declareNonEnumCompositeValue( ReturnTypeAnnotation: sema.TypeAnnotation{ Type: compositeType, }, - RequiredArgumentCount: nil, } var initializerFunction FunctionValue @@ -1690,6 +1705,7 @@ func (interpreter *Interpreter) transferAndConvert( atree.Address{}, false, nil, + nil, ) result := interpreter.ConvertAndBox( @@ -3742,20 +3758,28 @@ func (interpreter *Interpreter) newStorageIterationFunction( }() for key, value := storageIterator.Next(); key != nil && value != nil; key, value = storageIterator.Next() { - staticType := value.StaticType(inter) - // Perform a forced type loading to see if the underlying type is not broken. - // If broken, skip this value from the iteration. - typeError := inter.checkTypeLoading(staticType) - if typeError != nil { - continue - } + staticType := value.StaticType(inter) // TODO: unfortunately, the iterator only returns an atree.Value, not a StorageMapKey identifier := string(key.(StringAtreeValue)) pathValue := NewPathValue(inter, domain, identifier) runtimeType := NewTypeValue(inter, staticType) + // Perform a forced value de-referencing to see if the associated type is not broken. + // If broken, skip this value from the iteration. + valueError := inter.checkValue( + address, + pathValue, + value, + staticType, + invocation.LocationRange, + ) + + if valueError != nil { + continue + } + subInvocation := NewInvocation( inter, nil, @@ -3796,14 +3820,21 @@ func (interpreter *Interpreter) newStorageIterationFunction( ) } -func (interpreter *Interpreter) checkTypeLoading(staticType StaticType) (typeError error) { +func (interpreter *Interpreter) checkValue( + address common.Address, + path PathValue, + value Value, + staticType StaticType, + locationRange LocationRange, +) (valueError error) { + defer func() { if r := recover(); r != nil { rootError := r for { switch err := r.(type) { case errors.UserError, errors.ExternalError: - typeError = err.(error) + valueError = err.(error) return case xerrors.Wrapper: r = err.Unwrap() @@ -3814,8 +3845,37 @@ func (interpreter *Interpreter) checkTypeLoading(staticType StaticType) (typeErr } }() - // Here it is only interested in whether the type can be properly loaded. - _, typeError = interpreter.ConvertStaticToSemaType(staticType) + // Here, the value at the path could be either: + // 1) The actual stored value (storage path) + // 2) A link to the value at the storage (private/public paths) + // + // Therefore, try to find the final path, and try loading the value. + + // However, borrow type is not statically known. + // So take the borrow type from the value itself + + var borrowType StaticType + if _, ok := value.(LinkValue); ok { + // Link values always have a `CapabilityStaticType` static type. + borrowType = staticType.(CapabilityStaticType).BorrowType + } else { + // Reference type with value's type (i.e. `staticType`) as both the borrow type and the referenced type. + borrowType = NewReferenceStaticType(interpreter, false, staticType, staticType) + } + + var semaType sema.Type + semaType, valueError = interpreter.ConvertStaticToSemaType(borrowType) + if valueError != nil { + return valueError + } + + // This is guaranteed to be a reference type, because `borrowType` is always a reference. + referenceType, ok := semaType.(*sema.ReferenceType) + if !ok { + panic(errors.NewUnreachableError()) + } + + _, valueError = interpreter.checkValueAtPath(address, path, referenceType, locationRange) return } @@ -3863,6 +3923,7 @@ func (interpreter *Interpreter) authAccountSaveFunction(addressValue AddressValu atree.Address(address), true, nil, + nil, ) // Write new value @@ -3986,6 +4047,7 @@ func (interpreter *Interpreter) authAccountReadFunction(addressValue AddressValu atree.Address{}, false, nil, + nil, ) // Remove the value from storage, @@ -4476,50 +4538,63 @@ func (interpreter *Interpreter) pathCapabilityCheckFunction( panic(errors.NewUnreachableError()) } - target, authorized, err := - interpreter.GetPathCapabilityFinalTarget( - address, - pathValue, - borrowType, - true, - locationRange, - ) + valid, err := interpreter.checkValueAtPath(address, pathValue, borrowType, locationRange) if err != nil { panic(err) } - if target == nil { - return FalseValue - } + return AsBoolValue(valid) + }, + ) +} - switch target := target.(type) { - case AccountCapabilityTarget: - return TrueValue +func (interpreter *Interpreter) checkValueAtPath( + address common.Address, + pathValue PathValue, + borrowType *sema.ReferenceType, + locationRange LocationRange, +) (bool, error) { - case PathCapabilityTarget: - targetPath := PathValue(target) + target, authorized, err := interpreter.GetPathCapabilityFinalTarget( + address, + pathValue, + borrowType, + true, + locationRange, + ) - reference := NewStorageReferenceValue( - interpreter, - authorized, - address, - targetPath, - borrowType.Type, - ) + if err != nil { + return false, err + } - // Attempt to dereference, - // which reads the stored value - // and performs a dynamic type check + if target == nil { + return false, nil + } - return AsBoolValue( - reference.ReferencedValue(interpreter, invocation.LocationRange, false) != nil, - ) + switch target := target.(type) { + case AccountCapabilityTarget: + return true, nil - default: - panic(errors.NewUnreachableError()) - } - }, - ) + case PathCapabilityTarget: + targetPath := PathValue(target) + + reference := NewStorageReferenceValue( + interpreter, + authorized, + address, + targetPath, + borrowType.Type, + ) + + // Attempt to dereference, + // which reads the stored value + // and performs a dynamic type check + + return reference.ReferencedValue(interpreter, locationRange, false) != nil, nil + + default: + panic(errors.NewUnreachableError()) + } } func (interpreter *Interpreter) GetPathCapabilityFinalTarget( @@ -4722,16 +4797,16 @@ func (interpreter *Interpreter) GetCompositeType( return compositeType, nil } } else { - compositeType = interpreter.getUserCompositeType(location, typeID) - if compositeType != nil { - return compositeType, nil + config := interpreter.SharedState.Config + compositeTypeHandler := config.CompositeTypeHandler + if compositeTypeHandler != nil { + compositeType = compositeTypeHandler(location, typeID) + if compositeType != nil { + return compositeType, nil + } } - } - config := interpreter.SharedState.Config - compositeTypeHandler := config.CompositeTypeHandler - if compositeTypeHandler != nil { - compositeType = compositeTypeHandler(location, typeID) + compositeType = interpreter.getUserCompositeType(location, typeID) if compositeType != nil { return compositeType, nil } diff --git a/runtime/interpreter/interpreter_expression.go b/runtime/interpreter/interpreter_expression.go index fc49fd6ed3..edb24e1d0c 100644 --- a/runtime/interpreter/interpreter_expression.go +++ b/runtime/interpreter/interpreter_expression.go @@ -1155,6 +1155,12 @@ func (interpreter *Interpreter) VisitReferenceExpression(referenceExpression *as interpreter.maybeTrackReferencedResourceKindedValue(result) + // There are four potential cases: + // 1) Target type is optional, actual value is also optional (nil/SomeValue) + // 2) Target type is optional, actual value is non-optional + // 3) Target type is non-optional, actual value is optional (SomeValue) + // 4) Target type is non-optional, actual value is non-optional + switch typ := borrowType.(type) { case *sema.OptionalType: innerBorrowType, ok := typ.Type.(*sema.ReferenceType) @@ -1165,6 +1171,7 @@ func (interpreter *Interpreter) VisitReferenceExpression(referenceExpression *as switch result := result.(type) { case *SomeValue: + // Case (1): // References to optionals are transformed into optional references, // so move the *SomeValue out to the reference itself @@ -1190,6 +1197,7 @@ func (interpreter *Interpreter) VisitReferenceExpression(referenceExpression *as return Nil default: + // Case (2): // If the referenced value is non-optional, // but the target type is optional, // then box the reference properly @@ -1212,8 +1220,21 @@ func (interpreter *Interpreter) VisitReferenceExpression(referenceExpression *as } case *sema.ReferenceType: + // Case (3): target type is non-optional, actual value is optional. + // Unwrap the optional and add it to reference tracking. + if someValue, ok := result.(*SomeValue); ok { + locationRange := LocationRange{ + Location: interpreter.Location, + HasPosition: referenceExpression.Expression, + } + innerValue := someValue.InnerValue(interpreter, locationRange) + interpreter.maybeTrackReferencedResourceKindedValue(innerValue) + } + + // Case (4): target type is non-optional, actual value is also non-optional return NewEphemeralReferenceValue(interpreter, typ.Authorized, result, typ.Type) } + panic(errors.NewUnreachableError()) } @@ -1310,6 +1331,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta atree.Address{}, false, nil, + nil, ).(*CompositeValue) // we enforce this in the checker diff --git a/runtime/interpreter/interpreter_invocation.go b/runtime/interpreter/interpreter_invocation.go index 817a9aeaf9..d0d18d39ea 100644 --- a/runtime/interpreter/interpreter_invocation.go +++ b/runtime/interpreter/interpreter_invocation.go @@ -100,6 +100,7 @@ func (interpreter *Interpreter) invokeFunctionValue( atree.Address{}, false, nil, + nil, ) } } diff --git a/runtime/interpreter/interpreter_statement.go b/runtime/interpreter/interpreter_statement.go index d3acaa47b9..171748e389 100644 --- a/runtime/interpreter/interpreter_statement.go +++ b/runtime/interpreter/interpreter_statement.go @@ -323,6 +323,7 @@ func (interpreter *Interpreter) VisitForStatement(statement *ast.ForStatement) S atree.Address{}, false, nil, + nil, ) iterable, ok := transferredValue.(IterableValue) diff --git a/runtime/interpreter/location.go b/runtime/interpreter/location.go index daf2996cde..4186c84c3e 100644 --- a/runtime/interpreter/location.go +++ b/runtime/interpreter/location.go @@ -23,14 +23,6 @@ import ( "github.com/onflow/cadence/runtime/common" ) -// LocationPosition defines a position in the source of the import tree. -// The Location defines the script within the import tree, the Position -// defines the row/colum within the source of that script. -type LocationPosition struct { - Location common.Location - Position ast.Position -} - // LocationRange defines a range in the source of the import tree. // The Position defines the script within the import tree, the Range // defines the start/end position within the source of that script. @@ -39,6 +31,22 @@ type LocationRange struct { ast.HasPosition } +var _ ast.HasPosition = LocationRange{} + +func (r LocationRange) StartPosition() ast.Position { + if r.HasPosition == nil { + return ast.EmptyPosition + } + return r.HasPosition.StartPosition() +} + +func (r LocationRange) EndPosition(memoryGauge common.MemoryGauge) ast.Position { + if r.HasPosition == nil { + return ast.EmptyPosition + } + return r.HasPosition.EndPosition(memoryGauge) +} + func (r LocationRange) ImportLocation() common.Location { return r.Location } diff --git a/runtime/interpreter/location_test.go b/runtime/interpreter/location_test.go new file mode 100644 index 0000000000..50a85d4ee7 --- /dev/null +++ b/runtime/interpreter/location_test.go @@ -0,0 +1,57 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Dapper Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package interpreter + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/onflow/cadence/runtime/ast" +) + +func TestLocationRange_HasPosition(t *testing.T) { + + t.Parallel() + + t.Run("nil", func(t *testing.T) { + + locationRange := LocationRange{} + + assert.Equal(t, ast.EmptyPosition, locationRange.StartPosition()) + assert.Equal(t, ast.EmptyPosition, locationRange.EndPosition(nil)) + }) + + t.Run("non-nil", func(t *testing.T) { + + startPos := ast.Position{Offset: 1, Line: 2, Column: 3} + endPos := ast.Position{Offset: 4, Line: 5, Column: 6} + + locationRange := LocationRange{ + HasPosition: ast.Range{ + StartPos: startPos, + EndPos: endPos, + }, + } + + assert.Equal(t, startPos, locationRange.StartPosition()) + assert.Equal(t, endPos, locationRange.EndPosition(nil)) + + }) +} diff --git a/runtime/interpreter/simplecompositevalue.go b/runtime/interpreter/simplecompositevalue.go index 0a4b637a1e..ca53a6cec9 100644 --- a/runtime/interpreter/simplecompositevalue.go +++ b/runtime/interpreter/simplecompositevalue.go @@ -236,6 +236,7 @@ func (v *SimpleCompositeValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { // TODO: actually not needed, value is not storable if remove { diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 2ef910c506..12efe97254 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -133,6 +133,7 @@ type Value interface { address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value DeepRemove(interpreter *Interpreter) // Clone returns a new value that is equal to this value. @@ -257,9 +258,13 @@ type ValueIterator interface { func safeAdd(a, b int, locationRange LocationRange) int { // INT32-C if (b > 0) && (a > (goMaxInt - b)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (b < 0) && (a < (goMinInt - b)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return a + b } @@ -270,24 +275,32 @@ func safeMul(a, b int, locationRange LocationRange) int { if b > 0 { // positive * positive = positive. overflow? if a > (goMaxInt / b) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } else { // positive * negative = negative. underflow? if b < (goMinInt / a) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } } else { if b > 0 { // negative * positive = negative. underflow? if a < (goMinInt / b) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } else { // negative * negative = positive. overflow? if (a != 0) && (b < (goMaxInt / a)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } } @@ -473,6 +486,7 @@ func (v TypeValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -592,6 +606,7 @@ func (v VoidValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -671,7 +686,7 @@ func (v BoolValue) Equal(_ *Interpreter, _ LocationRange, other Value) bool { return bool(v) == bool(otherBool) } -func (v BoolValue) Less(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v BoolValue) Less(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { o, ok := other.(BoolValue) if !ok { panic(errors.NewUnreachableError()) @@ -680,7 +695,7 @@ func (v BoolValue) Less(interpreter *Interpreter, other ComparableValue, locatio return !v && o } -func (v BoolValue) LessEqual(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v BoolValue) LessEqual(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { o, ok := other.(BoolValue) if !ok { panic(errors.NewUnreachableError()) @@ -689,7 +704,7 @@ func (v BoolValue) LessEqual(interpreter *Interpreter, other ComparableValue, lo return !v || o } -func (v BoolValue) Greater(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v BoolValue) Greater(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { o, ok := other.(BoolValue) if !ok { panic(errors.NewUnreachableError()) @@ -698,7 +713,7 @@ func (v BoolValue) Greater(interpreter *Interpreter, other ComparableValue, loca return v && !o } -func (v BoolValue) GreaterEqual(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v BoolValue) GreaterEqual(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { o, ok := other.(BoolValue) if !ok { panic(errors.NewUnreachableError()) @@ -764,6 +779,7 @@ func (v BoolValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -864,7 +880,7 @@ func (v CharacterValue) Equal(_ *Interpreter, _ LocationRange, other Value) bool return v.NormalForm() == otherChar.NormalForm() } -func (v CharacterValue) Less(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v CharacterValue) Less(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { otherChar, ok := other.(CharacterValue) if !ok { panic(errors.NewUnreachableError()) @@ -872,7 +888,7 @@ func (v CharacterValue) Less(interpreter *Interpreter, other ComparableValue, lo return v.NormalForm() < otherChar.NormalForm() } -func (v CharacterValue) LessEqual(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v CharacterValue) LessEqual(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { otherChar, ok := other.(CharacterValue) if !ok { panic(errors.NewUnreachableError()) @@ -880,7 +896,7 @@ func (v CharacterValue) LessEqual(interpreter *Interpreter, other ComparableValu return v.NormalForm() <= otherChar.NormalForm() } -func (v CharacterValue) Greater(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v CharacterValue) Greater(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { otherChar, ok := other.(CharacterValue) if !ok { panic(errors.NewUnreachableError()) @@ -888,7 +904,7 @@ func (v CharacterValue) Greater(interpreter *Interpreter, other ComparableValue, return v.NormalForm() > otherChar.NormalForm() } -func (v CharacterValue) GreaterEqual(interpreter *Interpreter, other ComparableValue, locationRange LocationRange) BoolValue { +func (v CharacterValue) GreaterEqual(_ *Interpreter, other ComparableValue, _ LocationRange) BoolValue { otherChar, ok := other.(CharacterValue) if !ok { panic(errors.NewUnreachableError()) @@ -937,6 +953,7 @@ func (v CharacterValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -1094,9 +1111,10 @@ func (v *StringValue) Less(interpreter *Interpreter, other ComparableValue, loca otherString, ok := other.(*StringValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -1107,9 +1125,10 @@ func (v *StringValue) LessEqual(interpreter *Interpreter, other ComparableValue, otherString, ok := other.(*StringValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -1120,9 +1139,10 @@ func (v *StringValue) Greater(interpreter *Interpreter, other ComparableValue, l otherString, ok := other.(*StringValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -1133,9 +1153,10 @@ func (v *StringValue) GreaterEqual(interpreter *Interpreter, other ComparableVal otherString, ok := other.(*StringValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -1413,6 +1434,7 @@ func (v *StringValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -1589,6 +1611,7 @@ func NewArrayValue( atree.Address(address), true, nil, + nil, ) return value @@ -1600,7 +1623,7 @@ func NewArrayValueWithIterator( interpreter *Interpreter, arrayType ArrayStaticType, address common.Address, - count uint64, + countOverestimate uint64, values func() Value, ) *ArrayValue { interpreter.ReportComputation(common.ComputationKindCreateArrayValue, 1) @@ -1645,7 +1668,7 @@ func NewArrayValueWithIterator( return array } // must assign to v here for tracing to work properly - v = newArrayValueFromConstructor(interpreter, arrayType, count, constructor) + v = newArrayValueFromConstructor(interpreter, arrayType, countOverestimate, constructor) return v } @@ -1662,14 +1685,14 @@ func newArrayValueFromAtreeValue( func newArrayValueFromConstructor( gauge common.MemoryGauge, staticType ArrayStaticType, - count uint64, + countOverestimate uint64, constructor func() *atree.Array, ) (array *ArrayValue) { var elementSize uint if staticType != nil { elementSize = staticType.ElementType().elementSize() } - baseUsage, elementUsage, dataSlabs, metaDataSlabs := common.NewArrayMemoryUsages(count, elementSize) + baseUsage, elementUsage, dataSlabs, metaDataSlabs := common.NewArrayMemoryUsages(countOverestimate, elementSize) common.UseMemory(gauge, baseUsage) common.UseMemory(gauge, elementUsage) common.UseMemory(gauge, dataSlabs) @@ -1885,6 +1908,7 @@ func (v *ArrayValue) Concat(interpreter *Interpreter, locationRange LocationRang atree.Address{}, false, nil, + nil, ) }, ) @@ -1971,6 +1995,9 @@ func (v *ArrayValue) Set(interpreter *Interpreter, locationRange LocationRange, v.array.Address(), true, nil, + map[atree.StorageID]struct{}{ + v.StorageID(): {}, + }, ) existingStorable, err := v.array.Set(uint64(index), element) @@ -2042,6 +2069,9 @@ func (v *ArrayValue) Append(interpreter *Interpreter, locationRange LocationRang v.array.Address(), true, nil, + map[atree.StorageID]struct{}{ + v.StorageID(): {}, + }, ) err := v.array.Append(element) @@ -2101,6 +2131,9 @@ func (v *ArrayValue) Insert(interpreter *Interpreter, locationRange LocationRang v.array.Address(), true, nil, + map[atree.StorageID]struct{}{ + v.StorageID(): {}, + }, ) err := v.array.Insert(uint64(index), element) @@ -2154,6 +2187,7 @@ func (v *ArrayValue) Remove(interpreter *Interpreter, locationRange LocationRang atree.Address{}, true, storable, + nil, ) } @@ -2411,6 +2445,72 @@ func (v *ArrayValue) GetMember(interpreter *Interpreter, locationRange LocationR ) }, ) + + case sema.ArrayTypeReverseFunctionName: + return NewHostFunctionValue( + interpreter, + sema.ArrayReverseFunctionType( + v.SemaType(interpreter), + ), + func(invocation Invocation) Value { + return v.Reverse( + invocation.Interpreter, + invocation.LocationRange, + ) + }, + ) + + case sema.ArrayTypeFilterFunctionName: + return NewHostFunctionValue( + interpreter, + sema.ArrayFilterFunctionType( + interpreter, + v.SemaType(interpreter).ElementType(false), + ), + func(invocation Invocation) Value { + interpreter := invocation.Interpreter + + funcArgument, ok := invocation.Arguments[0].(FunctionValue) + if !ok { + panic(errors.NewUnreachableError()) + } + + return v.Filter( + interpreter, + invocation.LocationRange, + funcArgument, + ) + }, + ) + + case sema.ArrayTypeMapFunctionName: + return NewHostFunctionValue( + interpreter, + sema.ArrayMapFunctionType( + interpreter, + v.SemaType(interpreter), + ), + func(invocation Invocation) Value { + interpreter := invocation.Interpreter + + funcArgument, ok := invocation.Arguments[0].(FunctionValue) + if !ok { + panic(errors.NewUnreachableError()) + } + + transformFunctionType, ok := invocation.ArgumentTypes[0].(*sema.FunctionType) + if !ok { + panic(errors.NewUnreachableError()) + } + + return v.Map( + interpreter, + invocation.LocationRange, + funcArgument, + transformFunctionType, + ) + }, + ) } return nil @@ -2556,6 +2656,7 @@ func (v *ArrayValue) Transfer( address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value { baseUsage, elementUsage, dataSlabs, metaDataSlabs := common.NewArrayMemoryUsages(v.array.Count(), v.elementSize) common.UseMemory(interpreter, baseUsage) @@ -2588,6 +2689,16 @@ func (v *ArrayValue) Transfer( currentStorageID := v.StorageID() + if preventTransfer == nil { + preventTransfer = map[atree.StorageID]struct{}{} + } else if _, ok := preventTransfer[currentStorageID]; ok { + panic(RecursiveTransferError{ + LocationRange: locationRange, + }) + } + preventTransfer[currentStorageID] = struct{}{} + defer delete(preventTransfer, currentStorageID) + array := v.array needsStoreTo := v.NeedsStoreTo(address) @@ -2614,7 +2725,7 @@ func (v *ArrayValue) Transfer( } element := MustConvertStoredValue(interpreter, value). - Transfer(interpreter, locationRange, address, remove, nil) + Transfer(interpreter, locationRange, address, remove, nil, preventTransfer) return element, nil }, @@ -2865,6 +2976,191 @@ func (v *ArrayValue) Slice( atree.Address{}, false, nil, + nil, + ) + }, + ) +} + +func (v *ArrayValue) Reverse( + interpreter *Interpreter, + locationRange LocationRange, +) Value { + count := v.Count() + index := count - 1 + + return NewArrayValueWithIterator( + interpreter, + v.Type, + common.ZeroAddress, + uint64(count), + func() Value { + if index < 0 { + return nil + } + + value := v.Get(interpreter, locationRange, index) + index-- + + return value.Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, + ) + }, + ) +} + +func (v *ArrayValue) Filter( + interpreter *Interpreter, + locationRange LocationRange, + procedure FunctionValue, +) Value { + + elementTypeSlice := []sema.Type{v.semaType.ElementType(false)} + iterationInvocation := func(arrayElement Value) Invocation { + invocation := NewInvocation( + interpreter, + nil, + nil, + []Value{arrayElement}, + elementTypeSlice, + nil, + locationRange, + ) + return invocation + } + + iterator, err := v.array.Iterator() + if err != nil { + panic(errors.NewExternalError(err)) + } + + return NewArrayValueWithIterator( + interpreter, + NewVariableSizedStaticType(interpreter, v.Type.ElementType()), + common.ZeroAddress, + uint64(v.Count()), // worst case estimation. + func() Value { + + var value Value + + for { + atreeValue, err := iterator.Next() + if err != nil { + panic(errors.NewExternalError(err)) + } + + // Also handles the end of array case since iterator.Next() returns nil for that. + if atreeValue == nil { + return nil + } + + value = MustConvertStoredValue(interpreter, atreeValue) + if value == nil { + return nil + } + + shouldInclude, ok := procedure.invoke(iterationInvocation(value)).(BoolValue) + if !ok { + panic(errors.NewUnreachableError()) + } + + // We found the next entry of the filtered array. + if shouldInclude { + break + } + } + + return value.Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, + ) + }, + ) +} + +func (v *ArrayValue) Map( + interpreter *Interpreter, + locationRange LocationRange, + procedure FunctionValue, + transformFunctionType *sema.FunctionType, +) Value { + + elementTypeSlice := []sema.Type{v.semaType.ElementType(false)} + iterationInvocation := func(arrayElement Value) Invocation { + return NewInvocation( + interpreter, + nil, + nil, + []Value{arrayElement}, + elementTypeSlice, + nil, + locationRange, + ) + } + + procedureStaticType, ok := ConvertSemaToStaticType(interpreter, transformFunctionType).(FunctionStaticType) + if !ok { + panic(errors.NewUnreachableError()) + } + returnType := procedureStaticType.ReturnType(interpreter) + + var returnArrayStaticType ArrayStaticType + switch v.Type.(type) { + case VariableSizedStaticType: + returnArrayStaticType = NewVariableSizedStaticType( + interpreter, + returnType, + ) + case ConstantSizedStaticType: + returnArrayStaticType = NewConstantSizedStaticType( + interpreter, + returnType, + int64(v.Count()), + ) + default: + panic(errors.NewUnreachableError()) + } + + iterator, err := v.array.Iterator() + if err != nil { + panic(errors.NewExternalError(err)) + } + + return NewArrayValueWithIterator( + interpreter, + returnArrayStaticType, + common.ZeroAddress, + uint64(v.Count()), + func() Value { + + atreeValue, err := iterator.Next() + if err != nil { + panic(errors.NewExternalError(err)) + } + + if atreeValue == nil { + return nil + } + + value := MustConvertStoredValue(interpreter, atreeValue) + + mappedValue := procedure.invoke(iterationInvocation(value)) + return mappedValue.Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, ) }, ) @@ -3100,7 +3396,9 @@ func (IntValue) IsImportable(_ *Interpreter) bool { func (v IntValue) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -3132,7 +3430,7 @@ func (v IntValue) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferences return v.String() } -func (v IntValue) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { +func (v IntValue) Negate(interpreter *Interpreter, _ LocationRange) NumberValue { return NewIntValueFromBigInt( interpreter, common.NewNegateBigIntMemoryUsage(v.BigInt), @@ -3146,9 +3444,10 @@ func (v IntValue) Plus(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3167,9 +3466,10 @@ func (v IntValue) SaturatingPlus(interpreter *Interpreter, other NumberValue, lo r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -3181,9 +3481,10 @@ func (v IntValue) Minus(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3202,9 +3503,10 @@ func (v IntValue) SaturatingMinus(interpreter *Interpreter, other NumberValue, l r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -3216,9 +3518,10 @@ func (v IntValue) Mod(interpreter *Interpreter, other NumberValue, locationRange o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3229,7 +3532,9 @@ func (v IntValue) Mod(interpreter *Interpreter, other NumberValue, locationRange res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Rem(v.BigInt, o.BigInt) }, @@ -3240,9 +3545,10 @@ func (v IntValue) Mul(interpreter *Interpreter, other NumberValue, locationRange o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3261,9 +3567,10 @@ func (v IntValue) SaturatingMul(interpreter *Interpreter, other NumberValue, loc r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -3275,9 +3582,10 @@ func (v IntValue) Div(interpreter *Interpreter, other NumberValue, locationRange o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3288,7 +3596,9 @@ func (v IntValue) Div(interpreter *Interpreter, other NumberValue, locationRange res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -3300,9 +3610,10 @@ func (v IntValue) SaturatingDiv(interpreter *Interpreter, other NumberValue, loc r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -3314,9 +3625,10 @@ func (v IntValue) Less(interpreter *Interpreter, other ComparableValue, location o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3328,9 +3640,10 @@ func (v IntValue) LessEqual(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3342,9 +3655,10 @@ func (v IntValue) Greater(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3357,9 +3671,10 @@ func (v IntValue) GreaterEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3399,9 +3714,10 @@ func (v IntValue) BitwiseOr(interpreter *Interpreter, other IntegerValue, locati o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3419,9 +3735,10 @@ func (v IntValue) BitwiseXor(interpreter *Interpreter, other IntegerValue, locat o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3439,9 +3756,10 @@ func (v IntValue) BitwiseAnd(interpreter *Interpreter, other IntegerValue, locat o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3459,18 +3777,23 @@ func (v IntValue) BitwiseLeftShift(interpreter *Interpreter, other IntegerValue, o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewIntValueFromBigInt( @@ -3487,18 +3810,23 @@ func (v IntValue) BitwiseRightShift(interpreter *Interpreter, other IntegerValue o, ok := other.(IntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewIntValueFromBigInt( @@ -3555,6 +3883,7 @@ func (v IntValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -3644,14 +3973,16 @@ func (v Int8Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReference return v.String() } -func (v Int8Value) ToInt(locationRange LocationRange) int { +func (v Int8Value) ToInt(_ LocationRange) int { return int(v) } func (v Int8Value) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { // INT32-C if v == math.MinInt8 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int8 { @@ -3665,17 +3996,22 @@ func (v Int8Value) Plus(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v > (math.MaxInt8 - o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v < (math.MinInt8 - o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int8 { @@ -3689,9 +4025,10 @@ func (v Int8Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3712,17 +4049,22 @@ func (v Int8Value) Minus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v < (math.MinInt8 + o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v > (math.MaxInt8 + o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int8 { @@ -3736,9 +4078,10 @@ func (v Int8Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3759,15 +4102,18 @@ func (v Int8Value) Mod(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() int8 { @@ -3781,9 +4127,10 @@ func (v Int8Value) Mul(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3792,24 +4139,32 @@ func (v Int8Value) Mul(interpreter *Interpreter, other NumberValue, locationRang if o > 0 { // positive * positive = positive. overflow? if v > (math.MaxInt8 / o) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } else { // positive * negative = negative. underflow? if o < (math.MinInt8 / v) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } } else { if o > 0 { // negative * positive = negative. underflow? if v < (math.MinInt8 / o) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } else { // negative * negative = positive. overflow? if (v != 0) && (o < (math.MaxInt8 / v)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } } @@ -3825,9 +4180,10 @@ func (v Int8Value) SaturatingMul(interpreter *Interpreter, other NumberValue, lo o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3869,18 +4225,23 @@ func (v Int8Value) Div(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt8) && (o == -1) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int8 { @@ -3894,9 +4255,10 @@ func (v Int8Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, lo o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3904,7 +4266,9 @@ func (v Int8Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, lo // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt8) && (o == -1) { return math.MaxInt8 } @@ -3918,9 +4282,10 @@ func (v Int8Value) Less(interpreter *Interpreter, other ComparableValue, locatio o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3931,9 +4296,10 @@ func (v Int8Value) LessEqual(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3944,9 +4310,10 @@ func (v Int8Value) Greater(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3957,9 +4324,10 @@ func (v Int8Value) GreaterEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -3990,18 +4358,26 @@ func ConvertInt8(memoryGauge common.MemoryGauge, value Value, locationRange Loca case BigNumberValue: v := value.ToBigInt(memoryGauge) if v.Cmp(sema.Int8TypeMaxInt) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int8TypeMinInt) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int8(v.Int64()) case NumberValue: v := value.ToInt(locationRange) if v > math.MaxInt8 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v < math.MinInt8 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int8(v) @@ -4017,9 +4393,10 @@ func (v Int8Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, locat o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4034,9 +4411,10 @@ func (v Int8Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4051,9 +4429,10 @@ func (v Int8Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4068,9 +4447,10 @@ func (v Int8Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValue o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4085,9 +4465,10 @@ func (v Int8Value) BitwiseRightShift(interpreter *Interpreter, other IntegerValu o, ok := other.(Int8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4142,6 +4523,7 @@ func (v Int8Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -4232,14 +4614,16 @@ func (v Int16Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v Int16Value) ToInt(locationRange LocationRange) int { +func (v Int16Value) ToInt(_ LocationRange) int { return int(v) } func (v Int16Value) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { // INT32-C if v == math.MinInt16 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int16 { @@ -4253,17 +4637,22 @@ func (v Int16Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v > (math.MaxInt16 - o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v < (math.MinInt16 - o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int16 { @@ -4277,9 +4666,10 @@ func (v Int16Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4300,17 +4690,22 @@ func (v Int16Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v < (math.MinInt16 + o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v > (math.MaxInt16 + o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int16 { @@ -4324,9 +4719,10 @@ func (v Int16Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4347,15 +4743,18 @@ func (v Int16Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() int16 { @@ -4369,9 +4768,10 @@ func (v Int16Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4380,24 +4780,32 @@ func (v Int16Value) Mul(interpreter *Interpreter, other NumberValue, locationRan if o > 0 { // positive * positive = positive. overflow? if v > (math.MaxInt16 / o) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } else { // positive * negative = negative. underflow? if o < (math.MinInt16 / v) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } } else { if o > 0 { // negative * positive = negative. underflow? if v < (math.MinInt16 / o) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } else { // negative * negative = positive. overflow? if (v != 0) && (o < (math.MaxInt16 / v)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } } @@ -4413,9 +4821,10 @@ func (v Int16Value) SaturatingMul(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4456,18 +4865,23 @@ func (v Int16Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt16) && (o == -1) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int16 { @@ -4481,9 +4895,10 @@ func (v Int16Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4491,7 +4906,9 @@ func (v Int16Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt16) && (o == -1) { return math.MaxInt16 } @@ -4505,9 +4922,10 @@ func (v Int16Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4518,9 +4936,10 @@ func (v Int16Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4531,9 +4950,10 @@ func (v Int16Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4544,9 +4964,10 @@ func (v Int16Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4577,18 +4998,26 @@ func ConvertInt16(memoryGauge common.MemoryGauge, value Value, locationRange Loc case BigNumberValue: v := value.ToBigInt(memoryGauge) if v.Cmp(sema.Int16TypeMaxInt) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int16TypeMinInt) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int16(v.Int64()) case NumberValue: v := value.ToInt(locationRange) if v > math.MaxInt16 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v < math.MinInt16 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int16(v) @@ -4604,9 +5033,10 @@ func (v Int16Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4621,9 +5051,10 @@ func (v Int16Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4638,9 +5069,10 @@ func (v Int16Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4655,9 +5087,10 @@ func (v Int16Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValu o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4672,9 +5105,10 @@ func (v Int16Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Int16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4731,6 +5165,7 @@ func (v Int16Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -4821,14 +5256,16 @@ func (v Int32Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v Int32Value) ToInt(locationRange LocationRange) int { +func (v Int32Value) ToInt(_ LocationRange) int { return int(v) } func (v Int32Value) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { // INT32-C if v == math.MinInt32 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int32 { @@ -4842,17 +5279,22 @@ func (v Int32Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v > (math.MaxInt32 - o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v < (math.MinInt32 - o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int32 { @@ -4866,9 +5308,10 @@ func (v Int32Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4889,17 +5332,22 @@ func (v Int32Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v < (math.MinInt32 + o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v > (math.MaxInt32 + o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int32 { @@ -4913,9 +5361,10 @@ func (v Int32Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4936,15 +5385,18 @@ func (v Int32Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() int32 { @@ -4958,9 +5410,10 @@ func (v Int32Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -4969,24 +5422,32 @@ func (v Int32Value) Mul(interpreter *Interpreter, other NumberValue, locationRan if o > 0 { // positive * positive = positive. overflow? if v > (math.MaxInt32 / o) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } else { // positive * negative = negative. underflow? if o < (math.MinInt32 / v) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } } else { if o > 0 { // negative * positive = negative. underflow? if v < (math.MinInt32 / o) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } else { // negative * negative = positive. overflow? if (v != 0) && (o < (math.MaxInt32 / v)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } } @@ -5002,9 +5463,10 @@ func (v Int32Value) SaturatingMul(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5045,18 +5507,23 @@ func (v Int32Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt32) && (o == -1) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int32 { @@ -5070,9 +5537,10 @@ func (v Int32Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5080,7 +5548,9 @@ func (v Int32Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt32) && (o == -1) { return math.MaxInt32 } @@ -5095,9 +5565,10 @@ func (v Int32Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5108,9 +5579,10 @@ func (v Int32Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5121,9 +5593,10 @@ func (v Int32Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5134,9 +5607,10 @@ func (v Int32Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5166,18 +5640,26 @@ func ConvertInt32(memoryGauge common.MemoryGauge, value Value, locationRange Loc case BigNumberValue: v := value.ToBigInt(memoryGauge) if v.Cmp(sema.Int32TypeMaxInt) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int32TypeMinInt) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int32(v.Int64()) case NumberValue: v := value.ToInt(locationRange) if v > math.MaxInt32 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v < math.MinInt32 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int32(v) @@ -5193,9 +5675,10 @@ func (v Int32Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5210,9 +5693,10 @@ func (v Int32Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5227,9 +5711,10 @@ func (v Int32Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5244,9 +5729,10 @@ func (v Int32Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValu o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5261,9 +5747,10 @@ func (v Int32Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Int32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5320,6 +5807,7 @@ func (v Int32Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -5408,14 +5896,16 @@ func (v Int64Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v Int64Value) ToInt(locationRange LocationRange) int { +func (v Int64Value) ToInt(_ LocationRange) int { return int(v) } func (v Int64Value) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { // INT32-C if v == math.MinInt64 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int64 { @@ -5428,9 +5918,13 @@ func (v Int64Value) Negate(interpreter *Interpreter, locationRange LocationRange func safeAddInt64(a, b int64, locationRange LocationRange) int64 { // INT32-C if (b > 0) && (a > (math.MaxInt64 - b)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (b < 0) && (a < (math.MinInt64 - b)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return a + b } @@ -5439,9 +5933,10 @@ func (v Int64Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5456,9 +5951,10 @@ func (v Int64Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5479,17 +5975,22 @@ func (v Int64Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT32-C if (o > 0) && (v < (math.MinInt64 + o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v > (math.MaxInt64 + o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int64 { @@ -5503,9 +6004,10 @@ func (v Int64Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5526,15 +6028,18 @@ func (v Int64Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() int64 { @@ -5548,9 +6053,10 @@ func (v Int64Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5559,24 +6065,32 @@ func (v Int64Value) Mul(interpreter *Interpreter, other NumberValue, locationRan if o > 0 { // positive * positive = positive. overflow? if v > (math.MaxInt64 / o) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } else { // positive * negative = negative. underflow? if o < (math.MinInt64 / v) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } } else { if o > 0 { // negative * positive = negative. underflow? if v < (math.MinInt64 / o) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } } else { // negative * negative = positive. overflow? if (v != 0) && (o < (math.MaxInt64 / v)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } } } @@ -5592,9 +6106,10 @@ func (v Int64Value) SaturatingMul(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5635,18 +6150,23 @@ func (v Int64Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt64) && (o == -1) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int64 { @@ -5660,9 +6180,10 @@ func (v Int64Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5670,7 +6191,9 @@ func (v Int64Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l // INT33-C // https://golang.org/ref/spec#Integer_operators if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } else if (v == math.MinInt64) && (o == -1) { return math.MaxInt64 } @@ -5684,9 +6207,10 @@ func (v Int64Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5697,9 +6221,10 @@ func (v Int64Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5710,9 +6235,10 @@ func (v Int64Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5724,9 +6250,10 @@ func (v Int64Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5756,9 +6283,13 @@ func ConvertInt64(memoryGauge common.MemoryGauge, value Value, locationRange Loc case BigNumberValue: v := value.ToBigInt(memoryGauge) if v.Cmp(sema.Int64TypeMaxInt) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int64TypeMinInt) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v.Int64() @@ -5778,9 +6309,10 @@ func (v Int64Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5795,9 +6327,10 @@ func (v Int64Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5812,9 +6345,10 @@ func (v Int64Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5829,9 +6363,10 @@ func (v Int64Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValu o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5846,9 +6381,10 @@ func (v Int64Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Int64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -5905,6 +6441,7 @@ func (v Int64Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -5994,7 +6531,9 @@ func (Int128Value) IsImportable(_ *Interpreter) bool { func (v Int128Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -6032,7 +6571,9 @@ func (v Int128Value) Negate(interpreter *Interpreter, locationRange LocationRang // ... // } if v.BigInt.Cmp(sema.Int128TypeMinIntBig) == 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() *big.Int { @@ -6046,9 +6587,10 @@ func (v Int128Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6068,9 +6610,13 @@ func (v Int128Value) Plus(interpreter *Interpreter, other NumberValue, locationR res := new(big.Int) res.Add(v.BigInt, o.BigInt) if res.Cmp(sema.Int128TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6083,9 +6629,10 @@ func (v Int128Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6120,9 +6667,10 @@ func (v Int128Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6142,9 +6690,13 @@ func (v Int128Value) Minus(interpreter *Interpreter, other NumberValue, location res := new(big.Int) res.Sub(v.BigInt, o.BigInt) if res.Cmp(sema.Int128TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6157,9 +6709,10 @@ func (v Int128Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6194,9 +6747,10 @@ func (v Int128Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6204,7 +6758,9 @@ func (v Int128Value) Mod(interpreter *Interpreter, other NumberValue, locationRa res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.Rem(v.BigInt, o.BigInt) @@ -6218,9 +6774,10 @@ func (v Int128Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6228,9 +6785,13 @@ func (v Int128Value) Mul(interpreter *Interpreter, other NumberValue, locationRa res := new(big.Int) res.Mul(v.BigInt, o.BigInt) if res.Cmp(sema.Int128TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6243,9 +6804,10 @@ func (v Int128Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6268,9 +6830,10 @@ func (v Int128Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6283,11 +6846,15 @@ func (v Int128Value) Div(interpreter *Interpreter, other NumberValue, locationRa // ... // } if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.SetInt64(-1) if (v.BigInt.Cmp(sema.Int128TypeMinIntBig) == 0) && (o.BigInt.Cmp(res) == 0) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } res.Div(v.BigInt, o.BigInt) @@ -6301,9 +6868,10 @@ func (v Int128Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6316,7 +6884,9 @@ func (v Int128Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, // ... // } if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.SetInt64(-1) if (v.BigInt.Cmp(sema.Int128TypeMinIntBig) == 0) && (o.BigInt.Cmp(res) == 0) { @@ -6334,9 +6904,10 @@ func (v Int128Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6348,9 +6919,10 @@ func (v Int128Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6362,9 +6934,10 @@ func (v Int128Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6376,9 +6949,10 @@ func (v Int128Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6430,9 +7004,13 @@ func ConvertInt128(memoryGauge common.MemoryGauge, value Value, locationRange Lo } if v.Cmp(sema.Int128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int128TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v @@ -6445,9 +7023,10 @@ func (v Int128Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6464,9 +7043,10 @@ func (v Int128Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6483,9 +7063,10 @@ func (v Int128Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6502,17 +7083,22 @@ func (v Int128Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() *big.Int { @@ -6528,17 +7114,22 @@ func (v Int128Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Int128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() *big.Int { @@ -6594,6 +7185,7 @@ func (v Int128Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -6683,7 +7275,9 @@ func (Int256Value) IsImportable(_ *Interpreter) bool { func (v Int256Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -6721,7 +7315,9 @@ func (v Int256Value) Negate(interpreter *Interpreter, locationRange LocationRang // ... // } if v.BigInt.Cmp(sema.Int256TypeMinIntBig) == 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() *big.Int { @@ -6735,9 +7331,10 @@ func (v Int256Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6757,9 +7354,13 @@ func (v Int256Value) Plus(interpreter *Interpreter, other NumberValue, locationR res := new(big.Int) res.Add(v.BigInt, o.BigInt) if res.Cmp(sema.Int256TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6772,9 +7373,10 @@ func (v Int256Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6809,9 +7411,10 @@ func (v Int256Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6831,9 +7434,13 @@ func (v Int256Value) Minus(interpreter *Interpreter, other NumberValue, location res := new(big.Int) res.Sub(v.BigInt, o.BigInt) if res.Cmp(sema.Int256TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6846,9 +7453,10 @@ func (v Int256Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6883,9 +7491,10 @@ func (v Int256Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6893,7 +7502,9 @@ func (v Int256Value) Mod(interpreter *Interpreter, other NumberValue, locationRa res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.Rem(v.BigInt, o.BigInt) @@ -6907,9 +7518,10 @@ func (v Int256Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6917,9 +7529,13 @@ func (v Int256Value) Mul(interpreter *Interpreter, other NumberValue, locationRa res := new(big.Int) res.Mul(v.BigInt, o.BigInt) if res.Cmp(sema.Int256TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if res.Cmp(sema.Int256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res @@ -6932,9 +7548,10 @@ func (v Int256Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6957,9 +7574,10 @@ func (v Int256Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -6972,11 +7590,15 @@ func (v Int256Value) Div(interpreter *Interpreter, other NumberValue, locationRa // ... // } if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.SetInt64(-1) if (v.BigInt.Cmp(sema.Int256TypeMinIntBig) == 0) && (o.BigInt.Cmp(res) == 0) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } res.Div(v.BigInt, o.BigInt) return res @@ -6989,9 +7611,10 @@ func (v Int256Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7004,7 +7627,9 @@ func (v Int256Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, // ... // } if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.SetInt64(-1) if (v.BigInt.Cmp(sema.Int256TypeMinIntBig) == 0) && (o.BigInt.Cmp(res) == 0) { @@ -7021,9 +7646,10 @@ func (v Int256Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7035,9 +7661,10 @@ func (v Int256Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7049,9 +7676,10 @@ func (v Int256Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7063,9 +7691,10 @@ func (v Int256Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7117,9 +7746,13 @@ func ConvertInt256(memoryGauge common.MemoryGauge, value Value, locationRange Lo } if v.Cmp(sema.Int256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Cmp(sema.Int256TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v @@ -7132,9 +7765,10 @@ func (v Int256Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7151,9 +7785,10 @@ func (v Int256Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7170,9 +7805,10 @@ func (v Int256Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7189,19 +7825,24 @@ func (v Int256Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } valueGetter := func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } res.Lsh(v.BigInt, uint(o.BigInt.Uint64())) @@ -7215,19 +7856,24 @@ func (v Int256Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Int256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } valueGetter := func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } res.Rsh(v.BigInt, uint(o.BigInt.Uint64())) return res @@ -7280,6 +7926,7 @@ func (v Int256Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -7356,7 +8003,9 @@ func ConvertUInt(memoryGauge common.MemoryGauge, value Value, locationRange Loca func() *big.Int { v := value.ToBigInt(memoryGauge) if v.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v }, @@ -7365,7 +8014,9 @@ func ConvertUInt(memoryGauge common.MemoryGauge, value Value, locationRange Loca case NumberValue: v := value.ToInt(locationRange) if v < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return NewUIntValueFromUint64( memoryGauge, @@ -7406,7 +8057,9 @@ func (v UIntValue) IsImportable(_ *Interpreter) bool { func (v UIntValue) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -7446,9 +8099,10 @@ func (v UIntValue) Plus(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7467,9 +8121,10 @@ func (v UIntValue) SaturatingPlus(interpreter *Interpreter, other NumberValue, l r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -7481,9 +8136,10 @@ func (v UIntValue) Minus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7495,7 +8151,9 @@ func (v UIntValue) Minus(interpreter *Interpreter, other NumberValue, locationRa res.Sub(v.BigInt, o.BigInt) // INT30-C if res.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return res }, @@ -7506,9 +8164,10 @@ func (v UIntValue) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7531,9 +8190,10 @@ func (v UIntValue) Mod(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7544,7 +8204,9 @@ func (v UIntValue) Mod(interpreter *Interpreter, other NumberValue, locationRang res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } res.Rem(v.BigInt, o.BigInt) return res @@ -7556,9 +8218,10 @@ func (v UIntValue) Mul(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7577,9 +8240,10 @@ func (v UIntValue) SaturatingMul(interpreter *Interpreter, other NumberValue, lo r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -7591,9 +8255,10 @@ func (v UIntValue) Div(interpreter *Interpreter, other NumberValue, locationRang o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7604,7 +8269,9 @@ func (v UIntValue) Div(interpreter *Interpreter, other NumberValue, locationRang res := new(big.Int) // INT33-C if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -7616,9 +8283,10 @@ func (v UIntValue) SaturatingDiv(interpreter *Interpreter, other NumberValue, lo r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -7630,9 +8298,10 @@ func (v UIntValue) Less(interpreter *Interpreter, other ComparableValue, locatio o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7644,9 +8313,10 @@ func (v UIntValue) LessEqual(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7658,9 +8328,10 @@ func (v UIntValue) Greater(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7672,9 +8343,10 @@ func (v UIntValue) GreaterEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7714,9 +8386,10 @@ func (v UIntValue) BitwiseOr(interpreter *Interpreter, other IntegerValue, locat o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7734,9 +8407,10 @@ func (v UIntValue) BitwiseXor(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7754,9 +8428,10 @@ func (v UIntValue) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7774,18 +8449,23 @@ func (v UIntValue) BitwiseLeftShift(interpreter *Interpreter, other IntegerValue o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewUIntValueFromBigInt( @@ -7803,17 +8483,22 @@ func (v UIntValue) BitwiseRightShift(interpreter *Interpreter, other IntegerValu o, ok := other.(UIntValue) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewUIntValueFromBigInt( @@ -7870,6 +8555,7 @@ func (v UIntValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -7958,7 +8644,7 @@ func (v UInt8Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v UInt8Value) ToInt(locationRange LocationRange) int { +func (v UInt8Value) ToInt(_ LocationRange) int { return int(v) } @@ -7970,9 +8656,10 @@ func (v UInt8Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -7980,7 +8667,9 @@ func (v UInt8Value) Plus(interpreter *Interpreter, other NumberValue, locationRa sum := v + o // INT30-C if sum < v { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint8(sum) }) @@ -7990,9 +8679,10 @@ func (v UInt8Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8010,9 +8700,10 @@ func (v UInt8Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8022,7 +8713,9 @@ func (v UInt8Value) Minus(interpreter *Interpreter, other NumberValue, locationR diff := v - o // INT30-C if diff > v { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint8(diff) }, @@ -8033,9 +8726,10 @@ func (v UInt8Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8056,9 +8750,10 @@ func (v UInt8Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8066,7 +8761,9 @@ func (v UInt8Value) Mod(interpreter *Interpreter, other NumberValue, locationRan interpreter, func() uint8 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint8(v % o) }, @@ -8077,9 +8774,10 @@ func (v UInt8Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8088,7 +8786,9 @@ func (v UInt8Value) Mul(interpreter *Interpreter, other NumberValue, locationRan func() uint8 { // INT30-C if (v > 0) && (o > 0) && (v > (math.MaxUint8 / o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint8(v * o) }, @@ -8099,9 +8799,10 @@ func (v UInt8Value) SaturatingMul(interpreter *Interpreter, other NumberValue, l o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8121,9 +8822,10 @@ func (v UInt8Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8131,7 +8833,9 @@ func (v UInt8Value) Div(interpreter *Interpreter, other NumberValue, locationRan interpreter, func() uint8 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint8(v / o) }, @@ -8143,9 +8847,10 @@ func (v UInt8Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -8157,9 +8862,10 @@ func (v UInt8Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8170,9 +8876,10 @@ func (v UInt8Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8183,9 +8890,10 @@ func (v UInt8Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8196,9 +8904,10 @@ func (v UInt8Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8233,18 +8942,26 @@ func ConvertUnsigned[T Unsigned]( case BigNumberValue: v := value.ToBigInt(memoryGauge) if v.Cmp(maxBigNumber) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return T(v.Int64()) case NumberValue: v := value.ToInt(locationRange) if maxNumber > 0 && v > maxNumber { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return T(v) @@ -8289,9 +9006,10 @@ func (v UInt8Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8307,9 +9025,10 @@ func (v UInt8Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8325,9 +9044,10 @@ func (v UInt8Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8343,9 +9063,10 @@ func (v UInt8Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValu o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8361,9 +9082,10 @@ func (v UInt8Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVal o, ok := other.(UInt8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8419,6 +9141,7 @@ func (v UInt8Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -8507,7 +9230,7 @@ func (v UInt16Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen return v.String() } -func (v UInt16Value) ToInt(locationRange LocationRange) int { +func (v UInt16Value) ToInt(_ LocationRange) int { return int(v) } func (v UInt16Value) Negate(*Interpreter, LocationRange) NumberValue { @@ -8518,9 +9241,10 @@ func (v UInt16Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8530,7 +9254,9 @@ func (v UInt16Value) Plus(interpreter *Interpreter, other NumberValue, locationR sum := v + o // INT30-C if sum < v { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint16(sum) }, @@ -8541,9 +9267,10 @@ func (v UInt16Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8564,9 +9291,10 @@ func (v UInt16Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8576,7 +9304,9 @@ func (v UInt16Value) Minus(interpreter *Interpreter, other NumberValue, location diff := v - o // INT30-C if diff > v { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint16(diff) }, @@ -8587,9 +9317,10 @@ func (v UInt16Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8610,9 +9341,10 @@ func (v UInt16Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8620,7 +9352,9 @@ func (v UInt16Value) Mod(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint16 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint16(v % o) }, @@ -8631,9 +9365,10 @@ func (v UInt16Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8642,7 +9377,9 @@ func (v UInt16Value) Mul(interpreter *Interpreter, other NumberValue, locationRa func() uint16 { // INT30-C if (v > 0) && (o > 0) && (v > (math.MaxUint16 / o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint16(v * o) }, @@ -8653,9 +9390,10 @@ func (v UInt16Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8675,9 +9413,10 @@ func (v UInt16Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8685,7 +9424,9 @@ func (v UInt16Value) Div(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint16 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint16(v / o) }, @@ -8697,9 +9438,10 @@ func (v UInt16Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -8711,9 +9453,10 @@ func (v UInt16Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8724,9 +9467,10 @@ func (v UInt16Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8737,9 +9481,10 @@ func (v UInt16Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8750,9 +9495,10 @@ func (v UInt16Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8795,9 +9541,10 @@ func (v UInt16Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8813,9 +9560,10 @@ func (v UInt16Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8831,9 +9579,10 @@ func (v UInt16Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8849,9 +9598,10 @@ func (v UInt16Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8867,9 +9617,10 @@ func (v UInt16Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(UInt16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -8931,6 +9682,7 @@ func (v UInt16Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -9019,7 +9771,7 @@ func (v UInt32Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen return v.String() } -func (v UInt32Value) ToInt(locationRange LocationRange) int { +func (v UInt32Value) ToInt(_ LocationRange) int { return int(v) } @@ -9031,9 +9783,10 @@ func (v UInt32Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9043,7 +9796,9 @@ func (v UInt32Value) Plus(interpreter *Interpreter, other NumberValue, locationR sum := v + o // INT30-C if sum < v { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint32(sum) }, @@ -9054,9 +9809,10 @@ func (v UInt32Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9077,9 +9833,10 @@ func (v UInt32Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9089,7 +9846,9 @@ func (v UInt32Value) Minus(interpreter *Interpreter, other NumberValue, location diff := v - o // INT30-C if diff > v { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint32(diff) }, @@ -9100,9 +9859,10 @@ func (v UInt32Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9123,9 +9883,10 @@ func (v UInt32Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9133,7 +9894,9 @@ func (v UInt32Value) Mod(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint32 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint32(v % o) }, @@ -9144,9 +9907,10 @@ func (v UInt32Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9154,7 +9918,9 @@ func (v UInt32Value) Mul(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint32 { if (v > 0) && (o > 0) && (v > (math.MaxUint32 / o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint32(v * o) }, @@ -9165,9 +9931,10 @@ func (v UInt32Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9188,9 +9955,10 @@ func (v UInt32Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9198,7 +9966,9 @@ func (v UInt32Value) Div(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint32 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint32(v / o) }, @@ -9210,9 +9980,10 @@ func (v UInt32Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -9224,9 +9995,10 @@ func (v UInt32Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9237,9 +10009,10 @@ func (v UInt32Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9250,9 +10023,10 @@ func (v UInt32Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9263,9 +10037,10 @@ func (v UInt32Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9308,9 +10083,10 @@ func (v UInt32Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9326,9 +10102,10 @@ func (v UInt32Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9344,9 +10121,10 @@ func (v UInt32Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9362,9 +10140,10 @@ func (v UInt32Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9380,9 +10159,10 @@ func (v UInt32Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(UInt32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9444,6 +10224,7 @@ func (v UInt32Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -9540,7 +10321,9 @@ func (v UInt64Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen func (v UInt64Value) ToInt(locationRange LocationRange) int { if v > math.MaxInt64 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v) } @@ -9568,7 +10351,9 @@ func safeAddUint64(a, b uint64, locationRange LocationRange) uint64 { sum := a + b // INT30-C if sum < a { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return sum } @@ -9577,9 +10362,10 @@ func (v UInt64Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9595,9 +10381,10 @@ func (v UInt64Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9618,9 +10405,10 @@ func (v UInt64Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9630,7 +10418,9 @@ func (v UInt64Value) Minus(interpreter *Interpreter, other NumberValue, location diff := v - o // INT30-C if diff > v { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint64(diff) }, @@ -9641,9 +10431,10 @@ func (v UInt64Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9664,9 +10455,10 @@ func (v UInt64Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9674,7 +10466,9 @@ func (v UInt64Value) Mod(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint64 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint64(v % o) }, @@ -9685,9 +10479,10 @@ func (v UInt64Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9695,7 +10490,9 @@ func (v UInt64Value) Mul(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint64 { if (v > 0) && (o > 0) && (v > (math.MaxUint64 / o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return uint64(v * o) }, @@ -9706,9 +10503,10 @@ func (v UInt64Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9728,9 +10526,10 @@ func (v UInt64Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9738,7 +10537,9 @@ func (v UInt64Value) Div(interpreter *Interpreter, other NumberValue, locationRa interpreter, func() uint64 { if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return uint64(v / o) }, @@ -9750,9 +10551,10 @@ func (v UInt64Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -9764,9 +10566,10 @@ func (v UInt64Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9777,9 +10580,10 @@ func (v UInt64Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9790,9 +10594,10 @@ func (v UInt64Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9803,9 +10608,10 @@ func (v UInt64Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9848,9 +10654,10 @@ func (v UInt64Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9866,9 +10673,10 @@ func (v UInt64Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9884,9 +10692,10 @@ func (v UInt64Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9902,9 +10711,10 @@ func (v UInt64Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9920,9 +10730,10 @@ func (v UInt64Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(UInt64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -9984,6 +10795,7 @@ func (v UInt64Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -10073,7 +10885,9 @@ func (UInt128Value) IsImportable(_ *Interpreter) bool { func (v UInt128Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -10113,9 +10927,10 @@ func (v UInt128Value) Plus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10135,7 +10950,9 @@ func (v UInt128Value) Plus(interpreter *Interpreter, other NumberValue, location // } // if sum.Cmp(sema.UInt128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return sum }, @@ -10146,9 +10963,10 @@ func (v UInt128Value) SaturatingPlus(interpreter *Interpreter, other NumberValue o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10179,9 +10997,10 @@ func (v UInt128Value) Minus(interpreter *Interpreter, other NumberValue, locatio o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10201,7 +11020,9 @@ func (v UInt128Value) Minus(interpreter *Interpreter, other NumberValue, locatio // } // if diff.Cmp(sema.UInt128TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return diff }, @@ -10212,9 +11033,10 @@ func (v UInt128Value) SaturatingMinus(interpreter *Interpreter, other NumberValu o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10245,9 +11067,10 @@ func (v UInt128Value) Mod(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10256,7 +11079,9 @@ func (v UInt128Value) Mod(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Rem(v.BigInt, o.BigInt) }, @@ -10267,9 +11092,10 @@ func (v UInt128Value) Mul(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10279,7 +11105,9 @@ func (v UInt128Value) Mul(interpreter *Interpreter, other NumberValue, locationR res := new(big.Int) res.Mul(v.BigInt, o.BigInt) if res.Cmp(sema.UInt128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res }, @@ -10290,9 +11118,10 @@ func (v UInt128Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10313,9 +11142,10 @@ func (v UInt128Value) Div(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10324,7 +11154,9 @@ func (v UInt128Value) Div(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -10337,9 +11169,10 @@ func (v UInt128Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -10351,9 +11184,10 @@ func (v UInt128Value) Less(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10365,9 +11199,10 @@ func (v UInt128Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10379,9 +11214,10 @@ func (v UInt128Value) Greater(interpreter *Interpreter, other ComparableValue, l o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10393,9 +11229,10 @@ func (v UInt128Value) GreaterEqual(interpreter *Interpreter, other ComparableVal o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10450,9 +11287,13 @@ func ConvertUInt128(memoryGauge common.MemoryGauge, value Value, locationRange L } if v.Cmp(sema.UInt128TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v @@ -10464,9 +11305,10 @@ func (v UInt128Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10483,9 +11325,10 @@ func (v UInt128Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, l o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10502,9 +11345,10 @@ func (v UInt128Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, l o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10522,9 +11366,10 @@ func (v UInt128Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10533,10 +11378,14 @@ func (v UInt128Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Lsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -10547,9 +11396,10 @@ func (v UInt128Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV o, ok := other.(UInt128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10558,10 +11408,14 @@ func (v UInt128Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Rsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -10616,6 +11470,7 @@ func (v UInt128Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -10705,7 +11560,9 @@ func (UInt256Value) IsImportable(_ *Interpreter) bool { func (v UInt256Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) @@ -10746,9 +11603,10 @@ func (v UInt256Value) Plus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10768,7 +11626,9 @@ func (v UInt256Value) Plus(interpreter *Interpreter, other NumberValue, location // } // if sum.Cmp(sema.UInt256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return sum }, @@ -10780,9 +11640,10 @@ func (v UInt256Value) SaturatingPlus(interpreter *Interpreter, other NumberValue o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10813,9 +11674,10 @@ func (v UInt256Value) Minus(interpreter *Interpreter, other NumberValue, locatio o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10835,7 +11697,9 @@ func (v UInt256Value) Minus(interpreter *Interpreter, other NumberValue, locatio // } // if diff.Cmp(sema.UInt256TypeMinIntBig) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return diff }, @@ -10846,9 +11710,10 @@ func (v UInt256Value) SaturatingMinus(interpreter *Interpreter, other NumberValu o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10880,9 +11745,10 @@ func (v UInt256Value) Mod(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10891,7 +11757,9 @@ func (v UInt256Value) Mod(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Rem(v.BigInt, o.BigInt) }, @@ -10902,9 +11770,10 @@ func (v UInt256Value) Mul(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10914,7 +11783,9 @@ func (v UInt256Value) Mul(interpreter *Interpreter, other NumberValue, locationR res := new(big.Int) res.Mul(v.BigInt, o.BigInt) if res.Cmp(sema.UInt256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res }, @@ -10925,9 +11796,10 @@ func (v UInt256Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10948,9 +11820,10 @@ func (v UInt256Value) Div(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10959,7 +11832,9 @@ func (v UInt256Value) Div(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -10971,9 +11846,10 @@ func (v UInt256Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -10985,9 +11861,10 @@ func (v UInt256Value) Less(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -10999,9 +11876,10 @@ func (v UInt256Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11013,9 +11891,10 @@ func (v UInt256Value) Greater(interpreter *Interpreter, other ComparableValue, l o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11027,9 +11906,10 @@ func (v UInt256Value) GreaterEqual(interpreter *Interpreter, other ComparableVal o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11083,9 +11963,13 @@ func ConvertUInt256(memoryGauge common.MemoryGauge, value Value, locationRange L } if v.Cmp(sema.UInt256TypeMaxIntBig) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if v.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return v @@ -11097,9 +11981,10 @@ func (v UInt256Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11116,9 +12001,10 @@ func (v UInt256Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, l o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11135,9 +12021,10 @@ func (v UInt256Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, l o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11154,9 +12041,10 @@ func (v UInt256Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11165,10 +12053,14 @@ func (v UInt256Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Lsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -11179,9 +12071,10 @@ func (v UInt256Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV o, ok := other.(UInt256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11190,10 +12083,14 @@ func (v UInt256Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Rsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -11247,6 +12144,7 @@ func (v UInt256Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -11337,7 +12235,7 @@ func (v Word8Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v Word8Value) ToInt(locationRange LocationRange) int { +func (v Word8Value) ToInt(_ LocationRange) int { return int(v) } @@ -11349,9 +12247,10 @@ func (v Word8Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11370,9 +12269,10 @@ func (v Word8Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11391,14 +12291,17 @@ func (v Word8Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint8 { @@ -11412,9 +12315,10 @@ func (v Word8Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11433,14 +12337,17 @@ func (v Word8Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint8 { @@ -11458,9 +12365,10 @@ func (v Word8Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11471,9 +12379,10 @@ func (v Word8Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11484,9 +12393,10 @@ func (v Word8Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11497,9 +12407,10 @@ func (v Word8Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11536,9 +12447,10 @@ func (v Word8Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loca o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11553,9 +12465,10 @@ func (v Word8Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11570,9 +12483,10 @@ func (v Word8Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11587,9 +12501,10 @@ func (v Word8Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerValu o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11604,9 +12519,10 @@ func (v Word8Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Word8Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11665,6 +12581,7 @@ func (v Word8Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -11755,7 +12672,7 @@ func (v Word16Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen return v.String() } -func (v Word16Value) ToInt(locationRange LocationRange) int { +func (v Word16Value) ToInt(_ LocationRange) int { return int(v) } func (v Word16Value) Negate(*Interpreter, LocationRange) NumberValue { @@ -11766,9 +12683,10 @@ func (v Word16Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11787,9 +12705,10 @@ func (v Word16Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11808,14 +12727,17 @@ func (v Word16Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint16 { @@ -11829,9 +12751,10 @@ func (v Word16Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11850,14 +12773,17 @@ func (v Word16Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint16 { @@ -11875,9 +12801,10 @@ func (v Word16Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11888,9 +12815,10 @@ func (v Word16Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11901,9 +12829,10 @@ func (v Word16Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11914,9 +12843,10 @@ func (v Word16Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11953,9 +12883,10 @@ func (v Word16Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11970,9 +12901,10 @@ func (v Word16Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -11987,9 +12919,10 @@ func (v Word16Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12004,9 +12937,10 @@ func (v Word16Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12021,9 +12955,10 @@ func (v Word16Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Word16Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12084,6 +13019,7 @@ func (v Word16Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -12174,7 +13110,7 @@ func (v Word32Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen return v.String() } -func (v Word32Value) ToInt(locationRange LocationRange) int { +func (v Word32Value) ToInt(_ LocationRange) int { return int(v) } @@ -12186,9 +13122,10 @@ func (v Word32Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12207,9 +13144,10 @@ func (v Word32Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12228,14 +13166,17 @@ func (v Word32Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint32 { @@ -12249,9 +13190,10 @@ func (v Word32Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12270,14 +13212,17 @@ func (v Word32Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint32 { @@ -12295,9 +13240,10 @@ func (v Word32Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12308,9 +13254,10 @@ func (v Word32Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12321,9 +13268,10 @@ func (v Word32Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12334,9 +13282,10 @@ func (v Word32Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12373,9 +13322,10 @@ func (v Word32Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12390,9 +13340,10 @@ func (v Word32Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12407,9 +13358,10 @@ func (v Word32Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12424,9 +13376,10 @@ func (v Word32Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12441,9 +13394,10 @@ func (v Word32Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Word32Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12504,6 +13458,7 @@ func (v Word32Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -12602,7 +13557,9 @@ func (v Word64Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen func (v Word64Value) ToInt(locationRange LocationRange) int { if v > math.MaxInt64 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v) } @@ -12630,9 +13587,10 @@ func (v Word64Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12651,9 +13609,10 @@ func (v Word64Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12672,14 +13631,17 @@ func (v Word64Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint64 { @@ -12693,9 +13655,10 @@ func (v Word64Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12714,14 +13677,17 @@ func (v Word64Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } if o == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } valueGetter := func() uint64 { @@ -12739,9 +13705,10 @@ func (v Word64Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12752,9 +13719,10 @@ func (v Word64Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12765,9 +13733,10 @@ func (v Word64Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12778,9 +13747,10 @@ func (v Word64Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12817,9 +13787,10 @@ func (v Word64Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, loc o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12834,9 +13805,10 @@ func (v Word64Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12851,9 +13823,10 @@ func (v Word64Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12868,9 +13841,10 @@ func (v Word64Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVal o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12885,9 +13859,10 @@ func (v Word64Value) BitwiseRightShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Word64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -12948,6 +13923,7 @@ func (v Word64Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -13037,7 +14013,9 @@ func (Word128Value) IsImportable(_ *Interpreter) bool { func (v Word128Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -13077,9 +14055,10 @@ func (v Word128Value) Plus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13110,7 +14089,7 @@ func (v Word128Value) Plus(interpreter *Interpreter, other NumberValue, location ) } -func (v Word128Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word128Value) SaturatingPlus(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13118,9 +14097,10 @@ func (v Word128Value) Minus(interpreter *Interpreter, other NumberValue, locatio o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13151,7 +14131,7 @@ func (v Word128Value) Minus(interpreter *Interpreter, other NumberValue, locatio ) } -func (v Word128Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word128Value) SaturatingMinus(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13159,9 +14139,10 @@ func (v Word128Value) Mod(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13170,7 +14151,9 @@ func (v Word128Value) Mod(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Rem(v.BigInt, o.BigInt) }, @@ -13181,9 +14164,10 @@ func (v Word128Value) Mul(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13200,7 +14184,7 @@ func (v Word128Value) Mul(interpreter *Interpreter, other NumberValue, locationR ) } -func (v Word128Value) SaturatingMul(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word128Value) SaturatingMul(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13208,9 +14192,10 @@ func (v Word128Value) Div(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13219,7 +14204,9 @@ func (v Word128Value) Div(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -13227,7 +14214,7 @@ func (v Word128Value) Div(interpreter *Interpreter, other NumberValue, locationR } -func (v Word128Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word128Value) SaturatingDiv(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13235,9 +14222,10 @@ func (v Word128Value) Less(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13249,9 +14237,10 @@ func (v Word128Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13263,9 +14252,10 @@ func (v Word128Value) Greater(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13277,9 +14267,10 @@ func (v Word128Value) GreaterEqual(interpreter *Interpreter, other ComparableVal o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13348,9 +14339,10 @@ func (v Word128Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13367,9 +14359,10 @@ func (v Word128Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, l o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13386,9 +14379,10 @@ func (v Word128Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, l o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13406,9 +14400,10 @@ func (v Word128Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Word128Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13417,10 +14412,14 @@ func (v Word128Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Lsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -13442,10 +14441,14 @@ func (v Word128Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Rsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -13500,6 +14503,7 @@ func (v Word128Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -13589,7 +14593,9 @@ func (Word256Value) IsImportable(_ *Interpreter) bool { func (v Word256Value) ToInt(locationRange LocationRange) int { if !v.BigInt.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return int(v.BigInt.Int64()) } @@ -13629,9 +14635,10 @@ func (v Word256Value) Plus(interpreter *Interpreter, other NumberValue, location o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13662,7 +14669,7 @@ func (v Word256Value) Plus(interpreter *Interpreter, other NumberValue, location ) } -func (v Word256Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word256Value) SaturatingPlus(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13670,9 +14677,10 @@ func (v Word256Value) Minus(interpreter *Interpreter, other NumberValue, locatio o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13703,7 +14711,7 @@ func (v Word256Value) Minus(interpreter *Interpreter, other NumberValue, locatio ) } -func (v Word256Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word256Value) SaturatingMinus(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13711,9 +14719,10 @@ func (v Word256Value) Mod(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13722,7 +14731,9 @@ func (v Word256Value) Mod(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Rem(v.BigInt, o.BigInt) }, @@ -13733,9 +14744,10 @@ func (v Word256Value) Mul(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13752,7 +14764,7 @@ func (v Word256Value) Mul(interpreter *Interpreter, other NumberValue, locationR ) } -func (v Word256Value) SaturatingMul(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word256Value) SaturatingMul(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13760,9 +14772,10 @@ func (v Word256Value) Div(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13771,7 +14784,9 @@ func (v Word256Value) Div(interpreter *Interpreter, other NumberValue, locationR func() *big.Int { res := new(big.Int) if o.BigInt.Cmp(res) == 0 { - panic(DivisionByZeroError{LocationRange: locationRange}) + panic(DivisionByZeroError{ + LocationRange: locationRange, + }) } return res.Div(v.BigInt, o.BigInt) }, @@ -13779,7 +14794,7 @@ func (v Word256Value) Div(interpreter *Interpreter, other NumberValue, locationR } -func (v Word256Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, locationRange LocationRange) NumberValue { +func (v Word256Value) SaturatingDiv(_ *Interpreter, _ NumberValue, _ LocationRange) NumberValue { panic(errors.NewUnreachableError()) } @@ -13787,9 +14802,10 @@ func (v Word256Value) Less(interpreter *Interpreter, other ComparableValue, loca o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13801,9 +14817,10 @@ func (v Word256Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13815,9 +14832,10 @@ func (v Word256Value) Greater(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13829,9 +14847,10 @@ func (v Word256Value) GreaterEqual(interpreter *Interpreter, other ComparableVal o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13900,9 +14919,10 @@ func (v Word256Value) BitwiseOr(interpreter *Interpreter, other IntegerValue, lo o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseOr, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseOr, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13919,9 +14939,10 @@ func (v Word256Value) BitwiseXor(interpreter *Interpreter, other IntegerValue, l o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseXor, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseXor, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13938,9 +14959,10 @@ func (v Word256Value) BitwiseAnd(interpreter *Interpreter, other IntegerValue, l o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseAnd, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseAnd, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13958,9 +14980,10 @@ func (v Word256Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseLeftShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseLeftShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13969,10 +14992,14 @@ func (v Word256Value) BitwiseLeftShift(interpreter *Interpreter, other IntegerVa func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Lsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -13983,9 +15010,10 @@ func (v Word256Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV o, ok := other.(Word256Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationBitwiseRightShift, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationBitwiseRightShift, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -13994,10 +15022,14 @@ func (v Word256Value) BitwiseRightShift(interpreter *Interpreter, other IntegerV func() *big.Int { res := new(big.Int) if o.BigInt.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if !o.BigInt.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return res.Rsh(v.BigInt, uint(o.BigInt.Uint64())) }, @@ -14052,6 +15084,7 @@ func (v Word256Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -14103,11 +15136,15 @@ func NewFix64ValueWithInteger(gauge common.MemoryGauge, constructor func() int64 func NewUnmeteredFix64ValueWithInteger(integer int64, locationRange LocationRange) Fix64Value { if integer < sema.Fix64TypeMinInt { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } if integer > sema.Fix64TypeMaxInt { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewUnmeteredFix64Value(integer * sema.Fix64Factor) @@ -14167,14 +15204,16 @@ func (v Fix64Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferenc return v.String() } -func (v Fix64Value) ToInt(locationRange LocationRange) int { +func (v Fix64Value) ToInt(_ LocationRange) int { return int(v / sema.Fix64Factor) } func (v Fix64Value) Negate(interpreter *Interpreter, locationRange LocationRange) NumberValue { // INT32-C if v == math.MinInt64 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } valueGetter := func() int64 { @@ -14188,9 +15227,10 @@ func (v Fix64Value) Plus(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14205,9 +15245,10 @@ func (v Fix64Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14228,18 +15269,23 @@ func (v Fix64Value) Minus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } valueGetter := func() int64 { // INT32-C if (o > 0) && (v < (math.MinInt64 + o)) { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } else if (o < 0) && (v > (math.MaxInt64 + o)) { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return int64(v - o) @@ -14252,9 +15298,10 @@ func (v Fix64Value) SaturatingMinus(interpreter *Interpreter, other NumberValue, o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14278,9 +15325,10 @@ func (v Fix64Value) Mul(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14292,9 +15340,13 @@ func (v Fix64Value) Mul(interpreter *Interpreter, other NumberValue, locationRan result.Div(result, sema.Fix64FactorBig) if result.Cmp(minInt64Big) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if result.Cmp(maxInt64Big) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return result.Int64() @@ -14307,9 +15359,10 @@ func (v Fix64Value) SaturatingMul(interpreter *Interpreter, other NumberValue, l o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14336,9 +15389,10 @@ func (v Fix64Value) Div(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14350,9 +15404,13 @@ func (v Fix64Value) Div(interpreter *Interpreter, other NumberValue, locationRan result.Div(result, b) if result.Cmp(minInt64Big) < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } else if result.Cmp(maxInt64Big) > 0 { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return result.Int64() @@ -14365,9 +15423,10 @@ func (v Fix64Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, l o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14394,9 +15453,10 @@ func (v Fix64Value) Mod(interpreter *Interpreter, other NumberValue, locationRan o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14404,9 +15464,10 @@ func (v Fix64Value) Mod(interpreter *Interpreter, other NumberValue, locationRan quotient, ok := v.Div(interpreter, o, locationRange).(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14428,9 +15489,10 @@ func (v Fix64Value) Less(interpreter *Interpreter, other ComparableValue, locati o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14441,9 +15503,10 @@ func (v Fix64Value) LessEqual(interpreter *Interpreter, other ComparableValue, l o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14454,9 +15517,10 @@ func (v Fix64Value) Greater(interpreter *Interpreter, other ComparableValue, loc o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14467,9 +15531,10 @@ func (v Fix64Value) GreaterEqual(interpreter *Interpreter, other ComparableValue o, ok := other.(Fix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14500,7 +15565,9 @@ func ConvertFix64(memoryGauge common.MemoryGauge, value Value, locationRange Loc case UFix64Value: if value > Fix64MaxValue { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewFix64Value( memoryGauge, @@ -14518,7 +15585,9 @@ func ConvertFix64(memoryGauge common.MemoryGauge, value Value, locationRange Loc // allows us to call `v.Int64()` safely. if !v.IsInt64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return v.Int64() @@ -14592,6 +15661,7 @@ func (v Fix64Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -14643,7 +15713,9 @@ func NewUFix64ValueWithInteger(gauge common.MemoryGauge, constructor func() uint func NewUnmeteredUFix64ValueWithInteger(integer uint64, locationRange LocationRange) UFix64Value { if integer > sema.UFix64TypeMaxInt { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return NewUnmeteredUFix64Value(integer * sema.Fix64Factor) @@ -14703,7 +15775,7 @@ func (v UFix64Value) MeteredString(memoryGauge common.MemoryGauge, _ SeenReferen return v.String() } -func (v UFix64Value) ToInt(locationRange LocationRange) int { +func (v UFix64Value) ToInt(_ LocationRange) int { return int(v / sema.Fix64Factor) } @@ -14715,9 +15787,10 @@ func (v UFix64Value) Plus(interpreter *Interpreter, other NumberValue, locationR o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationPlus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationPlus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14732,9 +15805,10 @@ func (v UFix64Value) SaturatingPlus(interpreter *Interpreter, other NumberValue, o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingAddFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingAddFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14754,9 +15828,10 @@ func (v UFix64Value) Minus(interpreter *Interpreter, other NumberValue, location o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMinus, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMinus, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14765,7 +15840,9 @@ func (v UFix64Value) Minus(interpreter *Interpreter, other NumberValue, location // INT30-C if diff > v { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint64(diff) } @@ -14777,9 +15854,10 @@ func (v UFix64Value) SaturatingMinus(interpreter *Interpreter, other NumberValue o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingSubtractFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14800,9 +15878,10 @@ func (v UFix64Value) Mul(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMul, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMul, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14814,7 +15893,9 @@ func (v UFix64Value) Mul(interpreter *Interpreter, other NumberValue, locationRa result.Div(result, sema.Fix64FactorBig) if !result.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return result.Uint64() @@ -14827,9 +15908,10 @@ func (v UFix64Value) SaturatingMul(interpreter *Interpreter, other NumberValue, o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingMultiplyFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14854,9 +15936,10 @@ func (v UFix64Value) Div(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationDiv, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationDiv, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14878,9 +15961,10 @@ func (v UFix64Value) SaturatingDiv(interpreter *Interpreter, other NumberValue, r := recover() if _, ok := r.(InvalidOperandsError); ok { panic(InvalidOperandsError{ - FunctionName: sema.NumericTypeSaturatingDivideFunctionName, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + FunctionName: sema.NumericTypeSaturatingDivideFunctionName, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } }() @@ -14892,9 +15976,10 @@ func (v UFix64Value) Mod(interpreter *Interpreter, other NumberValue, locationRa o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14902,9 +15987,10 @@ func (v UFix64Value) Mod(interpreter *Interpreter, other NumberValue, locationRa quotient, ok := v.Div(interpreter, o, locationRange).(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationMod, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationMod, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14926,9 +16012,10 @@ func (v UFix64Value) Less(interpreter *Interpreter, other ComparableValue, locat o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLess, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLess, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14939,9 +16026,10 @@ func (v UFix64Value) LessEqual(interpreter *Interpreter, other ComparableValue, o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationLessEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationLessEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14952,9 +16040,10 @@ func (v UFix64Value) Greater(interpreter *Interpreter, other ComparableValue, lo o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreater, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreater, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14965,9 +16054,10 @@ func (v UFix64Value) GreaterEqual(interpreter *Interpreter, other ComparableValu o, ok := other.(UFix64Value) if !ok { panic(InvalidOperandsError{ - Operation: ast.OperationGreaterEqual, - LeftType: v.StaticType(interpreter), - RightType: other.StaticType(interpreter), + Operation: ast.OperationGreaterEqual, + LeftType: v.StaticType(interpreter), + RightType: other.StaticType(interpreter), + LocationRange: locationRange, }) } @@ -14998,7 +16088,9 @@ func ConvertUFix64(memoryGauge common.MemoryGauge, value Value, locationRange Lo case Fix64Value: if value < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return NewUFix64Value( memoryGauge, @@ -15012,7 +16104,9 @@ func ConvertUFix64(memoryGauge common.MemoryGauge, value Value, locationRange Lo v := value.ToBigInt(memoryGauge) if v.Sign() < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } // First, check if the value is at least in the uint64 range. @@ -15020,7 +16114,9 @@ func ConvertUFix64(memoryGauge common.MemoryGauge, value Value, locationRange Lo // allows us to call `v.UInt64()` safely. if !v.IsUint64() { - panic(OverflowError{LocationRange: locationRange}) + panic(OverflowError{ + LocationRange: locationRange, + }) } return v.Uint64() @@ -15033,7 +16129,9 @@ func ConvertUFix64(memoryGauge common.MemoryGauge, value Value, locationRange Lo converter := func() uint64 { v := value.ToInt(locationRange) if v < 0 { - panic(UnderflowError{LocationRange: locationRange}) + panic(UnderflowError{ + LocationRange: locationRange, + }) } return uint64(v) @@ -15097,6 +16195,7 @@ func (v UFix64Value) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -15395,7 +16494,7 @@ func (v *CompositeValue) Destroy(interpreter *Interpreter, locationRange Locatio var base *EphemeralReferenceValue var self MemberAccessibleValue = v if v.Kind == common.CompositeKindAttachment { - base, self = attachmentBaseAndSelfValues(interpreter, locationRange, v) + base, self = attachmentBaseAndSelfValues(interpreter, v) } invocation := NewInvocation( interpreter, @@ -15535,7 +16634,7 @@ func (v *CompositeValue) GetMember(interpreter *Interpreter, locationRange Locat var base *EphemeralReferenceValue var self MemberAccessibleValue = v if v.Kind == common.CompositeKindAttachment { - base, self = attachmentBaseAndSelfValues(interpreter, locationRange, v) + base, self = attachmentBaseAndSelfValues(interpreter, v) } return NewBoundFunctionValue(interpreter, function, &self, base) } @@ -15653,6 +16752,7 @@ func (v *CompositeValue) RemoveMember( atree.Address{}, true, existingValueStorable, + nil, ) } @@ -15694,6 +16794,9 @@ func (v *CompositeValue) SetMember( address, true, nil, + map[atree.StorageID]struct{}{ + v.StorageID(): {}, + }, ) existingStorable, err := v.dictionary.Set( @@ -15939,7 +17042,7 @@ func (v *CompositeValue) ConformsToStaticType( } if compositeType.Kind == common.CompositeKindAttachment { - base := v.getBaseValue(interpreter, locationRange).Value + base := v.getBaseValue().Value if base == nil || !base.ConformsToStaticType(interpreter, locationRange, results) { return false } @@ -16044,6 +17147,7 @@ func (v *CompositeValue) Transfer( address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value { baseUse, elementOverhead, dataUse, metaDataUse := common.NewCompositeMemoryUsages(v.dictionary.Count(), 0) @@ -16080,6 +17184,16 @@ func (v *CompositeValue) Transfer( currentStorageID := v.StorageID() currentAddress := v.StorageAddress() + if preventTransfer == nil { + preventTransfer = map[atree.StorageID]struct{}{} + } else if _, ok := preventTransfer[currentStorageID]; ok { + panic(RecursiveTransferError{ + LocationRange: locationRange, + }) + } + preventTransfer[currentStorageID] = struct{}{} + defer delete(preventTransfer, currentStorageID) + dictionary := v.dictionary needsStoreTo := v.NeedsStoreTo(address) @@ -16124,11 +17238,20 @@ func (v *CompositeValue) Transfer( value := MustConvertStoredValue(interpreter, atreeValue) // the base of an attachment is not stored in the atree, so in order to make the // transfer happen properly, we set the base value here if this field is an attachment - if compositeValue, ok := value.(*CompositeValue); ok && compositeValue.Kind == common.CompositeKindAttachment { + if compositeValue, ok := value.(*CompositeValue); ok && + compositeValue.Kind == common.CompositeKindAttachment { + compositeValue.setBaseValue(interpreter, v) } - value = value.Transfer(interpreter, locationRange, address, remove, nil) + value = value.Transfer( + interpreter, + locationRange, + address, + remove, + nil, + preventTransfer, + ) return atreeKey, value, nil }, @@ -16425,7 +17548,7 @@ func NewEnumCaseValue( return v } -func (v *CompositeValue) getBaseValue(interpreter *Interpreter, locationRange LocationRange) *EphemeralReferenceValue { +func (v *CompositeValue) getBaseValue() *EphemeralReferenceValue { return v.base } @@ -16470,10 +17593,9 @@ func (v *CompositeValue) GetAttachments(interpreter *Interpreter, locationRange func attachmentBaseAndSelfValues( interpreter *Interpreter, - locationRange LocationRange, v *CompositeValue, ) (base *EphemeralReferenceValue, self *EphemeralReferenceValue) { - base = v.getBaseValue(interpreter, locationRange) + base = v.getBaseValue() // in attachment functions, self is a reference value self = NewEphemeralReferenceValue(interpreter, false, v, interpreter.MustSemaTypeOfValue(v)) interpreter.trackReferencedResourceKindedValue(v.StorageID(), v) @@ -17117,7 +18239,14 @@ func (v *DictionaryValue) GetMember( } return MustConvertStoredValue(interpreter, key). - Transfer(interpreter, locationRange, atree.Address{}, false, nil) + Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, + ) }, ) @@ -17144,7 +18273,14 @@ func (v *DictionaryValue) GetMember( } return MustConvertStoredValue(interpreter, value). - Transfer(interpreter, locationRange, atree.Address{}, false, nil) + Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, + ) }) case "remove": @@ -17309,6 +18445,7 @@ func (v *DictionaryValue) Remove( atree.Address{}, true, existingValueStorable, + nil, ) return NewSomeValueNonCopying(interpreter, existingValue) @@ -17341,12 +18478,17 @@ func (v *DictionaryValue) Insert( address := v.dictionary.Address() + preventTransfer := map[atree.StorageID]struct{}{ + v.StorageID(): {}, + } + keyValue = keyValue.Transfer( interpreter, locationRange, address, true, nil, + preventTransfer, ) value = value.Transfer( @@ -17355,6 +18497,7 @@ func (v *DictionaryValue) Insert( address, true, nil, + preventTransfer, ) valueComparator := newValueComparator(interpreter, locationRange) @@ -17389,6 +18532,7 @@ func (v *DictionaryValue) Insert( atree.Address{}, true, existingValueStorable, + nil, ) return NewSomeValueNonCopying(interpreter, existingValue) @@ -17548,6 +18692,7 @@ func (v *DictionaryValue) Transfer( address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value { baseUse, elementOverhead, dataUse, metaDataUse := common.NewDictionaryMemoryUsages( v.dictionary.Count(), @@ -17583,6 +18728,16 @@ func (v *DictionaryValue) Transfer( currentStorageID := v.StorageID() + if preventTransfer == nil { + preventTransfer = map[atree.StorageID]struct{}{} + } else if _, ok := preventTransfer[currentStorageID]; ok { + panic(RecursiveTransferError{ + LocationRange: locationRange, + }) + } + preventTransfer[currentStorageID] = struct{}{} + defer delete(preventTransfer, currentStorageID) + dictionary := v.dictionary needsStoreTo := v.NeedsStoreTo(address) @@ -17620,10 +18775,10 @@ func (v *DictionaryValue) Transfer( } key := MustConvertStoredValue(interpreter, atreeKey). - Transfer(interpreter, locationRange, address, remove, nil) + Transfer(interpreter, locationRange, address, remove, nil, preventTransfer) value := MustConvertStoredValue(interpreter, atreeValue). - Transfer(interpreter, locationRange, address, remove, nil) + Transfer(interpreter, locationRange, address, remove, nil, preventTransfer) return key, value, nil }, @@ -17956,6 +19111,7 @@ func (v NilValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -18024,6 +19180,10 @@ func (v *SomeValue) Walk(_ *Interpreter, walkChild func(Value)) { } func (v *SomeValue) StaticType(inter *Interpreter) StaticType { + if v.isDestroyed { + return nil + } + innerType := v.value.StaticType(inter) if innerType == nil { return nil @@ -18237,6 +19397,7 @@ func (v *SomeValue) Transfer( address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value { config := interpreter.SharedState.Config @@ -18251,7 +19412,14 @@ func (v *SomeValue) Transfer( if needsStoreTo || !isResourceKinded { - innerValue = v.value.Transfer(interpreter, locationRange, address, remove, nil) + innerValue = v.value.Transfer( + interpreter, + locationRange, + address, + remove, + nil, + preventTransfer, + ) if remove { interpreter.RemoveReferencedSlab(v.valueStorable) @@ -18676,6 +19844,7 @@ func (v *StorageReferenceValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -18790,22 +19959,11 @@ func (*EphemeralReferenceValue) IsImportable(_ *Interpreter) bool { } func (v *EphemeralReferenceValue) ReferencedValue( - interpreter *Interpreter, - locationRange LocationRange, + _ *Interpreter, + _ LocationRange, _ bool, ) *Value { - // Just like for storage references, references to optionals are unwrapped, - // i.e. a reference to `nil` aborts when dereferenced. - - switch referenced := v.Value.(type) { - case *SomeValue: - innerValue := referenced.InnerValue(interpreter, locationRange) - return &innerValue - case NilValue: - return nil - default: - return &v.Value - } + return &v.Value } func (v *EphemeralReferenceValue) MustReferencedValue( @@ -19021,6 +20179,7 @@ func (v *EphemeralReferenceValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -19237,6 +20396,7 @@ func (v AddressValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -19522,6 +20682,7 @@ func (v PathValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -19739,6 +20900,7 @@ func (v *PathCapabilityValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { v.DeepRemove(interpreter) @@ -19940,6 +21102,7 @@ func (v *IDCapabilityValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { v.DeepRemove(interpreter) @@ -20088,6 +21251,7 @@ func (v PathLinkValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -20224,14 +21388,30 @@ func (v *PublishedValue) Transfer( address atree.Address, remove bool, storable atree.Storable, + preventTransfer map[atree.StorageID]struct{}, ) Value { // NB: if the inner value of a PublishedValue can be a resource, // we must perform resource-related checks here as well if v.NeedsStoreTo(address) { - innerValue := v.Value.Transfer(interpreter, locationRange, address, remove, nil).(CapabilityValue) - addressValue := v.Recipient.Transfer(interpreter, locationRange, address, remove, nil).(AddressValue) + innerValue := v.Value.Transfer( + interpreter, + locationRange, + address, + remove, + nil, + preventTransfer, + ).(CapabilityValue) + + addressValue := v.Recipient.Transfer( + interpreter, + locationRange, + address, + remove, + nil, + preventTransfer, + ).(AddressValue) if remove { interpreter.RemoveReferencedSlab(storable) @@ -20370,6 +21550,7 @@ func (v AccountLinkValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) diff --git a/runtime/interpreter/value_accountcapabilitycontroller.go b/runtime/interpreter/value_accountcapabilitycontroller.go index 3cbf569cce..5f400f5765 100644 --- a/runtime/interpreter/value_accountcapabilitycontroller.go +++ b/runtime/interpreter/value_accountcapabilitycontroller.go @@ -41,6 +41,7 @@ type AccountCapabilityControllerValue struct { // Tags are not stored directly inside the controller // to avoid unnecessary storage reads // when the controller is loaded for borrowing/checking + GetCapability func() *IDCapabilityValue GetTag func() *StringValue SetTag func(*StringValue) DeleteFunction FunctionValue @@ -110,7 +111,10 @@ func (v *AccountCapabilityControllerValue) RecursiveString(seenReferences SeenRe ) } -func (v *AccountCapabilityControllerValue) MeteredString(memoryGauge common.MemoryGauge, seenReferences SeenReferences) string { +func (v *AccountCapabilityControllerValue) MeteredString( + memoryGauge common.MemoryGauge, + seenReferences SeenReferences, +) string { common.UseMemory(memoryGauge, common.AccountCapabilityControllerValueStringMemoryUsage) return format.AccountCapabilityController( @@ -127,7 +131,11 @@ func (v *AccountCapabilityControllerValue) ConformsToStaticType( return true } -func (v *AccountCapabilityControllerValue) Equal(interpreter *Interpreter, locationRange LocationRange, other Value) bool { +func (v *AccountCapabilityControllerValue) Equal( + interpreter *Interpreter, + locationRange LocationRange, + other Value, +) bool { otherController, ok := other.(*AccountCapabilityControllerValue) if !ok { return false @@ -141,7 +149,14 @@ func (*AccountCapabilityControllerValue) IsStorable() bool { return true } -func (v *AccountCapabilityControllerValue) Storable(storage atree.SlabStorage, address atree.Address, maxInlineSize uint64) (atree.Storable, error) { +func (v *AccountCapabilityControllerValue) Storable( + storage atree.SlabStorage, + address atree.Address, + maxInlineSize uint64, +) ( + atree.Storable, + error, +) { return maybeLargeImmutableStorable(v, storage, address, maxInlineSize) } @@ -159,6 +174,7 @@ func (v *AccountCapabilityControllerValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -211,6 +227,9 @@ func (v *AccountCapabilityControllerValue) GetMember(inter *Interpreter, _ Locat case sema.AccountCapabilityControllerTypeDeleteFunctionName: return v.DeleteFunction + + case sema.AccountCapabilityControllerTypeCapabilityFieldName: + return v.GetCapability() } return nil @@ -221,7 +240,12 @@ func (*AccountCapabilityControllerValue) RemoveMember(_ *Interpreter, _ Location panic(errors.NewUnreachableError()) } -func (v *AccountCapabilityControllerValue) SetMember(_ *Interpreter, _ LocationRange, identifier string, value Value) bool { +func (v *AccountCapabilityControllerValue) SetMember( + _ *Interpreter, + _ LocationRange, + identifier string, + value Value, +) bool { switch identifier { case sema.AccountCapabilityControllerTypeTagFieldName: stringValue, ok := value.(*StringValue) @@ -236,6 +260,10 @@ func (v *AccountCapabilityControllerValue) SetMember(_ *Interpreter, _ LocationR panic(errors.NewUnreachableError()) } +func (v *AccountCapabilityControllerValue) ControllerCapabilityID() UInt64Value { + return v.CapabilityID +} + func (v *AccountCapabilityControllerValue) ReferenceValue( interpreter *Interpreter, capabilityAddress common.Address, diff --git a/runtime/interpreter/value_accountreference.go b/runtime/interpreter/value_accountreference.go index 164dd19e96..5bee11ed14 100644 --- a/runtime/interpreter/value_accountreference.go +++ b/runtime/interpreter/value_accountreference.go @@ -276,6 +276,7 @@ func (v *AccountReferenceValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) diff --git a/runtime/interpreter/value_function.go b/runtime/interpreter/value_function.go index e2e17c4c50..1734d966dd 100644 --- a/runtime/interpreter/value_function.go +++ b/runtime/interpreter/value_function.go @@ -152,6 +152,7 @@ func (f *InterpretedFunctionValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { // TODO: actually not needed, value is not storable if remove { @@ -300,6 +301,7 @@ func (f *HostFunctionValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { // TODO: actually not needed, value is not storable if remove { @@ -426,6 +428,7 @@ func (f BoundFunctionValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { // TODO: actually not needed, value is not storable if remove { diff --git a/runtime/interpreter/value_publickey.go b/runtime/interpreter/value_publickey.go index 9672ceeee6..9193ed3253 100644 --- a/runtime/interpreter/value_publickey.go +++ b/runtime/interpreter/value_publickey.go @@ -65,7 +65,14 @@ func NewPublicKeyValue( publicKeyValue.ComputedFields = map[string]ComputedField{ sema.PublicKeyTypePublicKeyFieldName: func(interpreter *Interpreter, locationRange LocationRange) Value { - return publicKey.Transfer(interpreter, locationRange, atree.Address{}, false, nil) + return publicKey.Transfer( + interpreter, + locationRange, + atree.Address{}, + false, + nil, + nil, + ) }, } publicKeyValue.Functions = map[string]FunctionValue{ diff --git a/runtime/interpreter/value_storagecapabilitycontroller.go b/runtime/interpreter/value_storagecapabilitycontroller.go index 43e0ca2dae..470809612c 100644 --- a/runtime/interpreter/value_storagecapabilitycontroller.go +++ b/runtime/interpreter/value_storagecapabilitycontroller.go @@ -36,6 +36,7 @@ type CapabilityControllerValue interface { capabilityAddress common.Address, resultBorrowType *sema.ReferenceType, ) ReferenceValue + ControllerCapabilityID() UInt64Value } // StorageCapabilityControllerValue @@ -53,6 +54,7 @@ type StorageCapabilityControllerValue struct { // Tags are not stored directly inside the controller // to avoid unnecessary storage reads // when the controller is loaded for borrowing/checking + GetCapability func() *IDCapabilityValue GetTag func() *StringValue SetTag func(*StringValue) TargetFunction FunctionValue @@ -130,7 +132,10 @@ func (v *StorageCapabilityControllerValue) RecursiveString(seenReferences SeenRe ) } -func (v *StorageCapabilityControllerValue) MeteredString(memoryGauge common.MemoryGauge, seenReferences SeenReferences) string { +func (v *StorageCapabilityControllerValue) MeteredString( + memoryGauge common.MemoryGauge, + seenReferences SeenReferences, +) string { common.UseMemory(memoryGauge, common.StorageCapabilityControllerValueStringMemoryUsage) return format.StorageCapabilityController( @@ -148,7 +153,11 @@ func (v *StorageCapabilityControllerValue) ConformsToStaticType( return true } -func (v *StorageCapabilityControllerValue) Equal(interpreter *Interpreter, locationRange LocationRange, other Value) bool { +func (v *StorageCapabilityControllerValue) Equal( + interpreter *Interpreter, + locationRange LocationRange, + other Value, +) bool { otherController, ok := other.(*StorageCapabilityControllerValue) if !ok { return false @@ -163,7 +172,14 @@ func (*StorageCapabilityControllerValue) IsStorable() bool { return true } -func (v *StorageCapabilityControllerValue) Storable(storage atree.SlabStorage, address atree.Address, maxInlineSize uint64) (atree.Storable, error) { +func (v *StorageCapabilityControllerValue) Storable( + storage atree.SlabStorage, + address atree.Address, + maxInlineSize uint64, +) ( + atree.Storable, + error, +) { return maybeLargeImmutableStorable(v, storage, address, maxInlineSize) } @@ -181,6 +197,7 @@ func (v *StorageCapabilityControllerValue) Transfer( _ atree.Address, remove bool, storable atree.Storable, + _ map[atree.StorageID]struct{}, ) Value { if remove { interpreter.RemoveReferencedSlab(storable) @@ -241,6 +258,9 @@ func (v *StorageCapabilityControllerValue) GetMember(inter *Interpreter, _ Locat case sema.StorageCapabilityControllerTypeDeleteFunctionName: return v.DeleteFunction + + case sema.StorageCapabilityControllerTypeCapabilityFieldName: + return v.GetCapability() } return nil @@ -251,7 +271,12 @@ func (*StorageCapabilityControllerValue) RemoveMember(_ *Interpreter, _ Location panic(errors.NewUnreachableError()) } -func (v *StorageCapabilityControllerValue) SetMember(_ *Interpreter, _ LocationRange, identifier string, value Value) bool { +func (v *StorageCapabilityControllerValue) SetMember( + _ *Interpreter, + _ LocationRange, + identifier string, + value Value, +) bool { switch identifier { case sema.StorageCapabilityControllerTypeTagFieldName: stringValue, ok := value.(*StringValue) @@ -266,6 +291,10 @@ func (v *StorageCapabilityControllerValue) SetMember(_ *Interpreter, _ LocationR panic(errors.NewUnreachableError()) } +func (v *StorageCapabilityControllerValue) ControllerCapabilityID() UInt64Value { + return v.CapabilityID +} + func (v *StorageCapabilityControllerValue) ReferenceValue( interpreter *Interpreter, capabilityAddress common.Address, diff --git a/runtime/interpreter/value_test.go b/runtime/interpreter/value_test.go index 4056ffee24..dd8e35b2e6 100644 --- a/runtime/interpreter/value_test.go +++ b/runtime/interpreter/value_test.go @@ -175,6 +175,7 @@ func TestOwnerArrayDeepCopy(t *testing.T) { atree.Address(newOwner), false, nil, + nil, ) array = arrayCopy.(*ArrayValue) @@ -568,6 +569,7 @@ func TestOwnerDictionaryCopy(t *testing.T) { atree.Address{}, false, nil, + nil, ) dictionaryCopy := copyResult.(*DictionaryValue) @@ -871,6 +873,7 @@ func TestOwnerCompositeCopy(t *testing.T) { atree.Address{}, false, nil, + nil, ).(*CompositeValue) value = composite.GetMember( diff --git a/runtime/literal.go b/runtime/literal.go index 521db21801..6b7d42ef37 100644 --- a/runtime/literal.go +++ b/runtime/literal.go @@ -97,7 +97,8 @@ func ParseLiteralArgumentList( parameterType := parameterTypes[i] value, err := LiteralValue(inter, argument.Expression, parameterType) if err != nil { - return nil, parser.NewUnpositionedSyntaxError( + return nil, parser.NewSyntaxError( + argument.Expression.StartPosition(), "invalid argument at index %d: %v", i, err, ) } diff --git a/runtime/parser/declaration_test.go b/runtime/parser/declaration_test.go index f50618c322..03eabad929 100644 --- a/runtime/parser/declaration_test.go +++ b/runtime/parser/declaration_test.go @@ -5513,7 +5513,7 @@ func TestParseEventEmitStatement(t *testing.T) { { Label: "to", LabelStartPos: &ast.Position{Offset: 42, Line: 3, Column: 22}, - LabelEndPos: &ast.Position{Offset: 43, Line: 3, Column: 23}, + LabelEndPos: &ast.Position{Offset: 44, Line: 3, Column: 24}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("1"), Value: big.NewInt(1), @@ -5528,7 +5528,7 @@ func TestParseEventEmitStatement(t *testing.T) { { Label: "from", LabelStartPos: &ast.Position{Offset: 49, Line: 3, Column: 29}, - LabelEndPos: &ast.Position{Offset: 52, Line: 3, Column: 32}, + LabelEndPos: &ast.Position{Offset: 53, Line: 3, Column: 33}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("2"), Value: big.NewInt(2), diff --git a/runtime/parser/errors.go b/runtime/parser/errors.go index e870aacbd4..5e2381e8d2 100644 --- a/runtime/parser/errors.go +++ b/runtime/parser/errors.go @@ -74,6 +74,7 @@ func NewSyntaxError(pos ast.Position, message string, params ...any) *SyntaxErro func NewUnpositionedSyntaxError(message string, params ...any) *SyntaxError { return &SyntaxError{ + Pos: ast.Position{Line: 1}, Message: fmt.Sprintf(message, params...), } } diff --git a/runtime/parser/expression.go b/runtime/parser/expression.go index b95629e7ab..81620434a0 100644 --- a/runtime/parser/expression.go +++ b/runtime/parser/expression.go @@ -198,7 +198,7 @@ func defineExpr(def any) { func setExprNullDenotation(tokenType lexer.TokenType, nullDenotation exprNullDenotationFunc) { current := exprNullDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "expression null denotation for token %s already exists", tokenType, )) @@ -225,7 +225,7 @@ func setExprIdentifierLeftBindingPower(keyword string, power int) { func setExprLeftDenotation(tokenType lexer.TokenType, leftDenotation exprLeftDenotationFunc) { current := exprLeftDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "expression left denotation for token %s already exists", tokenType, )) @@ -237,7 +237,7 @@ func setExprLeftDenotation(tokenType lexer.TokenType, leftDenotation exprLeftDen func setExprMetaLeftDenotation(tokenType lexer.TokenType, metaLeftDenotation exprMetaLeftDenotationFunc) { current := exprMetaLeftDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "expression meta left denotation for token %s already exists", tokenType, )) @@ -1054,6 +1054,8 @@ func parseArgument(p *parser) (*ast.Argument, error) { // If a colon follows the expression, the expression was our label. if p.current.Is(lexer.TokenColon) { + labelEndPos = p.current.EndPos + identifier, ok := expr.(*ast.IdentifierExpression) if !ok { return nil, p.syntaxError( @@ -1063,7 +1065,6 @@ func parseArgument(p *parser) (*ast.Argument, error) { } label = identifier.Identifier.Identifier labelStartPos = expr.StartPosition() - labelEndPos = expr.EndPosition(p.memoryGauge) // Skip the identifier p.nextSemanticToken() diff --git a/runtime/parser/expression_test.go b/runtime/parser/expression_test.go index b07901f4b7..b8c6083523 100644 --- a/runtime/parser/expression_test.go +++ b/runtime/parser/expression_test.go @@ -1478,7 +1478,7 @@ func TestParseInvocation(t *testing.T) { { Label: "label", LabelStartPos: &ast.Position{Offset: 2, Line: 1, Column: 2}, - LabelEndPos: &ast.Position{Offset: 6, Line: 1, Column: 6}, + LabelEndPos: &ast.Position{Offset: 7, Line: 1, Column: 7}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("1"), Value: big.NewInt(1), @@ -1567,7 +1567,7 @@ func TestParseInvocation(t *testing.T) { { Label: "a", LabelStartPos: &ast.Position{Offset: 2, Line: 1, Column: 2}, - LabelEndPos: &ast.Position{Offset: 2, Line: 1, Column: 2}, + LabelEndPos: &ast.Position{Offset: 3, Line: 1, Column: 3}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("1"), Value: big.NewInt(1), @@ -1582,7 +1582,7 @@ func TestParseInvocation(t *testing.T) { { Label: "b", LabelStartPos: &ast.Position{Offset: 6, Line: 1, Column: 6}, - LabelEndPos: &ast.Position{Offset: 6, Line: 1, Column: 6}, + LabelEndPos: &ast.Position{Offset: 7, Line: 1, Column: 7}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("2"), Value: big.NewInt(2), @@ -4637,7 +4637,7 @@ func TestParseInvocationExpressionWithLabels(t *testing.T) { t.Parallel() const code = ` - let a = b(x: 1, y: 2) + let a = b(x: 1, y: 2, z : 3) ` result, errs := testParseProgram(code) require.Empty(t, errs) @@ -4665,7 +4665,7 @@ func TestParseInvocationExpressionWithLabels(t *testing.T) { { Label: "x", LabelStartPos: &ast.Position{Offset: 16, Line: 2, Column: 15}, - LabelEndPos: &ast.Position{Offset: 16, Line: 2, Column: 15}, + LabelEndPos: &ast.Position{Offset: 17, Line: 2, Column: 16}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("1"), Value: big.NewInt(1), @@ -4680,7 +4680,7 @@ func TestParseInvocationExpressionWithLabels(t *testing.T) { { Label: "y", LabelStartPos: &ast.Position{Offset: 22, Line: 2, Column: 21}, - LabelEndPos: &ast.Position{Offset: 22, Line: 2, Column: 21}, + LabelEndPos: &ast.Position{Offset: 23, Line: 2, Column: 22}, Expression: &ast.IntegerExpression{ PositiveLiteral: []byte("2"), Value: big.NewInt(2), @@ -4692,9 +4692,24 @@ func TestParseInvocationExpressionWithLabels(t *testing.T) { }, TrailingSeparatorPos: ast.Position{Offset: 26, Line: 2, Column: 25}, }, + { + Label: "z", + LabelStartPos: &ast.Position{Offset: 28, Line: 2, Column: 27}, + LabelEndPos: &ast.Position{Offset: 30, Line: 2, Column: 29}, + Expression: &ast.IntegerExpression{ + PositiveLiteral: []byte("3"), + Value: big.NewInt(3), + Base: 10, + Range: ast.Range{ + StartPos: ast.Position{Offset: 32, Line: 2, Column: 31}, + EndPos: ast.Position{Offset: 32, Line: 2, Column: 31}, + }, + }, + TrailingSeparatorPos: ast.Position{Offset: 33, Line: 2, Column: 32}, + }, }, ArgumentsStartPos: ast.Position{Offset: 15, Line: 2, Column: 14}, - EndPos: ast.Position{Offset: 26, Line: 2, Column: 25}, + EndPos: ast.Position{Offset: 33, Line: 2, Column: 32}, }, StartPos: ast.Position{Offset: 6, Line: 2, Column: 5}, }, diff --git a/runtime/parser/parser_test.go b/runtime/parser/parser_test.go index 4ebb853610..7b547afb7e 100644 --- a/runtime/parser/parser_test.go +++ b/runtime/parser/parser_test.go @@ -791,9 +791,9 @@ func TestParseArgumentList(t *testing.T) { Column: 4, }, LabelEndPos: &ast.Position{ - Offset: 4, + Offset: 5, Line: 1, - Column: 4, + Column: 5, }, Expression: &ast.BoolExpression{ Value: true, diff --git a/runtime/parser/type.go b/runtime/parser/type.go index 1c862419a8..80b764b98f 100644 --- a/runtime/parser/type.go +++ b/runtime/parser/type.go @@ -53,7 +53,7 @@ var typeMetaLeftDenotations [lexer.TokenMax]typeMetaLeftDenotationFunc func setTypeNullDenotation(tokenType lexer.TokenType, nullDenotation typeNullDenotationFunc) { current := typeNullDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "type null denotation for token %s already exists", tokenType, )) @@ -72,7 +72,7 @@ func setTypeLeftBindingPower(tokenType lexer.TokenType, power int) { func setTypeLeftDenotation(tokenType lexer.TokenType, leftDenotation typeLeftDenotationFunc) { current := typeLeftDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "type left denotation for token %s already exists", tokenType, )) @@ -83,7 +83,7 @@ func setTypeLeftDenotation(tokenType lexer.TokenType, leftDenotation typeLeftDen func setTypeMetaLeftDenotation(tokenType lexer.TokenType, metaLeftDenotation typeMetaLeftDenotationFunc) { current := typeMetaLeftDenotations[tokenType] if current != nil { - panic(NewUnpositionedSyntaxError( + panic(errors.NewUnexpectedError( "type meta left denotation for token %s already exists", tokenType, )) diff --git a/runtime/runtime.go b/runtime/runtime.go index 1ed4f9d6d7..d34514f59f 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -263,6 +263,7 @@ func getWrappedError(recovered any, location Location, codesAndPrograms codesAnd return newError(err, location, codesAndPrograms) } } + func (r *interpreterRuntime) NewScriptExecutor( script Script, context Context, diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 35d9fe1f71..e32394af78 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -198,7 +198,7 @@ type testRuntimeInterface struct { programParsed func(location Location, duration time.Duration) programChecked func(location Location, duration time.Duration) programInterpreted func(location Location, duration time.Duration) - unsafeRandom func() (uint64, error) + readRandom func([]byte) error verifySignature func( signature []byte, tag string, @@ -513,11 +513,11 @@ func (i *testRuntimeInterface) GetBlockAtHeight(height uint64) (block stdlib.Blo return block, true, nil } -func (i *testRuntimeInterface) UnsafeRandom() (uint64, error) { - if i.unsafeRandom == nil { - return 0, nil +func (i *testRuntimeInterface) ReadRandom(buffer []byte) error { + if i.readRandom == nil { + return nil } - return i.unsafeRandom() + return i.readRandom(buffer) } func (i *testRuntimeInterface) VerifySignature( @@ -4752,8 +4752,9 @@ func TestRuntimeUnsafeRandom(t *testing.T) { var loggedMessages []string runtimeInterface := &testRuntimeInterface{ - unsafeRandom: func() (uint64, error) { - return 7558174677681708339, nil + readRandom: func(buffer []byte) error { + binary.LittleEndian.PutUint64(buffer, 7558174677681708339) + return nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -7704,7 +7705,7 @@ func assertRuntimeErrorIsInternalError(t *testing.T, err error) { require.True( t, runtimeErrors.IsInternalError(innerError), - "Expected `UserError`, found `%T`", innerError, + "Expected `InternalError`, found `%T`", innerError, ) } @@ -8638,3 +8639,675 @@ func TestInvalidatedResourceUse2(t *testing.T) { var destroyedResourceErr interpreter.DestroyedResourceError require.ErrorAs(t, err, &destroyedResourceErr) } + +func TestRuntimeInvalidRecursiveTransferViaVariableDeclaration(t *testing.T) { + + t.Parallel() + + runtime := newTestInterpreterRuntime() + runtime.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + + contract := []byte(` + pub contract Test{ + + pub resource Holder{ + + pub var vaults: @[AnyResource] + + init(_ vaults: @[AnyResource]){ + self.vaults <- vaults + } + + pub fun x(): @[AnyResource] { + var x <- self.vaults <- [<-Test.dummy()] + return <-x + } + + destroy() { + var t <- self.vaults[0] <- self.vaults // here is the problem + destroy t + Test.account.save(<- self.x(), to: /storage/x42) + } + } + + pub fun createHolder(_ vaults: @[AnyResource]): @Holder { + return <- create Holder(<-vaults) + } + + pub resource Dummy {} + + pub fun dummy(): @Dummy { + return <- create Dummy() + } + } + `) + + tx := []byte(` + import Test from 0x1 + + transaction { + + prepare(acct: AuthAccount) { + var holder <- Test.createHolder(<-[<-Test.dummy(), <-Test.dummy()]) + destroy holder + } + } + `) + + deploy := DeploymentTransaction("Test", contract) + + var accountCode []byte + var events []cadence.Event + + runtimeInterface := &testRuntimeInterface{ + getCode: func(_ Location) (bytes []byte, err error) { + return accountCode, nil + }, + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { + return accountCode, nil + }, + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { + accountCode = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + // Deploy + + err := runtime.ExecuteTransaction( + Script{ + Source: deploy, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Test + + err = runtime.ExecuteTransaction( + Script{ + Source: tx, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + RequireError(t, err) + + require.ErrorAs(t, err, &interpreter.RecursiveTransferError{}) +} + +func TestRuntimeInvalidRecursiveTransferViaFunctionArgument(t *testing.T) { + + t.Parallel() + + runtime := newTestInterpreterRuntime() + runtime.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + + contract := []byte(` + pub contract Test{ + + pub resource Holder { + + pub var vaults: @[AnyResource] + + init(_ vaults: @[AnyResource]) { + self.vaults <- vaults + } + + destroy() { + self.vaults.append(<-self.vaults) + } + } + + pub fun createHolder(_ vaults: @[AnyResource]): @Holder { + return <- create Holder(<-vaults) + } + + pub resource Dummy {} + + pub fun dummy(): @Dummy { + return <- create Dummy() + } + } + `) + + tx := []byte(` + import Test from 0x1 + + transaction { + + prepare(acct: AuthAccount) { + var holder <- Test.createHolder(<-[<-Test.dummy(), <-Test.dummy()]) + destroy holder + } + } + `) + + deploy := DeploymentTransaction("Test", contract) + + var accountCode []byte + var events []cadence.Event + + runtimeInterface := &testRuntimeInterface{ + getCode: func(_ Location) (bytes []byte, err error) { + return accountCode, nil + }, + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { + return accountCode, nil + }, + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { + accountCode = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + // Deploy + + err := runtime.ExecuteTransaction( + Script{ + Source: deploy, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Test + + err = runtime.ExecuteTransaction( + Script{ + Source: tx, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + RequireError(t, err) + + require.ErrorAs(t, err, &interpreter.RecursiveTransferError{}) +} + +func TestRuntimeOptionalReferenceAttack(t *testing.T) { + + t.Parallel() + + script := ` + pub resource Vault { + pub var balance: UFix64 + + init(balance: UFix64) { + self.balance = balance + } + + pub fun withdraw(amount: UFix64): @Vault { + self.balance = self.balance - amount + return <-create Vault(balance: amount) + } + + pub fun deposit(from: @Vault) { + self.balance = self.balance + from.balance + destroy from + } + } + + pub fun empty(): @Vault { + return <- create Vault(balance: 0.0) + } + + pub fun giveme(): @Vault { + return <- create Vault(balance: 10.0) + } + + pub fun main() { + var vault <- giveme() //get 10 token + var someDict:@{Int:Vault} <- {1:<-vault} + var r = (&someDict[1] as auth &AnyResource) as! &Vault + var double <- empty() + double.deposit(from: <- someDict.remove(key:1)!) + double.deposit(from: <- r.withdraw(amount:10.0)) + log(double.balance) // 20 + destroy double + destroy someDict + } + ` + + runtime := newTestInterpreterRuntime() + + accountCodes := map[common.Location][]byte{} + + var events []cadence.Event + + signerAccount := common.MustBytesToAddress([]byte{0x1}) + + storage := newTestLedger(nil, nil) + + runtimeInterface := &testRuntimeInterface{ + getCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + storage: storage, + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAccount}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + log: func(s string) { + + }, + } + runtimeInterface.decodeArgument = func(b []byte, t cadence.Type) (value cadence.Value, err error) { + return json.Decode(nil, b) + } + + _, err := runtime.ExecuteScript( + Script{ + Source: []byte(script), + Arguments: [][]byte{}, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + RequireError(t, err) + + var checkerErr *sema.CheckerError + require.ErrorAs(t, err, &checkerErr) + + errs := checker.RequireCheckerErrors(t, checkerErr, 1) + + assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) +} + +func TestRuntimeReturnDestroyedOptional(t *testing.T) { + + t.Parallel() + + runtime := newTestInterpreterRuntime() + + script := []byte(` + pub resource Foo {} + + pub fun main(): AnyStruct { + let y: @Foo? <- create Foo() + let z: @AnyResource <- y + var ref = &z as &AnyResource + destroy z + return ref + } + `) + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + } + + // Test + + _, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + RequireError(t, err) + + require.ErrorAs(t, err, &interpreter.DestroyedResourceError{}) +} + +func TestRuntimeComputationMeteringError(t *testing.T) { + + t.Parallel() + + runtime := newTestInterpreterRuntime() + + t.Run("regular error returned", func(t *testing.T) { + t.Parallel() + + script := []byte(` + access(all) fun foo() {} + + pub fun main() { + foo() + } + `) + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + meterComputation: func(compKind common.ComputationKind, intensity uint) error { + return fmt.Errorf("computation limit exceeded") + }, + } + + _, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + require.Error(t, err) + + // Returned error MUST be an external error. + // It can NOT be an internal error. + assertRuntimeErrorIsExternalError(t, err) + }) + + t.Run("regular error panicked", func(t *testing.T) { + t.Parallel() + + script := []byte(` + access(all) fun foo() {} + + pub fun main() { + foo() + } + `) + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + meterComputation: func(compKind common.ComputationKind, intensity uint) error { + panic(fmt.Errorf("computation limit exceeded")) + }, + } + + _, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + require.Error(t, err) + + // Returned error MUST be an external error. + // It can NOT be an internal error. + assertRuntimeErrorIsExternalError(t, err) + }) + + t.Run("go runtime error panicked", func(t *testing.T) { + t.Parallel() + + script := []byte(` + access(all) fun foo() {} + + pub fun main() { + foo() + } + `) + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + meterComputation: func(compKind common.ComputationKind, intensity uint) error { + // Cause a runtime error + var x any = "hello" + _ = x.(int) + return nil + }, + } + + _, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + require.Error(t, err) + + // Returned error MUST be an internal error. + assertRuntimeErrorIsInternalError(t, err) + }) + + t.Run("go runtime error returned", func(t *testing.T) { + t.Parallel() + + script := []byte(` + access(all) fun foo() {} + + pub fun main() { + foo() + } + `) + + runtimeInterface := &testRuntimeInterface{ + storage: newTestLedger(nil, nil), + meterComputation: func(compKind common.ComputationKind, intensity uint) (err error) { + // Cause a runtime error. Catch it and return. + var x any = "hello" + defer func() { + if r := recover(); r != nil { + if r, ok := r.(error); ok { + err = r + } + } + }() + + _ = x.(int) + + return + }, + } + + _, err := runtime.ExecuteScript( + Script{ + Source: script, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + require.Error(t, err) + + // Returned error MUST be an internal error. + assertRuntimeErrorIsInternalError(t, err) + }) +} + +func TestRuntimeWrappedErrorHandling(t *testing.T) { + + t.Parallel() + + foo := []byte(` + access(all) contract Foo { + access(all) resource R { + access(all) var x: Int + + init() { + self.x = 0 + } + } + + access(all) fun createR(): @R { + return <-create R() + } + } + `) + + brokenFoo := []byte(` + access(all) contract Foo { + access(all) resource R { + access(all) var x: Int + + init() { + self.x = "hello" + } + } + + access(all) fun createR(): @R { + return <-create R() + } + } + `) + + tx1 := []byte(` + import Foo from 0x1 + + transaction { + prepare(signer: AuthAccount) { + signer.save(<- Foo.createR(), to: /storage/r) + signer.link<&Foo.R>(/private/r, target:/storage/r) + } + } + `) + + tx2 := []byte(` + transaction { + prepare(signer: AuthAccount) { + var cap = signer.getCapability<&AnyStruct>(/private/r) + cap.check() + } + } + `) + + runtime := newTestInterpreterRuntime() + runtime.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + + deploy := DeploymentTransaction("Foo", foo) + + var contractCode []byte + var events []cadence.Event + + isContractBroken := false + + runtimeInterface := &testRuntimeInterface{ + getCode: func(_ Location) (bytes []byte, err error) { + return contractCode, nil + }, + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { + if isContractBroken && contractCode != nil { + return brokenFoo, nil + } + return contractCode, nil + }, + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { + contractCode = code + return nil + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + getAndSetProgram: func(location Location, load func() (*interpreter.Program, error)) (*interpreter.Program, error) { + program, err := load() + if err == nil { + return program, nil + } + return program, fmt.Errorf("wrapped error: %w", err) + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + // Deploy + + err := runtime.ExecuteTransaction( + Script{ + Source: deploy, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Run Tx to save values + + err = runtime.ExecuteTransaction( + Script{ + Source: tx1, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Run Tx to load value. + // Mark the contract is broken + + isContractBroken = true + + err = runtime.ExecuteTransaction( + Script{ + Source: tx2, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + + RequireError(t, err) + + // Returned error MUST be a user error. + // It can NOT be an internal error. + assertRuntimeErrorIsUserError(t, err) +} diff --git a/runtime/script_executor.go b/runtime/script_executor.go index ced232ac18..8ce26c534c 100644 --- a/runtime/script_executor.go +++ b/runtime/script_executor.go @@ -195,6 +195,7 @@ func (executor *interpreterScriptExecutor) execute() (val cadence.Value, err err } // Export before committing storage + exportableValue := newExportableValue(value, inter) result, err := exportValue( exportableValue, @@ -241,6 +242,6 @@ func (executor *interpreterScriptExecutor) scriptExecutionFunction() InterpretFu return nil, err } - return inter.Invoke("main", values...) + return inter.Invoke(sema.FunctionEntryPointName, values...) } } diff --git a/runtime/sema/account_capability_controller.cdc b/runtime/sema/account_capability_controller.cdc index 3dae2cc270..200ce7d88a 100644 --- a/runtime/sema/account_capability_controller.cdc +++ b/runtime/sema/account_capability_controller.cdc @@ -1,5 +1,9 @@ pub struct AccountCapabilityController { + /// The capability that is controlled by this controller. + access(all) + let capability: Capability + /// An arbitrary "tag" for the controller. /// For example, it could be used to describe the purpose of the capability. /// Empty by default. diff --git a/runtime/sema/account_capability_controller.gen.go b/runtime/sema/account_capability_controller.gen.go index 8777333b82..b9317b4d39 100644 --- a/runtime/sema/account_capability_controller.gen.go +++ b/runtime/sema/account_capability_controller.gen.go @@ -21,6 +21,14 @@ package sema import "github.com/onflow/cadence/runtime/ast" +const AccountCapabilityControllerTypeCapabilityFieldName = "capability" + +var AccountCapabilityControllerTypeCapabilityFieldType = &CapabilityType{} + +const AccountCapabilityControllerTypeCapabilityFieldDocString = ` +The capability that is controlled by this controller. +` + const AccountCapabilityControllerTypeTagFieldName = "tag" var AccountCapabilityControllerTypeTagFieldType = StringType @@ -87,6 +95,14 @@ var AccountCapabilityControllerType = &SimpleType{ func init() { AccountCapabilityControllerType.Members = func(t *SimpleType) map[string]MemberResolver { return MembersAsResolvers([]*Member{ + NewUnmeteredFieldMember( + t, + ast.AccessPublic, + ast.VariableKindConstant, + AccountCapabilityControllerTypeCapabilityFieldName, + AccountCapabilityControllerTypeCapabilityFieldType, + AccountCapabilityControllerTypeCapabilityFieldDocString, + ), NewUnmeteredFieldMember( t, ast.AccessPublicSettable, diff --git a/runtime/sema/authaccount.cdc b/runtime/sema/authaccount.cdc index 8617ee2ab6..4814762454 100644 --- a/runtime/sema/authaccount.cdc +++ b/runtime/sema/authaccount.cdc @@ -117,8 +117,6 @@ pub struct AuthAccount { /// The path must be a storage path, i.e., only the domain `storage` is allowed. pub fun check(from: StoragePath): Bool - /// **DEPRECATED**: Instead, use `capabilities.storage.issue`, and `capabilities.publish` if the path is public. - /// /// Creates a capability at the given public or private path, /// which targets the given public, private, or storage path. /// @@ -139,26 +137,18 @@ pub struct AuthAccount { /// and the target value might be moved out after the link has been created. pub fun link(_ newCapabilityPath: CapabilityPath, target: Path): Capability? - /// **DEPRECATED**: Use `capabilities.account.issue` instead. - /// /// Creates a capability at the given public or private path which targets this account. /// /// Returns nil if a link for the given capability path already exists, or the newly created capability if not. pub fun linkAccount(_ newCapabilityPath: PrivatePath): Capability<&AuthAccount>? - /// **DEPRECATED**: Use `capabilities.get` instead. - /// /// Returns the capability at the given private or public path. pub fun getCapability(_ path: CapabilityPath): Capability - /// **DEPRECATED**: Use `capabilities.storage.getController` and `StorageCapabilityController.target()`. - /// /// Returns the target path of the capability at the given public or private path, /// or nil if there exists no capability at the given path. pub fun getLinkTarget(_ path: CapabilityPath): Path? - /// **DEPRECATED**: Use `capabilities.unpublish` instead if the path is public. - /// /// Removes the capability at the given public or private path. pub fun unlink(_ path: CapabilityPath) diff --git a/runtime/sema/authaccount.gen.go b/runtime/sema/authaccount.gen.go index 3425d5deeb..bc39b67733 100644 --- a/runtime/sema/authaccount.gen.go +++ b/runtime/sema/authaccount.gen.go @@ -431,8 +431,6 @@ var AuthAccountTypeLinkFunctionType = &FunctionType{ } const AuthAccountTypeLinkFunctionDocString = ` -**DEPRECATED**: Instead, use ` + "`capabilities.storage.issue`" + `, and ` + "`capabilities.publish`" + ` if the path is public. - Creates a capability at the given public or private path, which targets the given public, private, or storage path. @@ -476,8 +474,6 @@ var AuthAccountTypeLinkAccountFunctionType = &FunctionType{ } const AuthAccountTypeLinkAccountFunctionDocString = ` -**DEPRECATED**: Use ` + "`capabilities.account.issue`" + ` instead. - Creates a capability at the given public or private path which targets this account. Returns nil if a link for the given capability path already exists, or the newly created capability if not. @@ -514,8 +510,6 @@ var AuthAccountTypeGetCapabilityFunctionType = &FunctionType{ } const AuthAccountTypeGetCapabilityFunctionDocString = ` -**DEPRECATED**: Use ` + "`capabilities.get`" + ` instead. - Returns the capability at the given private or public path. ` @@ -537,8 +531,6 @@ var AuthAccountTypeGetLinkTargetFunctionType = &FunctionType{ } const AuthAccountTypeGetLinkTargetFunctionDocString = ` -**DEPRECATED**: Use ` + "`capabilities.storage.getController`" + ` and ` + "`StorageCapabilityController.target()`" + `. - Returns the target path of the capability at the given public or private path, or nil if there exists no capability at the given path. ` @@ -559,8 +551,6 @@ var AuthAccountTypeUnlinkFunctionType = &FunctionType{ } const AuthAccountTypeUnlinkFunctionDocString = ` -**DEPRECATED**: Use ` + "`capabilities.unpublish`" + ` instead if the path is public. - Removes the capability at the given public or private path. ` diff --git a/runtime/sema/authaccount.go b/runtime/sema/authaccount.go index e1e880473c..9f879ec8ab 100644 --- a/runtime/sema/authaccount.go +++ b/runtime/sema/authaccount.go @@ -23,7 +23,7 @@ package sema var AuthAccountTypeLinkAccountFunctionTypePathParameterTypeAnnotation = AuthAccountTypeLinkAccountFunctionType.Parameters[0].TypeAnnotation func init() { - AuthAccountContractsTypeAddFunctionType.RequiredArgumentCount = RequiredArgumentCount(2) + AuthAccountContractsTypeAddFunctionType.Arity = &Arity{Min: 2} AuthAccountTypeGetCapabilityFunctionTypeParameterT.Optional = true PublicAccountTypeGetCapabilityFunctionTypeParameterT.Optional = true } diff --git a/runtime/sema/check_composite_declaration.go b/runtime/sema/check_composite_declaration.go index 18eefc0dad..f7c8091ed9 100644 --- a/runtime/sema/check_composite_declaration.go +++ b/runtime/sema/check_composite_declaration.go @@ -738,11 +738,14 @@ func (checker *Checker) declareCompositeLikeMembersAndValue( } if _, ok := inheritedMembers.Get(memberName); ok { + errorRange := ast.NewRangeFromPositioned(checker.memoryGauge, declaration.DeclarationIdentifier()) + if member.HasImplementation { checker.report( &MultipleInterfaceDefaultImplementationsError{ CompositeType: nestedCompositeType, Member: member, + Range: errorRange, }, ) } else { @@ -750,6 +753,7 @@ func (checker *Checker) declareCompositeLikeMembersAndValue( &DefaultFunctionConflictError{ CompositeType: nestedCompositeType, Member: member, + Range: errorRange, }, ) } @@ -1243,11 +1247,13 @@ func (checker *Checker) checkCompositeLikeConformance( if interfaceMember.DeclarationKind == common.DeclarationKindFunction { if _, ok := inheritedMembers[name]; ok { + errorRange := ast.NewRangeFromPositioned(checker.memoryGauge, compositeDeclaration.DeclarationIdentifier()) if interfaceMember.HasImplementation { checker.report( &MultipleInterfaceDefaultImplementationsError{ CompositeType: compositeType, Member: interfaceMember, + Range: errorRange, }, ) } else { @@ -1255,6 +1261,7 @@ func (checker *Checker) checkCompositeLikeConformance( &DefaultFunctionConflictError{ CompositeType: compositeType, Member: interfaceMember, + Range: errorRange, }, ) } diff --git a/runtime/sema/check_invocation_expression.go b/runtime/sema/check_invocation_expression.go index aee6b6652e..a1ffe69b42 100644 --- a/runtime/sema/check_invocation_expression.go +++ b/runtime/sema/check_invocation_expression.go @@ -374,7 +374,7 @@ func (checker *Checker) checkInvocation( returnType Type, ) { parameterCount := len(functionType.Parameters) - requiredArgumentCount := functionType.RequiredArgumentCount + arity := functionType.Arity typeParameterCount := len(functionType.TypeParameters) // Check the type arguments and bind them to type parameters @@ -421,7 +421,7 @@ func (checker *Checker) checkInvocation( checker.checkInvocationArgumentCount( argumentCount, parameterCount, - requiredArgumentCount, + arity, invocationExpression, ) @@ -592,23 +592,28 @@ func (checker *Checker) checkInvocationRequiredArgument( func (checker *Checker) checkInvocationArgumentCount( argumentCount int, parameterCount int, - requiredArgumentCount *int, + arity *Arity, pos ast.HasPosition, ) { - - if argumentCount == parameterCount { + minCount := arity.MinCount(parameterCount) + if argumentCount < minCount { + checker.report( + &InsufficientArgumentsError{ + MinCount: minCount, + ActualCount: argumentCount, + Range: ast.NewRangeFromPositioned(checker.memoryGauge, pos), + }, + ) return } - // TODO: improve - if requiredArgumentCount == nil || - argumentCount < *requiredArgumentCount { - + maxCount := arity.MaxCount(parameterCount) + if maxCount != nil && argumentCount > *maxCount { checker.report( - &ArgumentCountError{ - ParameterCount: parameterCount, - ArgumentCount: argumentCount, - Range: ast.NewRangeFromPositioned(checker.memoryGauge, pos), + &ExcessiveArgumentsError{ + MaxCount: *maxCount, + ActualCount: argumentCount, + Range: ast.NewRangeFromPositioned(checker.memoryGauge, pos), }, ) } diff --git a/runtime/sema/check_reference_expression.go b/runtime/sema/check_reference_expression.go index 36c6e1e4bc..68d8c20e72 100644 --- a/runtime/sema/check_reference_expression.go +++ b/runtime/sema/check_reference_expression.go @@ -28,40 +28,47 @@ func (checker *Checker) VisitReferenceExpression(referenceExpression *ast.Refere // Check the result type and ensure it is a reference type - resultType := checker.ConvertType(referenceExpression.Type) - checker.checkInvalidInterfaceAsType(resultType, referenceExpression.Type) + rightType := checker.ConvertType(referenceExpression.Type) + checker.checkInvalidInterfaceAsType(rightType, referenceExpression.Type) + var isOpt bool var referenceType *ReferenceType - var targetType, returnType Type + var expectedLeftType Type + var returnType Type + + if !rightType.IsInvalidType() { - if !resultType.IsInvalidType() { - var ok bool // Reference expressions may reference a value which has an optional type. // For example, the result of indexing into a dictionary is an optional: // // let ints: {Int: String} = {0: "zero"} // let ref: &T? = &ints[0] as &T? // read as (&T)? // + // In this case the reference expression's borrow type must be an optional type. + // // In this case the reference expression's type is an optional type. // Unwrap it one level to get the actual reference type - optType, optOk := resultType.(*OptionalType) - if optOk { - resultType = optType.Type + + var optType *OptionalType + optType, isOpt = rightType.(*OptionalType) + if isOpt { + rightType = optType.Type } - referenceType, ok = resultType.(*ReferenceType) - if !ok { + var isRef bool + referenceType, isRef = rightType.(*ReferenceType) + if !isRef { checker.report( &NonReferenceTypeReferenceError{ - ActualType: resultType, + ActualType: rightType, Range: ast.NewRangeFromPositioned(checker.memoryGauge, referenceExpression.Type), }, ) } else { - targetType = referenceType.Type + expectedLeftType = referenceType.Type returnType = referenceType - if optOk { - targetType = &OptionalType{Type: targetType} + if isOpt { + expectedLeftType = &OptionalType{Type: expectedLeftType} returnType = &OptionalType{Type: returnType} } } @@ -71,7 +78,31 @@ func (checker *Checker) VisitReferenceExpression(referenceExpression *ast.Refere referencedExpression := referenceExpression.Expression - referencedType := checker.VisitExpression(referencedExpression, targetType) + beforeErrors := len(checker.errors) + + referencedType, actualType := checker.visitExpression(referencedExpression, expectedLeftType) + + hasErrors := len(checker.errors) > beforeErrors + if !hasErrors { + // If the reference type was an optional type, + // we proposed an optional type to the referenced expression. + // + // Check that it actually has an optional type + + // If the reference type was a non-optional type, + // check that the referenced expression does not have an optional type + + // Do not report an error if the `expectedLeftType` is unknown + + if _, ok := actualType.(*OptionalType); ok != isOpt && expectedLeftType != nil { + checker.report(&TypeMismatchError{ + ExpectedType: expectedLeftType, + ActualType: actualType, + Expression: referencedExpression, + Range: checker.expressionRange(referenceExpression), + }) + } + } if referenceType == nil { return InvalidType diff --git a/runtime/sema/check_return_statement.go b/runtime/sema/check_return_statement.go index f3b38249c4..77c9e1a370 100644 --- a/runtime/sema/check_return_statement.go +++ b/runtime/sema/check_return_statement.go @@ -25,8 +25,13 @@ func (checker *Checker) VisitReturnStatement(statement *ast.ReturnStatement) (_ defer func() { // NOTE: check for resource loss before declaring the function - // as having definitely returned - checker.checkResourceLossForFunction() + // as having definitely returned. + // + // Check all variables declared *inside* of the function. + // The function activation's value activation depth is where the *function* is declared ("parent scope"), + // and two value activation scopes are defined for the function itself: for the parameters and the body. + + checker.checkResourceLoss(functionActivation.ValueActivationDepth + 1) functionActivation.ReturnInfo.MaybeReturned = true functionActivation.ReturnInfo.DefinitelyReturned = true }() @@ -73,9 +78,3 @@ func (checker *Checker) VisitReturnStatement(statement *ast.ReturnStatement) (_ return } - -func (checker *Checker) checkResourceLossForFunction() { - functionValueActivationDepth := - checker.functionActivations.Current().ValueActivationDepth - checker.checkResourceLoss(functionValueActivationDepth) -} diff --git a/runtime/sema/errors.go b/runtime/sema/errors.go index 9012a60450..958ab6009f 100644 --- a/runtime/sema/errors.go +++ b/runtime/sema/errors.go @@ -76,6 +76,23 @@ func (e *unsupportedOperation) Error() string { ) } +// SuggestedFix + +type HasSuggestedFixes interface { + SuggestFixes(code string) []SuggestedFix +} + +type SuggestedFix struct { + Message string + TextEdits []TextEdit +} + +type TextEdit struct { + Replacement string + Insertion string + ast.Range +} + // InvalidPragmaError type InvalidPragmaError struct { @@ -411,31 +428,59 @@ func (e *NotCallableError) Error() string { ) } -// ArgumentCountError +// InsufficientArgumentsError -type ArgumentCountError struct { - ParameterCount int - ArgumentCount int +type InsufficientArgumentsError struct { + MinCount int + ActualCount int ast.Range } -var _ SemanticError = &ArgumentCountError{} -var _ errors.UserError = &ArgumentCountError{} -var _ errors.SecondaryError = &ArgumentCountError{} +var _ SemanticError = &InsufficientArgumentsError{} +var _ errors.UserError = &InsufficientArgumentsError{} +var _ errors.SecondaryError = &InsufficientArgumentsError{} -func (*ArgumentCountError) isSemanticError() {} +func (*InsufficientArgumentsError) isSemanticError() {} -func (*ArgumentCountError) IsUserError() {} +func (*InsufficientArgumentsError) IsUserError() {} -func (e *ArgumentCountError) Error() string { - return "incorrect number of arguments" +func (e *InsufficientArgumentsError) Error() string { + return "too few arguments" } -func (e *ArgumentCountError) SecondaryError() string { +func (e *InsufficientArgumentsError) SecondaryError() string { return fmt.Sprintf( - "expected %d, got %d", - e.ParameterCount, - e.ArgumentCount, + "expected at least %d, got %d", + e.MinCount, + e.ActualCount, + ) +} + +// ExcessiveArgumentsError + +type ExcessiveArgumentsError struct { + MaxCount int + ActualCount int + ast.Range +} + +var _ SemanticError = &ExcessiveArgumentsError{} +var _ errors.UserError = &ExcessiveArgumentsError{} +var _ errors.SecondaryError = &ExcessiveArgumentsError{} + +func (*ExcessiveArgumentsError) isSemanticError() {} + +func (*ExcessiveArgumentsError) IsUserError() {} + +func (e *ExcessiveArgumentsError) Error() string { + return "too many arguments" +} + +func (e *ExcessiveArgumentsError) SecondaryError() string { + return fmt.Sprintf( + "expected up to %d, got %d", + e.MaxCount, + e.ActualCount, ) } @@ -450,6 +495,7 @@ type MissingArgumentLabelError struct { var _ SemanticError = &MissingArgumentLabelError{} var _ errors.UserError = &MissingArgumentLabelError{} +var _ HasSuggestedFixes = &MissingArgumentLabelError{} func (*MissingArgumentLabelError) isSemanticError() {} @@ -462,6 +508,23 @@ func (e *MissingArgumentLabelError) Error() string { ) } +func (e *MissingArgumentLabelError) SuggestFixes(_ string) []SuggestedFix { + return []SuggestedFix{ + { + Message: "insert argument label", + TextEdits: []TextEdit{ + { + Insertion: fmt.Sprintf("%s: ", e.ExpectedArgumentLabel), + Range: ast.NewUnmeteredRange( + e.StartPos, + e.StartPos, + ), + }, + }, + }, + } +} + // IncorrectArgumentLabelError type IncorrectArgumentLabelError struct { @@ -473,6 +536,7 @@ type IncorrectArgumentLabelError struct { var _ SemanticError = &IncorrectArgumentLabelError{} var _ errors.UserError = &IncorrectArgumentLabelError{} var _ errors.SecondaryError = &IncorrectArgumentLabelError{} +var _ HasSuggestedFixes = &IncorrectArgumentLabelError{} func (*IncorrectArgumentLabelError) isSemanticError() {} @@ -494,6 +558,50 @@ func (e *IncorrectArgumentLabelError) SecondaryError() string { ) } +func (e *IncorrectArgumentLabelError) SuggestFixes(code string) []SuggestedFix { + if len(e.ExpectedArgumentLabel) > 0 { + return []SuggestedFix{ + { + Message: "replace argument label", + TextEdits: []TextEdit{ + { + Replacement: fmt.Sprintf("%s:", e.ExpectedArgumentLabel), + Range: e.Range, + }, + }, + }, + } + } else { + endPos := e.Range.EndPos + + var whitespaceSuffixLength int + for offset := endPos.Offset + 1; offset < len(code); offset++ { + if code[offset] == ' ' { + whitespaceSuffixLength++ + } else { + break + } + } + + adjustedEndPos := endPos.Shifted(nil, whitespaceSuffixLength) + + return []SuggestedFix{ + { + Message: "remove argument label", + TextEdits: []TextEdit{ + { + Replacement: "", + Range: ast.Range{ + StartPos: e.Range.StartPos, + EndPos: adjustedEndPos, + }, + }, + }, + }, + } + } +} + // InvalidUnaryOperandError type InvalidUnaryOperandError struct { @@ -915,6 +1023,7 @@ type NotDeclaredMemberError struct { var _ SemanticError = &NotDeclaredMemberError{} var _ errors.UserError = &NotDeclaredMemberError{} var _ errors.SecondaryError = &NotDeclaredMemberError{} +var _ HasSuggestedFixes = &NotDeclaredMemberError{} func (*NotDeclaredMemberError) isSemanticError() {} @@ -928,13 +1037,25 @@ func (e *NotDeclaredMemberError) Error() string { ) } +func (e *NotDeclaredMemberError) findOptionalMember() string { + optionalType, ok := e.Type.(*OptionalType) + if !ok { + return "" + } + + members := optionalType.Type.GetMembers() + name := e.Name + _, ok = members[name] + if !ok { + return "" + } + + return name +} + func (e *NotDeclaredMemberError) SecondaryError() string { - if optionalType, ok := e.Type.(*OptionalType); ok { - members := optionalType.Type.GetMembers() - name := e.Name - if _, ok := members[name]; ok { - return fmt.Sprintf("type is optional, consider optional-chaining: ?.%s", name) - } + if optionalMember := e.findOptionalMember(); optionalMember != "" { + return fmt.Sprintf("type is optional, consider optional-chaining: ?.%s", optionalMember) } if closestMember := e.findClosestMember(); closestMember != "" { return fmt.Sprintf("did you mean `%s`?", closestMember) @@ -942,6 +1063,30 @@ func (e *NotDeclaredMemberError) SecondaryError() string { return "unknown member" } +func (e *NotDeclaredMemberError) SuggestFixes(_ string) []SuggestedFix { + optionalMember := e.findOptionalMember() + if optionalMember == "" { + return nil + } + + accessPos := e.Expression.AccessPos + + return []SuggestedFix{ + { + Message: "use optional chaining", + TextEdits: []TextEdit{ + { + Insertion: "?", + Range: ast.Range{ + StartPos: accessPos, + EndPos: accessPos, + }, + }, + }, + }, + } +} + // findClosestMember searches the names of the members on the accessed type, // and finds the name with the smallest edit distance from the member the user // tried to access. In cases of typos, this should provide a helpful hint. @@ -1418,6 +1563,7 @@ func (e *DuplicateConformanceError) Error() string { type MultipleInterfaceDefaultImplementationsError struct { CompositeType *CompositeType Member *Member + ast.Range } var _ SemanticError = &MultipleInterfaceDefaultImplementationsError{} @@ -1436,14 +1582,6 @@ func (e *MultipleInterfaceDefaultImplementationsError) Error() string { ) } -func (e *MultipleInterfaceDefaultImplementationsError) StartPosition() ast.Position { - return e.Member.Identifier.StartPosition() -} - -func (e *MultipleInterfaceDefaultImplementationsError) EndPosition(memoryGauge common.MemoryGauge) ast.Position { - return e.Member.Identifier.EndPosition(memoryGauge) -} - // SpecialFunctionDefaultImplementationError type SpecialFunctionDefaultImplementationError struct { Container ast.Declaration @@ -1479,6 +1617,7 @@ func (e *SpecialFunctionDefaultImplementationError) EndPosition(memoryGauge comm type DefaultFunctionConflictError struct { CompositeType *CompositeType Member *Member + ast.Range } var _ SemanticError = &DefaultFunctionConflictError{} @@ -1490,21 +1629,13 @@ func (*DefaultFunctionConflictError) IsUserError() {} func (e *DefaultFunctionConflictError) Error() string { return fmt.Sprintf( - "%s `%s` has conflicting requirements for function `%s`", + "%s `%s` has conflicting requirements for function `%s` ", e.CompositeType.Kind.Name(), e.CompositeType.QualifiedString(), e.Member.Identifier.Identifier, ) } -func (e *DefaultFunctionConflictError) StartPosition() ast.Position { - return e.Member.Identifier.StartPosition() -} - -func (e *DefaultFunctionConflictError) EndPosition(memoryGauge common.MemoryGauge) ast.Position { - return e.Member.Identifier.EndPosition(memoryGauge) -} - // MissingConformanceError type MissingConformanceError struct { CompositeType *CompositeType diff --git a/runtime/sema/publicaccount.cdc b/runtime/sema/publicaccount.cdc index 4e4b8205a0..c59e023af7 100644 --- a/runtime/sema/publicaccount.cdc +++ b/runtime/sema/publicaccount.cdc @@ -28,13 +28,9 @@ pub struct PublicAccount { /// All public paths of this account. pub let publicPaths: [PublicPath] - /// **DEPRECATED**: Use `capabilities.get` instead. - /// /// Returns the capability at the given public path. pub fun getCapability(_ path: PublicPath): Capability - /// **DEPRECATED** - /// /// Returns the target path of the capability at the given public or private path, /// or nil if there exists no capability at the given path. pub fun getLinkTarget(_ path: CapabilityPath): Path? diff --git a/runtime/sema/publicaccount.gen.go b/runtime/sema/publicaccount.gen.go index fc8e2a57ad..1202be2d5c 100644 --- a/runtime/sema/publicaccount.gen.go +++ b/runtime/sema/publicaccount.gen.go @@ -129,8 +129,6 @@ var PublicAccountTypeGetCapabilityFunctionType = &FunctionType{ } const PublicAccountTypeGetCapabilityFunctionDocString = ` -**DEPRECATED**: Use ` + "`capabilities.get`" + ` instead. - Returns the capability at the given public path. ` @@ -152,8 +150,6 @@ var PublicAccountTypeGetLinkTargetFunctionType = &FunctionType{ } const PublicAccountTypeGetLinkTargetFunctionDocString = ` -**DEPRECATED** - Returns the target path of the capability at the given public or private path, or nil if there exists no capability at the given path. ` diff --git a/runtime/sema/storage_capability_controller.cdc b/runtime/sema/storage_capability_controller.cdc index 7221a7b5c9..6ebc6d8b80 100644 --- a/runtime/sema/storage_capability_controller.cdc +++ b/runtime/sema/storage_capability_controller.cdc @@ -1,5 +1,9 @@ pub struct StorageCapabilityController { + /// The capability that is controlled by this controller. + access(all) + let capability: Capability + /// An arbitrary "tag" for the controller. /// For example, it could be used to describe the purpose of the capability. /// Empty by default. diff --git a/runtime/sema/storage_capability_controller.gen.go b/runtime/sema/storage_capability_controller.gen.go index d114032758..d395512ff9 100644 --- a/runtime/sema/storage_capability_controller.gen.go +++ b/runtime/sema/storage_capability_controller.gen.go @@ -21,6 +21,14 @@ package sema import "github.com/onflow/cadence/runtime/ast" +const StorageCapabilityControllerTypeCapabilityFieldName = "capability" + +var StorageCapabilityControllerTypeCapabilityFieldType = &CapabilityType{} + +const StorageCapabilityControllerTypeCapabilityFieldDocString = ` +The capability that is controlled by this controller. +` + const StorageCapabilityControllerTypeTagFieldName = "tag" var StorageCapabilityControllerTypeTagFieldType = StringType @@ -119,6 +127,14 @@ var StorageCapabilityControllerType = &SimpleType{ func init() { StorageCapabilityControllerType.Members = func(t *SimpleType) map[string]MemberResolver { return MembersAsResolvers([]*Member{ + NewUnmeteredFieldMember( + t, + ast.AccessPublic, + ast.VariableKindConstant, + StorageCapabilityControllerTypeCapabilityFieldName, + StorageCapabilityControllerTypeCapabilityFieldType, + StorageCapabilityControllerTypeCapabilityFieldDocString, + ), NewUnmeteredFieldMember( t, ast.AccessPublicSettable, diff --git a/runtime/sema/type.go b/runtime/sema/type.go index e2746a10f0..66c9487ac2 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -1788,6 +1788,26 @@ It does not modify the original array. If either of the parameters are out of the bounds of the array, or the indices are invalid (` + "`from > upTo`" + `), then the function will fail. ` +const ArrayTypeReverseFunctionName = "reverse" + +const arrayTypeReverseFunctionDocString = ` +Returns a new array with contents in the reversed order. +Available if the array element type is not resource-kinded. +` + +const ArrayTypeFilterFunctionName = "filter" + +const arrayTypeFilterFunctionDocString = ` +Returns a new array whose elements are filtered by applying the filter function on each element of the original array. +Available if the array element type is not resource-kinded. +` + +const ArrayTypeMapFunctionName = "map" + +const arrayTypeMapFunctionDocString = ` +Returns a new array whose elements are produced by applying the mapper function on each element of the original array. +` + func getArrayMembers(arrayType ArrayType) map[string]MemberResolver { members := map[string]MemberResolver{ @@ -1881,6 +1901,81 @@ func getArrayMembers(arrayType ArrayType) map[string]MemberResolver { ) }, }, + ArrayTypeReverseFunctionName: { + Kind: common.DeclarationKindFunction, + Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member { + elementType := arrayType.ElementType(false) + + // It is impossible for a resource to be present in two arrays. + if elementType.IsResourceType() { + report( + &InvalidResourceArrayMemberError{ + Name: identifier, + DeclarationKind: common.DeclarationKindFunction, + Range: targetRange, + }, + ) + } + + return NewPublicFunctionMember( + memoryGauge, + arrayType, + identifier, + ArrayReverseFunctionType(arrayType), + arrayTypeReverseFunctionDocString, + ) + }, + }, + ArrayTypeFilterFunctionName: { + Kind: common.DeclarationKindFunction, + Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member { + + elementType := arrayType.ElementType(false) + + if elementType.IsResourceType() { + report( + &InvalidResourceArrayMemberError{ + Name: identifier, + DeclarationKind: common.DeclarationKindFunction, + Range: targetRange, + }, + ) + } + + return NewPublicFunctionMember( + memoryGauge, + arrayType, + identifier, + ArrayFilterFunctionType(memoryGauge, elementType), + arrayTypeFilterFunctionDocString, + ) + }, + }, + ArrayTypeMapFunctionName: { + Kind: common.DeclarationKindFunction, + Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member { + elementType := arrayType.ElementType(false) + + // TODO: maybe allow for resource element type as a reference. + if elementType.IsResourceType() { + report( + &InvalidResourceArrayMemberError{ + Name: identifier, + DeclarationKind: common.DeclarationKindFunction, + Range: targetRange, + }, + ) + } + + return NewPublicFunctionMember( + memoryGauge, + arrayType, + identifier, + ArrayMapFunctionType(memoryGauge, arrayType), + arrayTypeMapFunctionDocString, + ) + }, + }, } // TODO: maybe still return members but report a helpful error? @@ -2193,6 +2288,88 @@ func ArraySliceFunctionType(elementType Type) *FunctionType { } } +func ArrayReverseFunctionType(arrayType ArrayType) *FunctionType { + return &FunctionType{ + Parameters: []Parameter{}, + ReturnTypeAnnotation: NewTypeAnnotation(arrayType), + } +} + +func ArrayFilterFunctionType(memoryGauge common.MemoryGauge, elementType Type) *FunctionType { + // fun filter(_ function: ((T): Bool)): [T] + // funcType: elementType -> Bool + funcType := &FunctionType{ + Parameters: []Parameter{ + { + Identifier: "element", + TypeAnnotation: NewTypeAnnotation(elementType), + }, + }, + ReturnTypeAnnotation: NewTypeAnnotation(BoolType), + } + + return &FunctionType{ + Parameters: []Parameter{ + { + Label: ArgumentLabelNotRequired, + Identifier: "f", + TypeAnnotation: NewTypeAnnotation(funcType), + }, + }, + ReturnTypeAnnotation: NewTypeAnnotation(NewVariableSizedType(memoryGauge, elementType)), + } +} + +func ArrayMapFunctionType(memoryGauge common.MemoryGauge, arrayType ArrayType) *FunctionType { + // For [T] or [T; N] + // fun map(_ function: ((T): U)): [U] + // or + // fun map(_ function: ((T): U)): [U; N] + + typeParameter := &TypeParameter{ + Name: "U", + } + + typeU := &GenericType{ + TypeParameter: typeParameter, + } + + var returnArrayType Type + switch arrayType := arrayType.(type) { + case *VariableSizedType: + returnArrayType = NewVariableSizedType(memoryGauge, typeU) + case *ConstantSizedType: + returnArrayType = NewConstantSizedType(memoryGauge, typeU, arrayType.Size) + default: + panic(errors.NewUnreachableError()) + } + + // transformFuncType: elementType -> U + transformFuncType := &FunctionType{ + Parameters: []Parameter{ + { + Identifier: "element", + TypeAnnotation: NewTypeAnnotation(arrayType.ElementType(false)), + }, + }, + ReturnTypeAnnotation: NewTypeAnnotation(typeU), + } + + return &FunctionType{ + TypeParameters: []*TypeParameter{ + typeParameter, + }, + Parameters: []Parameter{ + { + Label: ArgumentLabelNotRequired, + Identifier: "transform", + TypeAnnotation: NewTypeAnnotation(transformFuncType), + }, + }, + ReturnTypeAnnotation: NewTypeAnnotation(returnArrayType), + } +} + // VariableSizedType is a variable sized array type type VariableSizedType struct { Type Type @@ -2655,10 +2832,38 @@ func formatFunctionType( return builder.String() } +// Arity + +type Arity struct { + Min int + Max int +} + +func (arity *Arity) MinCount(parameterCount int) int { + minCount := parameterCount + if arity != nil { + minCount = arity.Min + } + + return minCount +} + +func (arity *Arity) MaxCount(parameterCount int) *int { + maxCount := parameterCount + if arity != nil { + if arity.Max < parameterCount { + return nil + } + maxCount = arity.Max + } + + return &maxCount +} + // FunctionType type FunctionType struct { ReturnTypeAnnotation TypeAnnotation - RequiredArgumentCount *int + Arity *Arity ArgumentExpressionsCheck ArgumentExpressionsCheck Members *StringMemberOrderedMap TypeParameters []*TypeParameter @@ -2670,10 +2875,6 @@ type FunctionType struct { var _ Type = &FunctionType{} -func RequiredArgumentCount(count int) *int { - return &count -} - func (*FunctionType) IsType() {} func (t *FunctionType) Tag() TypeTag { @@ -2994,10 +3195,10 @@ func (t *FunctionType) RewriteWithRestrictedTypes() (Type, bool) { } return &FunctionType{ - TypeParameters: rewrittenTypeParameters, - Parameters: rewrittenParameters, - ReturnTypeAnnotation: NewTypeAnnotation(rewrittenReturnType), - RequiredArgumentCount: t.RequiredArgumentCount, + TypeParameters: rewrittenTypeParameters, + Parameters: rewrittenParameters, + ReturnTypeAnnotation: NewTypeAnnotation(rewrittenReturnType), + Arity: t.Arity, }, true } else { return t, false @@ -3106,9 +3307,9 @@ func (t *FunctionType) Resolve(typeArguments *TypeParameterTypeOrderedMap) Type } return &FunctionType{ - Parameters: newParameters, - ReturnTypeAnnotation: NewTypeAnnotation(newReturnType), - RequiredArgumentCount: t.RequiredArgumentCount, + Parameters: newParameters, + ReturnTypeAnnotation: NewTypeAnnotation(newReturnType), + Arity: t.Arity, } } diff --git a/runtime/sema/variable_activations.go b/runtime/sema/variable_activations.go index 94a6697ec0..2a83dd0984 100644 --- a/runtime/sema/variable_activations.go +++ b/runtime/sema/variable_activations.go @@ -253,7 +253,11 @@ func (a *VariableActivations) Find(name string) *Variable { // Depth returns the depth (size) of the activation stack. func (a *VariableActivations) Depth() int { - return len(a.activations) + current := a.Current() + if current == nil { + return 0 + } + return current.Depth } type variableDeclaration struct { diff --git a/runtime/stdlib/account.go b/runtime/stdlib/account.go index 9fde20d5bc..b97bcdd2a2 100644 --- a/runtime/stdlib/account.go +++ b/runtime/stdlib/account.go @@ -128,7 +128,7 @@ func NewAuthAccountConstructor(creator AccountCreator) StandardLibraryValue { address, err = creator.CreateAccount(payerAddress) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return @@ -345,7 +345,7 @@ func newAccountBalanceGetFunction( balance, err = provider.GetAccountBalance(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return @@ -374,7 +374,7 @@ func newAccountAvailableBalanceGetFunction( balance, err = provider.GetAccountAvailableBalance(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return @@ -413,7 +413,7 @@ func newStorageUsedGetFunction( capacity, err = provider.GetStorageUsed(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return capacity }, @@ -452,7 +452,7 @@ func newStorageCapacityGetFunction( capacity, err = provider.GetStorageCapacity(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return capacity }, @@ -498,7 +498,7 @@ func newAddPublicKeyFunction( err = handler.AddEncodedAccountKey(address, publicKey) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } handler.EmitEvent( @@ -546,7 +546,7 @@ func newRemovePublicKeyFunction( publicKey, err = handler.RevokeEncodedAccountKey(address, index.ToInt(invocation.LocationRange)) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } inter := invocation.Interpreter @@ -620,7 +620,7 @@ func newAccountKeysAddFunction( accountKey, err = handler.AddAccountKey(address, publicKey, hashAlgo, weight) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } handler.EmitEvent( @@ -691,7 +691,7 @@ func newAccountKeysGetFunction( }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } // Here it is expected the host function to return a nil key, if a key is not found at the given index. @@ -774,7 +774,7 @@ func newAccountKeysForEachFunction( }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } var accountKey *AccountKey @@ -784,7 +784,7 @@ func newAccountKeysForEachFunction( accountKey, err = provider.GetAccountKey(address, int(index)) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } // Here it is expected the host function to return a nil key, if a key is not found at the given index. @@ -838,7 +838,7 @@ func newAccountKeysCountGetter( if err != nil { // The provider might not be able to fetch the number of account keys // e.g. when the account does not exist - panic(err) + panic(interpreter.WrappedExternalError(err)) } return count @@ -882,7 +882,7 @@ func newAccountKeysRevokeFunction( accountKey, err = handler.RevokeAccountKey(address, index) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } // Here it is expected the host function to return a nil key, if a key is not found at the given index. @@ -1031,6 +1031,7 @@ func newAuthAccountInboxPublishFunction( atree.Address(provider), true, nil, + nil, ) storageMapKey := interpreter.StringStorageMapKey(nameValue.Str) @@ -1097,6 +1098,7 @@ func newAuthAccountInboxUnpublishFunction( atree.Address{}, true, nil, + nil, ) inter.WriteStored( @@ -1182,6 +1184,7 @@ func newAuthAccountInboxClaimFunction( atree.Address{}, true, nil, + nil, ) inter.WriteStored( @@ -1247,7 +1250,7 @@ func newAccountContractsGetNamesFunction( names, err = provider.GetAccountContractNames(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } values := make([]interpreter.Value, len(names)) @@ -1312,7 +1315,7 @@ func newAccountContractsGetFunction( code, err = provider.GetAccountContractCode(location) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } if len(code) > 0 { @@ -1378,7 +1381,7 @@ func newAccountContractsBorrowFunction( code, err = handler.GetAccountContractCode(location) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } if len(code) == 0 { return interpreter.Nil @@ -1818,7 +1821,7 @@ func updateAccountContractCode( err = handler.UpdateAccountContractCode(location, code) }) if err != nil { - return err + return interpreter.WrappedExternalError(err) } if createContract { @@ -1975,7 +1978,7 @@ func newAuthAccountContractsRemoveFunction( code, err = handler.GetAccountContractCode(location) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } // Only remove the contract code, remove the contract value, and emit an event, @@ -2003,7 +2006,7 @@ func newAuthAccountContractsRemoveFunction( err = handler.RemoveAccountContractCode(location) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } // NOTE: the contract recording function delays the write @@ -2531,7 +2534,7 @@ func issueStorageCapabilityController( capabilityID, err = idGenerator.GenerateAccountID(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } if capabilityID == 0 { panic(errors.NewUnexpectedError("invalid zero account ID")) @@ -2613,7 +2616,7 @@ func issueAccountCapabilityController( capabilityID, err = idGenerator.GenerateAccountID(address) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } if capabilityID == 0 { panic(errors.NewUnexpectedError("invalid zero account ID")) @@ -2714,10 +2717,15 @@ func getCapabilityController( // Inject functions switch controller := controller.(type) { case *interpreter.StorageCapabilityControllerValue: + capabilityID := controller.CapabilityID + + controller.GetCapability = + newCapabilityControllerGetCapabilityFunction(inter, address, controller) + controller.GetTag = - newCapabilityControllerGetTagFunction(inter, address, controller.CapabilityID) + newCapabilityControllerGetTagFunction(inter, address, capabilityID) controller.SetTag = - newCapabilityControllerSetTagFunction(inter, address, controller.CapabilityID) + newCapabilityControllerSetTagFunction(inter, address, capabilityID) controller.TargetFunction = newStorageCapabilityControllerTargetFunction(inter, controller) @@ -2727,10 +2735,15 @@ func getCapabilityController( newStorageCapabilityControllerDeleteFunction(inter, address, controller) case *interpreter.AccountCapabilityControllerValue: + capabilityID := controller.CapabilityID + + controller.GetCapability = + newCapabilityControllerGetCapabilityFunction(inter, address, controller) + controller.GetTag = - newCapabilityControllerGetTagFunction(inter, address, controller.CapabilityID) + newCapabilityControllerGetTagFunction(inter, address, capabilityID) controller.SetTag = - newCapabilityControllerSetTagFunction(inter, address, controller.CapabilityID) + newCapabilityControllerSetTagFunction(inter, address, capabilityID) controller.DeleteFunction = newAccountCapabilityControllerDeleteFunction(inter, address, controller) @@ -3188,6 +3201,7 @@ func newAuthAccountCapabilitiesPublishFunction( atree.Address(address), true, nil, + nil, ).(*interpreter.IDCapabilityValue) if !ok { panic(errors.NewUnreachableError()) @@ -3257,6 +3271,7 @@ func newAuthAccountCapabilitiesUnpublishFunction( atree.Address{}, true, nil, + nil, ).(*interpreter.IDCapabilityValue) if !ok { panic(errors.NewUnreachableError()) @@ -3403,6 +3418,7 @@ func newAuthAccountCapabilitiesMigrateLinkFunction( atree.Address(address), true, nil, + nil, ).(*interpreter.IDCapabilityValue) if !ok { panic(errors.NewUnreachableError()) @@ -3999,6 +4015,26 @@ func getCapabilityControllerTag( return stringValue } +func newCapabilityControllerGetCapabilityFunction( + inter *interpreter.Interpreter, + address common.Address, + controller interpreter.CapabilityControllerValue, +) func() *interpreter.IDCapabilityValue { + + addressValue := interpreter.AddressValue(address) + capabilityID := controller.ControllerCapabilityID() + borrowType := controller.CapabilityControllerBorrowType() + + return func() *interpreter.IDCapabilityValue { + return interpreter.NewIDCapabilityValue( + inter, + capabilityID, + addressValue, + borrowType, + ) + } +} + func newCapabilityControllerGetTagFunction( inter *interpreter.Interpreter, address common.Address, diff --git a/runtime/stdlib/assert.go b/runtime/stdlib/assert.go index 9b6c73ba0f..7fc5da6456 100644 --- a/runtime/stdlib/assert.go +++ b/runtime/stdlib/assert.go @@ -50,7 +50,8 @@ var assertFunctionType = &sema.FunctionType{ ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), - RequiredArgumentCount: sema.RequiredArgumentCount(1), + // `message` parameter is optional + Arity: &sema.Arity{Min: 1, Max: 2}, } var AssertFunction = NewStandardLibraryFunction( diff --git a/runtime/stdlib/block.go b/runtime/stdlib/block.go index 19c9a5cab6..c2d77ef022 100644 --- a/runtime/stdlib/block.go +++ b/runtime/stdlib/block.go @@ -180,7 +180,7 @@ func getBlockAtHeight( block, exists, err = provider.GetBlockAtHeight(height) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return block, exists @@ -205,7 +205,7 @@ func NewGetCurrentBlockFunction(provider CurrentBlockProvider) StandardLibraryVa height, err = provider.GetCurrentBlockHeight() }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } block, exists := getBlockAtHeight( diff --git a/runtime/stdlib/builtin_test.go b/runtime/stdlib/builtin_test.go index 6e1a7741b9..d0efd6c0a0 100644 --- a/runtime/stdlib/builtin_test.go +++ b/runtime/stdlib/builtin_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/onflow/cadence/runtime/activations" + "github.com/onflow/cadence/runtime/tests/checker" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -86,10 +87,81 @@ func newInterpreter(t *testing.T, code string, valueDeclarations ...StandardLibr return inter } -func TestAssert(t *testing.T) { +func TestCheckAssert(t *testing.T) { t.Parallel() + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(AssertFunction) + + parseAndCheck := func(t *testing.T, code string) (*sema.Checker, error) { + return checker.ParseAndCheckWithOptions(t, + code, + checker.ParseAndCheckOptions{ + Config: &sema.Config{ + BaseValueActivation: baseValueActivation, + }, + }, + ) + } + + t.Run("too few arguments", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert()`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.InsufficientArgumentsError{}) + }) + + t.Run("invalid first argument", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(1)`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.TypeMismatchError{}) + }) + + t.Run("no message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(true)`) + + require.NoError(t, err) + }) + + t.Run("with message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(true, message: "foo")`) + + require.NoError(t, err) + }) + + t.Run("invalid message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(true, message: 1)`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.TypeMismatchError{}) + }) + + t.Run("missing argument label for message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(true, "")`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.MissingArgumentLabelError{}) + }) + + t.Run("too many arguments", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = assert(true, message: "foo", true)`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.ExcessiveArgumentsError{}) + }) +} + +func TestInterpretAssert(t *testing.T) { + inter := newInterpreter(t, `pub let test = assert`, AssertFunction, @@ -131,7 +203,58 @@ func TestAssert(t *testing.T) { assert.NoError(t, err) } -func TestPanic(t *testing.T) { +func TestCheckPanic(t *testing.T) { + + t.Parallel() + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(PanicFunction) + + parseAndCheck := func(t *testing.T, code string) (*sema.Checker, error) { + return checker.ParseAndCheckWithOptions(t, + code, + checker.ParseAndCheckOptions{ + Config: &sema.Config{ + BaseValueActivation: baseValueActivation, + }, + }, + ) + } + + t.Run("too few arguments", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = panic()`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.InsufficientArgumentsError{}) + }) + + t.Run("message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = panic("test")`) + + require.NoError(t, err) + + }) + + t.Run("invalid message", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = panic(true)`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.TypeMismatchError{}) + }) + + t.Run("too many arguments", func(t *testing.T) { + + _, err := parseAndCheck(t, `let _ = panic("test", 1)`) + + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, errs[0], &sema.ExcessiveArgumentsError{}) + }) +} + +func TestInterpretPanic(t *testing.T) { t.Parallel() diff --git a/runtime/stdlib/contracts/test.cdc b/runtime/stdlib/contracts/test.cdc index d8ec4381d2..10dc61151d 100644 --- a/runtime/stdlib/contracts/test.cdc +++ b/runtime/stdlib/contracts/test.cdc @@ -122,10 +122,17 @@ pub contract Test { return self.backend.events(type) } - /// Resets the state of the blockchain. + /// Resets the state of the blockchain to the given height. /// - pub fun reset() { - self.backend.reset() + pub fun reset(to height: UInt64) { + self.backend.reset(to: height) + } + + /// Moves the time of the blockchain by the given delta, + /// which should be passed in the form of seconds. + /// + pub fun moveTime(by delta: Fix64) { + self.backend.moveTime(by: delta) } } @@ -168,9 +175,13 @@ pub contract Test { /// operations, such as transactions and scripts. /// pub struct interface Result { - /// The resulted status of an executed operation. + /// The result status of an executed operation. /// pub let status: ResultStatus + + /// The optional error of an executed operation. + /// + pub let error: Error? } /// The result of a transaction execution. @@ -305,9 +316,14 @@ pub contract Test { /// pub fun events(_ type: Type?): [AnyStruct] - /// Resets the state of the blockchain. + /// Resets the state of the blockchain to the given height. + /// + pub fun reset(to height: UInt64) + + /// Moves the time of the blockchain by the given delta, + /// which should be passed in the form of seconds. /// - pub fun reset() + pub fun moveTime(by delta: Fix64) } /// Returns a new matcher that negates the test of the given matcher. @@ -346,4 +362,28 @@ pub contract Test { }) } + /// Asserts that the result status of an executed operation, such as + /// a script or transaction, has failed and contains the given error + /// message. + /// + pub fun assertError(_ result: {Result}, errorMessage: String) { + pre { + result.status == ResultStatus.failed: "no error was found" + } + + var found = false + let msg = result.error!.message + let msgLength = msg.length - errorMessage.length + 1 + var i = 0 + while i < msgLength { + if msg.slice(from: i, upTo: i + errorMessage.length) == errorMessage { + found = true + break + } + i = i + 1 + } + + assert(found, message: "the error message did not contain the given sub-string") + } + } diff --git a/runtime/stdlib/hashalgorithm.go b/runtime/stdlib/hashalgorithm.go index 0e36b20b4b..74a428123f 100644 --- a/runtime/stdlib/hashalgorithm.go +++ b/runtime/stdlib/hashalgorithm.go @@ -155,7 +155,7 @@ func hash( result, err = hasher.Hash(data, tag, hashAlgorithm) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return interpreter.ByteSliceToByteArrayValue(inter, result) } diff --git a/runtime/stdlib/log.go b/runtime/stdlib/log.go index c794c2e07d..3e5a92ad2c 100644 --- a/runtime/stdlib/log.go +++ b/runtime/stdlib/log.go @@ -64,7 +64,7 @@ func NewLogFunction(logger Logger) StandardLibraryValue { err = logger.ProgramLog(message) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return interpreter.Void diff --git a/runtime/stdlib/publickey.go b/runtime/stdlib/publickey.go index 6ea9ae53d4..29d4bad749 100644 --- a/runtime/stdlib/publickey.go +++ b/runtime/stdlib/publickey.go @@ -67,6 +67,9 @@ func newPublicKeyValidationHandler(validator PublicKeyValidator) interpreter.Pub errors.WrapPanic(func() { err = validator.ValidatePublicKey(publicKey) }) + if err != nil { + err = interpreter.WrappedExternalError(err) + } return err } } @@ -290,7 +293,7 @@ func newPublicKeyVerifySignatureFunction( }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return interpreter.AsBoolValue(valid) @@ -343,7 +346,7 @@ func newPublicKeyVerifyPoPFunction( valid, err = verifier.BLSVerifyPOP(publicKey, signature) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } return interpreter.AsBoolValue(valid) }, diff --git a/runtime/stdlib/random.go b/runtime/stdlib/random.go index 7967fe28c4..558d87f023 100644 --- a/runtime/stdlib/random.go +++ b/runtime/stdlib/random.go @@ -19,6 +19,8 @@ package stdlib import ( + "encoding/binary" + "github.com/onflow/cadence/runtime/errors" "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" @@ -39,9 +41,8 @@ var unsafeRandomFunctionType = &sema.FunctionType{ } type UnsafeRandomGenerator interface { - // UnsafeRandom returns a random uint64, - // where the process of random number derivation is not cryptographically secure. - UnsafeRandom() (uint64, error) + // ReadRandom reads pseudo-random bytes into the input slice, using distributed randomness. + ReadRandom([]byte) error } func NewUnsafeRandomFunction(generator UnsafeRandomGenerator) StandardLibraryValue { @@ -53,15 +54,15 @@ func NewUnsafeRandomFunction(generator UnsafeRandomGenerator) StandardLibraryVal return interpreter.NewUInt64Value( invocation.Interpreter, func() uint64 { - var rand uint64 + var buffer [8]byte var err error errors.WrapPanic(func() { - rand, err = generator.UnsafeRandom() + err = generator.ReadRandom(buffer[:]) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } - return rand + return binary.LittleEndian.Uint64(buffer[:]) }, ) }, diff --git a/runtime/stdlib/test-framework.go b/runtime/stdlib/test-framework.go index dc1b770d15..92250afbcd 100644 --- a/runtime/stdlib/test-framework.go +++ b/runtime/stdlib/test-framework.go @@ -70,7 +70,9 @@ type TestFramework interface { eventType interpreter.StaticType, ) interpreter.Value - Reset() + Reset(uint64) + + MoveTime(int64) } type ScriptResult struct { diff --git a/runtime/stdlib/test_contract.go b/runtime/stdlib/test_contract.go index 1305225812..1513b356fa 100644 --- a/runtime/stdlib/test_contract.go +++ b/runtime/stdlib/test_contract.go @@ -75,7 +75,8 @@ var testTypeAssertFunctionType = &sema.FunctionType{ ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), - RequiredArgumentCount: sema.RequiredArgumentCount(1), + // `message` parameter is optional + Arity: &sema.Arity{Min: 1, Max: 2}, } var testTypeAssertFunction = interpreter.NewUnmeteredHostFunctionValue( @@ -132,7 +133,6 @@ var testTypeAssertEqualFunctionType = &sema.FunctionType{ ), }, }, - RequiredArgumentCount: sema.RequiredArgumentCount(2), ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), @@ -195,7 +195,8 @@ var testTypeFailFunctionType = &sema.FunctionType{ ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), - RequiredArgumentCount: sema.RequiredArgumentCount(0), + // `message` parameter is optional + Arity: &sema.Arity{Min: 0, Max: 1}, } var testTypeFailFunction = interpreter.NewUnmeteredHostFunctionValue( @@ -910,7 +911,6 @@ func newTestTypeExpectFailureFunctionType() *sema.FunctionType { ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), - RequiredArgumentCount: sema.RequiredArgumentCount(2), } } diff --git a/runtime/stdlib/test_emulatorbackend.go b/runtime/stdlib/test_emulatorbackend.go index 86e9db2038..8a03753f24 100644 --- a/runtime/stdlib/test_emulatorbackend.go +++ b/runtime/stdlib/test_emulatorbackend.go @@ -46,6 +46,7 @@ type testEmulatorBackendType struct { serviceAccountFunctionType *sema.FunctionType eventsFunctionType *sema.FunctionType resetFunctionType *sema.FunctionType + moveTimeFunctionType *sema.FunctionType } func newTestEmulatorBackendType(blockchainBackendInterfaceType *sema.InterfaceType) *testEmulatorBackendType { @@ -104,6 +105,11 @@ func newTestEmulatorBackendType(blockchainBackendInterfaceType *sema.InterfaceTy testEmulatorBackendTypeResetFunctionName, ) + moveTimeFunctionType := interfaceFunctionType( + blockchainBackendInterfaceType, + testEmulatorBackendTypeMoveTimeFunctionName, + ) + compositeType := &sema.CompositeType{ Identifier: testEmulatorBackendTypeName, Kind: common.CompositeKindStructure, @@ -180,6 +186,12 @@ func newTestEmulatorBackendType(blockchainBackendInterfaceType *sema.InterfaceTy resetFunctionType, testEmulatorBackendTypeResetFunctionDocString, ), + sema.NewUnmeteredPublicFunctionMember( + compositeType, + testEmulatorBackendTypeMoveTimeFunctionName, + moveTimeFunctionType, + testEmulatorBackendTypeMoveTimeFunctionDocString, + ), } compositeType.Members = sema.MembersAsMap(members) @@ -198,6 +210,7 @@ func newTestEmulatorBackendType(blockchainBackendInterfaceType *sema.InterfaceTy serviceAccountFunctionType: serviceAccountFunctionType, eventsFunctionType: eventsFunctionType, resetFunctionType: resetFunctionType, + moveTimeFunctionType: moveTimeFunctionType, } } @@ -666,16 +679,45 @@ func (t *testEmulatorBackendType) newEventsFunction( const testEmulatorBackendTypeResetFunctionName = "reset" const testEmulatorBackendTypeResetFunctionDocString = ` -Resets the state of the blockchain. +Resets the state of the blockchain to the given height. ` func (t *testEmulatorBackendType) newResetFunction( testFramework TestFramework, ) *interpreter.HostFunctionValue { return interpreter.NewUnmeteredHostFunctionValue( - t.eventsFunctionType, + t.resetFunctionType, + func(invocation interpreter.Invocation) interpreter.Value { + height, ok := invocation.Arguments[0].(interpreter.UInt64Value) + if !ok { + panic(errors.NewUnreachableError()) + } + testFramework.Reset(uint64(height)) + return interpreter.Void + }, + ) +} + +// 'Emulator.moveTime' function + +const testEmulatorBackendTypeMoveTimeFunctionName = "moveTime" + +const testEmulatorBackendTypeMoveTimeFunctionDocString = ` +Moves the time of the blockchain by the given delta, +which should be passed in the form of seconds. +` + +func (t *testEmulatorBackendType) newMoveTimeFunction( + testFramework TestFramework, +) *interpreter.HostFunctionValue { + return interpreter.NewUnmeteredHostFunctionValue( + t.moveTimeFunctionType, func(invocation interpreter.Invocation) interpreter.Value { - testFramework.Reset() + timeDelta, ok := invocation.Arguments[0].(interpreter.Fix64Value) + if !ok { + panic(errors.NewUnreachableError()) + } + testFramework.MoveTime(int64(timeDelta.ToInt(invocation.LocationRange))) return interpreter.Void }, ) @@ -730,6 +772,10 @@ func (t *testEmulatorBackendType) newEmulatorBackend( Name: testEmulatorBackendTypeResetFunctionName, Value: t.newResetFunction(testFramework), }, + { + Name: testEmulatorBackendTypeMoveTimeFunctionName, + Value: t.newMoveTimeFunction(testFramework), + }, } // TODO: Use SimpleCompositeValue diff --git a/runtime/stdlib/test_test.go b/runtime/stdlib/test_test.go index fd4b1f8a64..f8eeb09f52 100644 --- a/runtime/stdlib/test_test.go +++ b/runtime/stdlib/test_test.go @@ -1154,6 +1154,112 @@ func TestTestBeFailedMatcher(t *testing.T) { }) } +func TestTestAssertErrorMatcher(t *testing.T) { + + t.Parallel() + + t.Run("with ScriptResult", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testMatch() { + let result = Test.ScriptResult( + status: Test.ResultStatus.failed, + returnValue: nil, + error: Test.Error("computation exceeding limit") + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + + pub fun testNoMatch() { + let result = Test.ScriptResult( + status: Test.ResultStatus.failed, + returnValue: nil, + error: Test.Error("computation exceeding memory") + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + + pub fun testNoError() { + let result = Test.ScriptResult( + status: Test.ResultStatus.succeeded, + returnValue: 42, + error: nil + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + ` + + inter, err := newTestContractInterpreter(t, script) + require.NoError(t, err) + + _, err = inter.Invoke("testMatch") + require.NoError(t, err) + + _, err = inter.Invoke("testNoMatch") + require.Error(t, err) + assert.ErrorContains(t, err, "the error message did not contain the given sub-string") + + _, err = inter.Invoke("testNoError") + require.Error(t, err) + assert.ErrorContains(t, err, "no error was found") + }) + + t.Run("with TransactionResult", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testMatch() { + let result = Test.TransactionResult( + status: Test.ResultStatus.failed, + error: Test.Error("computation exceeding limit") + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + + pub fun testNoMatch() { + let result = Test.TransactionResult( + status: Test.ResultStatus.failed, + error: Test.Error("computation exceeding memory") + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + + pub fun testNoError() { + let result = Test.TransactionResult( + status: Test.ResultStatus.succeeded, + error: nil + ) + + Test.assertError(result, errorMessage: "exceeding limit") + } + ` + + inter, err := newTestContractInterpreter(t, script) + require.NoError(t, err) + + _, err = inter.Invoke("testMatch") + require.NoError(t, err) + + _, err = inter.Invoke("testNoMatch") + require.Error(t, err) + assert.ErrorContains(t, err, "the error message did not contain the given sub-string") + + _, err = inter.Invoke("testNoError") + require.Error(t, err) + assert.ErrorContains(t, err, "no error was found") + }) +} + func TestTestBeNilMatcher(t *testing.T) { t.Parallel() @@ -2023,6 +2129,154 @@ func TestBlockchain(t *testing.T) { assert.True(t, eventsInvoked) }) + t.Run("reset", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun test() { + let blockchain = Test.newEmulatorBlockchain() + blockchain.reset(to: 5) + } + ` + + resetInvoked := false + + testFramework := &mockedTestFramework{ + reset: func(height uint64) { + resetInvoked = true + assert.Equal(t, uint64(5), height) + }, + } + + inter, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + require.NoError(t, err) + + _, err = inter.Invoke("test") + require.NoError(t, err) + + assert.True(t, resetInvoked) + }) + + t.Run("reset with type mismatch for height", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun test() { + let blockchain = Test.newEmulatorBlockchain() + blockchain.reset(to: 5.5) + } + ` + + resetInvoked := false + + testFramework := &mockedTestFramework{ + reset: func(height uint64) { + resetInvoked = true + }, + } + + _, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + errs := checker.RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) + assert.False(t, resetInvoked) + }) + + t.Run("moveTime forward", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testMoveForward() { + let blockchain = Test.newEmulatorBlockchain() + // timeDelta is the representation of 35 days, + // in the form of seconds. + let timeDelta = Fix64(35 * 24 * 60 * 60) + blockchain.moveTime(by: timeDelta) + } + ` + + moveTimeInvoked := false + + testFramework := &mockedTestFramework{ + moveTime: func(timeDelta int64) { + moveTimeInvoked = true + assert.Equal(t, int64(3024000), timeDelta) + }, + } + + inter, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + require.NoError(t, err) + + _, err = inter.Invoke("testMoveForward") + require.NoError(t, err) + + assert.True(t, moveTimeInvoked) + }) + + t.Run("moveTime backward", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testMoveBackward() { + let blockchain = Test.newEmulatorBlockchain() + // timeDelta is the representation of 35 days, + // in the form of seconds. + let timeDelta = Fix64(35 * 24 * 60 * 60) * -1.0 + blockchain.moveTime(by: timeDelta) + } + ` + + moveTimeInvoked := false + + testFramework := &mockedTestFramework{ + moveTime: func(timeDelta int64) { + moveTimeInvoked = true + assert.Equal(t, int64(-3024000), timeDelta) + }, + } + + inter, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + require.NoError(t, err) + + _, err = inter.Invoke("testMoveBackward") + require.NoError(t, err) + + assert.True(t, moveTimeInvoked) + }) + + t.Run("moveTime with invalid time delta", func(t *testing.T) { + t.Parallel() + + const script = ` + import Test + + pub fun testMoveTime() { + let blockchain = Test.newEmulatorBlockchain() + blockchain.moveTime(by: 3000) + } + ` + + moveTimeInvoked := false + + testFramework := &mockedTestFramework{ + moveTime: func(timeDelta int64) { + moveTimeInvoked = true + }, + } + + _, err := newTestContractInterpreterWithTestFramework(t, script, testFramework) + errs := checker.RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) + assert.False(t, moveTimeInvoked) + }) + // TODO: Add more tests for the remaining functions. } @@ -2039,7 +2293,8 @@ type mockedTestFramework struct { logs func() []string serviceAccount func() (*Account, error) events func(inter *interpreter.Interpreter, eventType interpreter.StaticType) interpreter.Value - reset func() + reset func(uint64) + moveTime func(int64) } var _ TestFramework = &mockedTestFramework{} @@ -2159,10 +2414,18 @@ func (m mockedTestFramework) Events( return m.events(inter, eventType) } -func (m mockedTestFramework) Reset() { +func (m mockedTestFramework) Reset(height uint64) { if m.reset == nil { panic("'Reset' is not implemented") } - m.reset() + m.reset(height) +} + +func (m mockedTestFramework) MoveTime(timeDelta int64) { + if m.moveTime == nil { + panic("'SetTimestamp' is not implemented") + } + + m.moveTime(timeDelta) } diff --git a/runtime/storage.go b/runtime/storage.go index 53ee07c2e4..dd4618a747 100644 --- a/runtime/storage.go +++ b/runtime/storage.go @@ -102,7 +102,7 @@ func (s *Storage) GetStorageMap( data, err = s.Ledger.GetValue(key.Address[:], []byte(key.Key)) }) if err != nil { - panic(err) + panic(interpreter.WrappedExternalError(err)) } dataLength := len(data) @@ -258,7 +258,7 @@ func (s *Storage) commitNewStorageMaps() error { ) }) if err != nil { - return err + return interpreter.WrappedExternalError(err) } } diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 93f8c09883..b90f76d35e 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -3790,4 +3790,405 @@ func TestRuntimeStorageIteration(t *testing.T) { ) require.NoError(t, err) }) + + t.Run("broken impl, linked with interface", func(t *testing.T) { + + t.Parallel() + + runtime := newTestInterpreterRuntime() + address := common.MustBytesToAddress([]byte{0x1}) + accountCodes := map[common.Location][]byte{} + ledger := newTestLedger(nil, nil) + nextTransactionLocation := newTransactionLocationGenerator() + contractIsBroken := false + + deployFoo := DeploymentTransaction("Foo", []byte(` + pub contract Foo { + pub resource interface Collection {} + } + `)) + + deployBar := DeploymentTransaction("Bar", []byte(` + import Foo from 0x1 + + pub contract Bar { + pub resource CollectionImpl: Foo.Collection {} + + pub fun getCollection(): @Bar.CollectionImpl { + return <- create Bar.CollectionImpl() + } + } + `)) + + newRuntimeInterface := func() Interface { + return &testRuntimeInterface{ + storage: ledger, + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + if contractIsBroken && location.Name == "Bar" { + // Contract has a semantic error. i.e: Mismatched types at `bar` function + return []byte(` + import Foo from 0x1 + + pub contract Bar { + pub resource CollectionImpl: Foo.Collection { + pub var mismatch: Int + + init() { + self.mismatch = "hello" + } + } + }`), nil + } + + code = accountCodes[location] + return code, nil + }, + emitEvent: func(event cadence.Event) error { + return nil + }, + } + } + + // Deploy ``Foo` contract + + runtimeInterface := newRuntimeInterface() + + err := runtime.ExecuteTransaction( + Script{ + Source: deployFoo, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Deploy `Bar` contract + + err = runtime.ExecuteTransaction( + Script{ + Source: deployBar, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Store values + + runtimeInterface = newRuntimeInterface() + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(` + import Bar from 0x1 + import Foo from 0x1 + + transaction { + prepare(signer: AuthAccount) { + signer.save("Hello, World!", to: /storage/first) + signer.save(<- Bar.getCollection(), to: /storage/second) + + signer.link<&String>(/private/a, target:/storage/first) + signer.link<&AnyResource{Foo.Collection}>(/private/b, target:/storage/second) + + signer.link<&String>(/public/a, target:/storage/first) + signer.link<&AnyResource{Foo.Collection}>(/public/b, target:/storage/second) + } + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Make the `Bar` contract broken. i.e: `Bar.CollectionImpl` type is broken. + contractIsBroken = true + + runtimeInterface = newRuntimeInterface() + + // 1) Iterate through public paths + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(` + import Foo from 0x1 + + transaction { + prepare(account: AuthAccount) { + var total = 0 + account.forEachPublic(fun (path: PublicPath, type: Type): Bool { + var cap = account.getCapability<&AnyResource{Foo.Collection}>(path) + cap.check() + total = total + 1 + return true + }) + + // Total values iterated should be 1. + // The broken value must be skipped. + assert(total == 1) + } + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // 2) Iterate through private paths + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(` + import Foo from 0x1 + + transaction { + prepare(account: AuthAccount) { + var total = 0 + account.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { + var cap = account.getCapability<&AnyResource{Foo.Collection}>(path) + cap.check() + total = total + 1 + return true + }) + + // Total values iterated should be 1. + // The broken value must be skipped. + assert(total == 1) + } + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // 3) Iterate through storage paths + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(` + import Foo from 0x1 + + transaction { + prepare(account: AuthAccount) { + var total = 0 + account.forEachStored(fun (path: StoragePath, type: Type): Bool { + account.check<@AnyResource{Foo.Collection}>(from: path) + total = total + 1 + return true + }) + + // Total values iterated should be 1. + // The broken value must be skipped. + assert(total == 1) + } + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + }) + + t.Run("linked with wrong type", func(t *testing.T) { + + t.Parallel() + + test := func(brokenType bool, t *testing.T) { + + runtime := newTestInterpreterRuntime() + address := common.MustBytesToAddress([]byte{0x1}) + accountCodes := map[common.Location][]byte{} + ledger := newTestLedger(nil, nil) + nextTransactionLocation := newTransactionLocationGenerator() + contractIsBroken := false + + deployFoo := DeploymentTransaction("Foo", []byte(` + pub contract Foo { + pub resource interface Collection {} + } + `)) + + deployBar := DeploymentTransaction("Bar", []byte(` + import Foo from 0x1 + + pub contract Bar { + pub resource CollectionImpl: Foo.Collection {} + + pub fun getCollection(): @Bar.CollectionImpl { + return <- create Bar.CollectionImpl() + } + } + `)) + + newRuntimeInterface := func() Interface { + return &testRuntimeInterface{ + storage: ledger, + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + if contractIsBroken && location.Name == "Bar" { + // Contract has a semantic error. i.e: Mismatched types at `bar` function + return []byte(` + import Foo from 0x1 + + pub contract Bar { + pub resource CollectionImpl: Foo.Collection { + pub var mismatch: Int + + init() { + self.mismatch = "hello" + } + } + }`), nil + } + + code = accountCodes[location] + return code, nil + }, + emitEvent: func(event cadence.Event) error { + return nil + }, + } + } + + // Deploy ``Foo` contract + + runtimeInterface := newRuntimeInterface() + + err := runtime.ExecuteTransaction( + Script{ + Source: deployFoo, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Deploy `Bar` contract + + err = runtime.ExecuteTransaction( + Script{ + Source: deployBar, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Store values + + runtimeInterface = newRuntimeInterface() + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(` + import Bar from 0x1 + import Foo from 0x1 + + transaction { + prepare(signer: AuthAccount) { + signer.save("Hello, World!", to: /storage/first) + signer.save(<- Bar.getCollection(), to: /storage/second) + + signer.link<&String>(/private/a, target:/storage/first) + signer.link<&String>(/private/b, target:/storage/second) + } + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Make the `Bar` contract broken. i.e: `Bar.CollectionImpl` type is broken. + contractIsBroken = brokenType + + runtimeInterface = newRuntimeInterface() + + // Iterate through public paths + + // If the type is broken, iterator should only find 1 value. + // Otherwise, it should fin all values (2). + count := 2 + if brokenType { + count = 1 + } + + err = runtime.ExecuteTransaction( + Script{ + Source: []byte(fmt.Sprintf(` + import Foo from 0x1 + + transaction { + prepare(account: AuthAccount) { + var total = 0 + account.forEachPrivate(fun (path: PrivatePath, type: Type): Bool { + var cap = account.getCapability<&String>(path) + cap.check() + total = total + 1 + return true + }) + + // The broken value must be skipped. + assert(total == %d) + } + } + `, + count, + )), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + } + + t.Run("broken type in storage", func(t *testing.T) { + test(true, t) + }) + + t.Run("valid type in storage", func(t *testing.T) { + test(false, t) + }) + }) } diff --git a/runtime/tests/checker/arrays_dictionaries_test.go b/runtime/tests/checker/arrays_dictionaries_test.go index 9bcf610093..09cab5a4ca 100644 --- a/runtime/tests/checker/arrays_dictionaries_test.go +++ b/runtime/tests/checker/arrays_dictionaries_test.go @@ -963,7 +963,7 @@ func TestCheckInvalidArrayRemoveFirst(t *testing.T) { errs := RequireCheckerErrors(t, err, 1) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.ExcessiveArgumentsError{}, errs[0]) } func TestCheckInvalidArrayRemoveFirstFromConstantSized(t *testing.T) { @@ -1078,6 +1078,251 @@ func TestCheckInvalidResourceFirstIndex(t *testing.T) { assert.IsType(t, &sema.ResourceLossError{}, errs[2]) } +func TestCheckArrayReverse(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + fun test() { + let x = [1, 2, 3] + let y = x.reverse() + } + `) + + require.NoError(t, err) +} + +func TestCheckArrayReverseInvalidArgs(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + fun test() { + let x = [1, 2, 3] + let y = x.reverse(100) + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.ExcessiveArgumentsError{}, errs[0]) +} + +func TestCheckResourceArrayReverseInvalid(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + resource X {} + + fun test(): @[X] { + let xs <- [<-create X()] + let revxs <-xs.reverse() + destroy xs + return <- revxs + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.InvalidResourceArrayMemberError{}, errs[0]) +} + +func TestCheckArrayFilter(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + fun test() { + let x = [1, 2, 3] + let onlyEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + let y = x.filter(onlyEven) + } + + fun testFixedSize() { + let x : [Int; 5] = [1, 2, 3, 21, 30] + let onlyEvenInt = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + let y = x.filter(onlyEvenInt) + } + `) + + require.NoError(t, err) +} + +func TestCheckArrayFilterInvalidArgs(t *testing.T) { + + t.Parallel() + + testInvalidArgs := func(code string, expectedErrors []sema.SemanticError) { + _, err := ParseAndCheck(t, code) + + errs := RequireCheckerErrors(t, err, len(expectedErrors)) + + for i, e := range expectedErrors { + assert.IsType(t, e, errs[i]) + } + } + + testInvalidArgs(` + fun test() { + let x = [1, 2, 3] + let y = x.filter(100) + } + `, + []sema.SemanticError{ + &sema.TypeMismatchError{}, + }, + ) + + testInvalidArgs(` + fun test() { + let x = [1, 2, 3] + let onlyEvenInt16 = + fun (_ x: Int16): Bool { + return x % 2 == 0 + } + + let y = x.filter(onlyEvenInt16) + } + `, + []sema.SemanticError{ + &sema.TypeMismatchError{}, + }, + ) +} + +func TestCheckResourceArrayFilterInvalid(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + resource X {} + + fun test(): @[X] { + let xs <- [<-create X()] + let allResources = + fun (_ x: @X): Bool { + destroy x + return true + } + + let filteredXs <-xs.filter(allResources) + destroy xs + return <- filteredXs + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.InvalidResourceArrayMemberError{}, errs[0]) +} + +func TestCheckArrayMap(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + fun test() { + let x = [1, 2, 3] + let trueForEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + let y: [Bool] = x.map(trueForEven) + } + + fun testFixedSize() { + let x : [Int; 5] = [1, 2, 3, 21, 30] + let trueForEvenInt = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + let y: [Bool; 5] = x.map(trueForEvenInt) + } + `) + + require.NoError(t, err) +} + +func TestCheckArrayMapInvalidArgs(t *testing.T) { + + t.Parallel() + + testInvalidArgs := func(code string, expectedErrors []sema.SemanticError) { + _, err := ParseAndCheck(t, code) + + errs := RequireCheckerErrors(t, err, len(expectedErrors)) + + for i, e := range expectedErrors { + assert.IsType(t, e, errs[i]) + } + } + + testInvalidArgs(` + fun test() { + let x = [1, 2, 3] + let y = x.map(100) + } + `, + []sema.SemanticError{ + &sema.TypeMismatchError{}, + &sema.TypeParameterTypeInferenceError{}, // since we're not passing a function. + }, + ) + + testInvalidArgs(` + fun test() { + let x = [1, 2, 3] + let trueForEvenInt16 = + fun (_ x: Int16): Bool { + return x % 2 == 0 + } + + let y: [Bool] = x.map(trueForEvenInt16) + } + `, + []sema.SemanticError{ + &sema.TypeMismatchError{}, + }, + ) +} + +func TestCheckResourceArrayMapInvalid(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + resource X {} + + fun test(): [Bool] { + let xs <- [<-create X()] + let allResources = + fun (_ x: @X): Bool { + destroy x + return true + } + + let mappedXs: [Bool] = xs.map(allResources) + destroy xs + return mappedXs + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.InvalidResourceArrayMemberError{}, errs[0]) +} + func TestCheckArrayContains(t *testing.T) { t.Parallel() diff --git a/runtime/tests/checker/builtinfunctions_test.go b/runtime/tests/checker/builtinfunctions_test.go index bf8c135c41..12e0cb4f14 100644 --- a/runtime/tests/checker/builtinfunctions_test.go +++ b/runtime/tests/checker/builtinfunctions_test.go @@ -130,8 +130,8 @@ func TestCheckAddressFromBytes(t *testing.T) { runInvalidCase(t, "[\"abc\"]", &sema.TypeMismatchError{}) runInvalidCase(t, "1", &sema.TypeMismatchError{}) - runInvalidCase(t, "[1], [2, 3, 4]", &sema.ArgumentCountError{}) - runInvalidCase(t, "", &sema.ArgumentCountError{}) + runInvalidCase(t, "[1], [2, 3, 4]", &sema.ExcessiveArgumentsError{}) + runInvalidCase(t, "", &sema.InsufficientArgumentsError{}) runInvalidCase(t, "typo: [1]", &sema.IncorrectArgumentLabelError{}) } @@ -180,8 +180,8 @@ func TestCheckAddressFromString(t *testing.T) { runInvalidCase(t, "[1232]", &sema.TypeMismatchError{}) runInvalidCase(t, "1", &sema.TypeMismatchError{}) - runInvalidCase(t, "\"0x1\", \"0x2\"", &sema.ArgumentCountError{}) - runInvalidCase(t, "", &sema.ArgumentCountError{}) + runInvalidCase(t, "\"0x1\", \"0x2\"", &sema.ExcessiveArgumentsError{}) + runInvalidCase(t, "", &sema.InsufficientArgumentsError{}) runInvalidCase(t, "typo: \"0x1\"", &sema.IncorrectArgumentLabelError{}) } @@ -262,8 +262,8 @@ func TestCheckFromBigEndianBytes(t *testing.T) { runValidCase(t, ty, "[1, 2, 100, 4, 45, 12]") runInvalidCase(t, ty, "\"abcd\"", &sema.TypeMismatchError{}) - runInvalidCase(t, ty, "", &sema.ArgumentCountError{}) - runInvalidCase(t, ty, "[1], [2, 4]", &sema.ArgumentCountError{}) + runInvalidCase(t, ty, "", &sema.InsufficientArgumentsError{}) + runInvalidCase(t, ty, "[1], [2, 4]", &sema.ExcessiveArgumentsError{}) runInvalidCase(t, ty, "typo: [1]", &sema.IncorrectArgumentLabelError{}) } } diff --git a/runtime/tests/checker/capability_controller_test.go b/runtime/tests/checker/capability_controller_test.go index 7fd5e27b04..4b94c86c53 100644 --- a/runtime/tests/checker/capability_controller_test.go +++ b/runtime/tests/checker/capability_controller_test.go @@ -73,6 +73,7 @@ func TestCheckStorageCapabilityController(t *testing.T) { t.Parallel() _, err := parseAndCheck(t, ` + let cap: Capability = controller.capability let tag: String = controller.tag let borrowType: Type = controller.borrowType let capabilityID: UInt64 = controller.capabilityID @@ -133,6 +134,7 @@ func TestCheckAccountCapabilityController(t *testing.T) { t.Parallel() _, err := parseAndCheck(t, ` + let cap: Capability = controller.capability let tag: String = controller.tag let borrowType: Type = controller.borrowType let capabilityID: UInt64 = controller.capabilityID diff --git a/runtime/tests/checker/casting_test.go b/runtime/tests/checker/casting_test.go index 0b5ac1f9ed..043d419504 100644 --- a/runtime/tests/checker/casting_test.go +++ b/runtime/tests/checker/casting_test.go @@ -6049,8 +6049,7 @@ func TestCheckStaticCastElaboration(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) diff --git a/runtime/tests/checker/conditions_test.go b/runtime/tests/checker/conditions_test.go index a7fe05a0f3..c90e5f814d 100644 --- a/runtime/tests/checker/conditions_test.go +++ b/runtime/tests/checker/conditions_test.go @@ -145,7 +145,7 @@ func TestCheckInvalidFunctionPostConditionWithBeforeAndNoArgument(t *testing.T) errs := RequireCheckerErrors(t, err, 2) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.InsufficientArgumentsError{}, errs[0]) assert.IsType(t, &sema.TypeParameterTypeInferenceError{}, errs[1]) } diff --git a/runtime/tests/checker/function_test.go b/runtime/tests/checker/function_test.go index 659b6b0b93..4ce60c282d 100644 --- a/runtime/tests/checker/function_test.go +++ b/runtime/tests/checker/function_test.go @@ -380,10 +380,9 @@ func TestCheckInvalidResourceCapturingJustMemberAccess(t *testing.T) { let test = makeKittyIdGetter() `) - errs := RequireCheckerErrors(t, err, 2) + errs := RequireCheckerErrors(t, err, 1) assert.IsType(t, &sema.ResourceCapturingError{}, errs[0]) - assert.IsType(t, &sema.ResourceLossError{}, errs[1]) } func TestCheckInvalidFunctionWithResult(t *testing.T) { diff --git a/runtime/tests/checker/genericfunction_test.go b/runtime/tests/checker/genericfunction_test.go index 1282d8753a..326221b719 100644 --- a/runtime/tests/checker/genericfunction_test.go +++ b/runtime/tests/checker/genericfunction_test.go @@ -66,10 +66,7 @@ func TestCheckGenericFunction(t *testing.T) { variant, ), &sema.FunctionType{ - TypeParameters: nil, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -91,10 +88,7 @@ func TestCheckGenericFunction(t *testing.T) { let res = test() `, &sema.FunctionType{ - TypeParameters: nil, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -120,9 +114,7 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -148,9 +140,7 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -199,8 +189,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -249,14 +238,13 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) errs := RequireCheckerErrors(t, err, 2) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.InsufficientArgumentsError{}, errs[0]) assert.IsType(t, &sema.TypeParameterTypeInferenceError{}, errs[1]) }) @@ -288,8 +276,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -327,8 +314,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -372,8 +358,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -431,8 +416,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -459,13 +443,11 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, ReturnTypeAnnotation: sema.NewTypeAnnotation( &sema.GenericType{ TypeParameter: typeParameter, }, ), - RequiredArgumentCount: nil, }, ) @@ -491,13 +473,11 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, ReturnTypeAnnotation: sema.NewTypeAnnotation( &sema.GenericType{ TypeParameter: typeParameter, }, ), - RequiredArgumentCount: nil, }, ) @@ -556,7 +536,6 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameter: typeParameter, }, ), - RequiredArgumentCount: nil, }, ) @@ -599,9 +578,7 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -639,9 +616,7 @@ func TestCheckGenericFunction(t *testing.T) { TypeParameters: []*sema.TypeParameter{ typeParameter, }, - Parameters: nil, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -678,8 +653,7 @@ func TestCheckGenericFunction(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) @@ -757,7 +731,6 @@ func TestCheckGenericFunction(t *testing.T) { }, ), ), - RequiredArgumentCount: nil, }, ) @@ -865,7 +838,6 @@ func TestCheckGenericFunction(t *testing.T) { }, ), ), - RequiredArgumentCount: nil, }, ) @@ -905,8 +877,7 @@ func TestCheckGenericFunctionIsInvalid(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), } assert.False(t, genericFunctionType.IsInvalidType()) diff --git a/runtime/tests/checker/integer_test.go b/runtime/tests/checker/integer_test.go index c07a7b6163..6f55526aba 100644 --- a/runtime/tests/checker/integer_test.go +++ b/runtime/tests/checker/integer_test.go @@ -475,7 +475,7 @@ func TestCheckInvalidIntegerConversionFunctionWithoutArgs(t *testing.T) { errs := RequireCheckerErrors(t, err, 1) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.InsufficientArgumentsError{}, errs[0]) }) } diff --git a/runtime/tests/checker/invocation_test.go b/runtime/tests/checker/invocation_test.go index 31757f21b9..f5f6239428 100644 --- a/runtime/tests/checker/invocation_test.go +++ b/runtime/tests/checker/invocation_test.go @@ -44,7 +44,7 @@ func TestCheckInvalidFunctionCallWithTooFewArguments(t *testing.T) { errs := RequireCheckerErrors(t, err, 1) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) + assert.IsType(t, &sema.InsufficientArgumentsError{}, errs[0]) } func TestCheckFunctionCallWithArgumentLabel(t *testing.T) { @@ -172,8 +172,7 @@ func TestCheckInvalidFunctionCallWithTooManyArguments(t *testing.T) { errs := RequireCheckerErrors(t, err, 2) - assert.IsType(t, &sema.ArgumentCountError{}, errs[0]) - + assert.IsType(t, &sema.ExcessiveArgumentsError{}, errs[0]) assert.IsType(t, &sema.MissingArgumentLabelError{}, errs[1]) } @@ -319,11 +318,7 @@ func TestCheckInvocationWithOnlyVarargs(t *testing.T) { ReturnTypeAnnotation: sema.TypeAnnotation{ Type: sema.VoidType, }, - RequiredArgumentCount: func() *int { - // NOTE: important to check *all* arguments are optional - var count = 0 - return &count - }(), + Arity: &sema.Arity{Max: -1}, }, "", nil, diff --git a/runtime/tests/checker/metatype_test.go b/runtime/tests/checker/metatype_test.go index 5ad0277773..44f65b4b6d 100644 --- a/runtime/tests/checker/metatype_test.go +++ b/runtime/tests/checker/metatype_test.go @@ -134,7 +134,7 @@ func TestCheckIsInstance(t *testing.T) { code: ` let result = (1).isInstance(Type(), Type()) `, - expectedErrorType: &sema.ArgumentCountError{}, + expectedErrorType: &sema.ExcessiveArgumentsError{}, }, } @@ -209,7 +209,7 @@ func TestCheckIsSubtype(t *testing.T) { code: ` let result = Type().isSubtype() `, - expectedErrorType: &sema.ArgumentCountError{}, + expectedErrorType: &sema.InsufficientArgumentsError{}, }, { name: "isSubtype argument must be named", @@ -223,7 +223,7 @@ func TestCheckIsSubtype(t *testing.T) { code: ` let result = Type().isSubtype(of: Type(), Type()) `, - expectedErrorType: &sema.ArgumentCountError{}, + expectedErrorType: &sema.ExcessiveArgumentsError{}, }, } diff --git a/runtime/tests/checker/reference_test.go b/runtime/tests/checker/reference_test.go index 34a5555215..0c328a1a1f 100644 --- a/runtime/tests/checker/reference_test.go +++ b/runtime/tests/checker/reference_test.go @@ -1069,26 +1069,30 @@ func TestCheckReferenceExpressionOfOptional(t *testing.T) { assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) }) - t.Run("upcast to optional", func(t *testing.T) { + t.Run("optional reference to non-optional value", func(t *testing.T) { t.Parallel() - checker, err := ParseAndCheck(t, ` + _, err := ParseAndCheck(t, ` let i: Int = 1 let ref = &i as &Int? `) - require.NoError(t, err) - refValueType := RequireGlobalValue(t, checker.Elaboration, "ref") + errs := RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) + }) - assert.Equal(t, - &sema.OptionalType{ - Type: &sema.ReferenceType{ - Type: sema.IntType, - }, - }, - refValueType, - ) + t.Run("non-optional reference to optional value", func(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + let opt: Int? = 1 + let ref = &opt as &AnyStruct + `) + + errs := RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.TypeMismatchError{}, errs[0]) }) } @@ -1300,3 +1304,40 @@ func TestCheckReferenceTypeImplicitConformance(t *testing.T) { require.IsType(t, &sema.TypeMismatchError{}, errs[0]) }) } + +func TestCheckReferenceCreationWithInvalidType(t *testing.T) { + + t.Parallel() + + t.Run("invalid reference type", func(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + let foo: AnyStruct? = nil + let x = &foo as &Foo + `) + + errs := RequireCheckerErrors(t, err, 1) + + var notDeclaredError *sema.NotDeclaredError + require.ErrorAs(t, errs[0], ¬DeclaredError) + }) + + t.Run("valid non-reference type", func(t *testing.T) { + + t.Parallel() + + _, err := ParseAndCheck(t, ` + struct Foo {} + + let foo: AnyStruct? = nil + let x = &foo as Foo + `) + + errs := RequireCheckerErrors(t, err, 1) + + var nonReferenceTypeReferenceError *sema.NonReferenceTypeReferenceError + require.ErrorAs(t, errs[0], &nonReferenceTypeReferenceError) + }) +} diff --git a/runtime/tests/checker/resources_test.go b/runtime/tests/checker/resources_test.go index f67489c989..65f79780fc 100644 --- a/runtime/tests/checker/resources_test.go +++ b/runtime/tests/checker/resources_test.go @@ -3982,11 +3982,10 @@ func TestCheckInvalidResourceDictionaryKeysForeach(t *testing.T) { } `) - errs := RequireCheckerErrors(t, err, 3) + errs := RequireCheckerErrors(t, err, 2) assert.IsType(t, &sema.InvalidDictionaryKeyTypeError{}, errs[0]) assert.IsType(t, &sema.InvalidResourceDictionaryMemberError{}, errs[1]) - assert.IsType(t, &sema.ResourceLossError{}, errs[2]) } func TestCheckInvalidResourceLossAfterMoveThroughDictionaryIndexing(t *testing.T) { @@ -9303,3 +9302,59 @@ func TestCheckInvalidUnreachableResourceInvalidation(t *testing.T) { assert.IsType(t, &sema.ResourceUseAfterInvalidationError{}, errs[0]) } + +func TestCheckResourceWithFunction(t *testing.T) { + + t.Parallel() + + t.Run("without return statement", func(t *testing.T) { + t.Parallel() + + _, err := ParseAndCheck(t, ` + + fun test() { + let x: @AnyResource? <- nil + + fun () {} + + destroy x + } + `) + require.NoError(t, err) + }) + + t.Run("with return statement", func(t *testing.T) { + t.Parallel() + + _, err := ParseAndCheck(t, ` + + fun test() { + let x: @AnyResource? <- nil + + fun (): Bool { + return true + } + + destroy x + } + `) + require.NoError(t, err) + }) +} + +func TestCheckInvalidResourceDestructionInFunction(t *testing.T) { + t.Parallel() + + _, err := ParseAndCheck(t, ` + fun test() { + let x: @AnyResource? <- nil + + fun () { + destroy x + } + } + `) + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.ResourceCapturingError{}, errs[0]) +} diff --git a/runtime/tests/checker/runtimetype_test.go b/runtime/tests/checker/runtimetype_test.go index bee08077e9..a2aea9373f 100644 --- a/runtime/tests/checker/runtimetype_test.go +++ b/runtime/tests/checker/runtimetype_test.go @@ -70,14 +70,14 @@ func TestCheckOptionalTypeConstructor(t *testing.T) { code: ` let result = OptionalType(Type(), Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "too few args", code: ` let result = OptionalType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, } @@ -142,14 +142,14 @@ func TestCheckVariableSizedArrayTypeConstructor(t *testing.T) { code: ` let result = VariableSizedArrayType(Type(), Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "too few args", code: ` let result = VariableSizedArrayType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, } @@ -221,21 +221,21 @@ func TestCheckConstantSizedArrayTypeConstructor(t *testing.T) { code: ` let result = ConstantSizedArrayType(type:Type(), size: 3, 4) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "one arg", code: ` let result = ConstantSizedArrayType(type: Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "no args", code: ` let result = ConstantSizedArrayType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "second label missing", @@ -322,21 +322,21 @@ func TestCheckDictionaryTypeConstructor(t *testing.T) { code: ` let result = DictionaryType(key: Type(), value: Type(), 4) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "one arg", code: ` let result = DictionaryType(key: Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "no args", code: ` let result = DictionaryType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "first label missing", @@ -400,14 +400,14 @@ func TestCheckCompositeTypeConstructor(t *testing.T) { code: ` let result = CompositeType("", 3) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "no args", code: ` let result = CompositeType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, } @@ -457,14 +457,14 @@ func TestCheckInterfaceTypeConstructor(t *testing.T) { code: ` let result = InterfaceType("", 3) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "no args", code: ` let result = InterfaceType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, } @@ -535,21 +535,21 @@ func TestCheckFunctionTypeConstructor(t *testing.T) { code: ` let result = FunctionType(parameters: [Type(), Type()], return: Type(), 4) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "one arg", code: ` let result = FunctionType(parameters: [Type(), Type()]) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "no args", code: ` let result = FunctionType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "first label missing", @@ -628,21 +628,21 @@ func TestCheckReferenceTypeConstructor(t *testing.T) { code: ` let result = ReferenceType(authorized: true, type: Type(), Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "one arg", code: ` let result = ReferenceType(authorized: true) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "no args", code: ` let result = ReferenceType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "first label missing", @@ -731,21 +731,21 @@ func TestCheckRestrictedTypeConstructor(t *testing.T) { code: ` let result = RestrictedType(identifier: "A", restrictions: ["I1"], ["I2"]) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "one arg", code: ` let result = RestrictedType(identifier: "A") `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "no args", code: ` let result = RestrictedType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, { name: "missing first label", @@ -824,14 +824,14 @@ func TestCheckCapabilityTypeConstructor(t *testing.T) { code: ` let result = CapabilityType(Type(), Type()) `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.ExcessiveArgumentsError{}, }, { name: "too few args", code: ` let result = CapabilityType() `, - expectedError: &sema.ArgumentCountError{}, + expectedError: &sema.InsufficientArgumentsError{}, }, } diff --git a/runtime/tests/checker/type_inference_test.go b/runtime/tests/checker/type_inference_test.go index 97c0a0aa1b..af024b4f16 100644 --- a/runtime/tests/checker/type_inference_test.go +++ b/runtime/tests/checker/type_inference_test.go @@ -363,8 +363,7 @@ func TestCheckFunctionArgumentTypeInference(t *testing.T) { ), }, }, - ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), - RequiredArgumentCount: nil, + ReturnTypeAnnotation: sema.NewTypeAnnotation(sema.VoidType), }, ) diff --git a/runtime/tests/interpreter/attachments_test.go b/runtime/tests/interpreter/attachments_test.go index f4662b95bb..02da5ce876 100644 --- a/runtime/tests/interpreter/attachments_test.go +++ b/runtime/tests/interpreter/attachments_test.go @@ -21,8 +21,10 @@ package interpreter_test import ( "testing" + "github.com/onflow/cadence/runtime/activations" "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" + "github.com/onflow/cadence/runtime/stdlib" "github.com/stretchr/testify/require" @@ -1925,3 +1927,54 @@ func TestInterpretAttachmentDefensiveCheck(t *testing.T) { require.ErrorAs(t, err, &interpreter.InvalidAttachmentOperationTargetError{}) }) } + +func TestInterpretBuiltinCompositeAttachment(t *testing.T) { + + t.Parallel() + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseActivation := activations.NewActivation(nil, interpreter.BaseActivation) + for _, valueDeclaration := range []stdlib.StandardLibraryValue{ + stdlib.NewPublicKeyConstructor( + assumeValidPublicKeyValidator{}, + nil, + nil, + ), + stdlib.SignatureAlgorithmConstructor, + } { + baseValueActivation.DeclareValue(valueDeclaration) + interpreter.Declare(baseActivation, valueDeclaration) + } + + inter, err := parseCheckAndInterpretWithOptions(t, + ` + attachment A for AnyStruct { + fun foo(): Int { + return 42 + } + } + + fun main(): Int { + var key = PublicKey( + publicKey: "0102".decodeHex(), + signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 + ) + key = attach A() to key + return key[A]!.foo() + } + `, + ParseCheckAndInterpretOptions{ + CheckerConfig: &sema.Config{ + BaseValueActivation: baseValueActivation, + AttachmentsEnabled: true, + }, + Config: &interpreter.Config{ + BaseActivation: baseActivation, + }, + }, + ) + require.NoError(t, err) + + _, err = inter.Invoke("main") + require.NoError(t, err) +} diff --git a/runtime/tests/interpreter/container_mutation_test.go b/runtime/tests/interpreter/container_mutation_test.go index bd029ad954..af49b9e16e 100644 --- a/runtime/tests/interpreter/container_mutation_test.go +++ b/runtime/tests/interpreter/container_mutation_test.go @@ -954,3 +954,144 @@ func TestInterpretContainerMutationAfterNilCoalescing(t *testing.T) { result, ) } + +func TestInterpretInnerContainerMutationWhileIteratingOuter(t *testing.T) { + + t.Parallel() + + t.Run("nested array, directly mutating inner", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun test(): [String] { + let nestedArrays: [[String]] = [["foo", "bar"], ["apple", "orange"]] + for array in nestedArrays { + array[0] = "hello" + } + + return nestedArrays[0] + } + `) + + result, err := inter.Invoke("test") + require.NoError(t, err) + + // array `["foo", "bar"]` should stay unchanged, because what's mutated is a copy. + + RequireValuesEqual( + t, + inter, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeString, + }, + common.ZeroAddress, + interpreter.NewUnmeteredStringValue("foo"), + interpreter.NewUnmeteredStringValue("bar"), + ), + result, + ) + }) + + t.Run("nested array, mutating inner via outer", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun test(): [String] { + let nestedArrays: [[String]] = [["foo", "bar"], ["apple", "orange"]] + for array in nestedArrays { + nestedArrays[0][0] = "hello" + } + + return nestedArrays[0] + } + `) + + result, err := inter.Invoke("test") + require.NoError(t, err) + + RequireValuesEqual( + t, + inter, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeString, + }, + common.ZeroAddress, + interpreter.NewUnmeteredStringValue("hello"), + interpreter.NewUnmeteredStringValue("bar"), + ), + result, + ) + }) + + t.Run("dictionary inside array, mutating inner via outer", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun test(): {String: String} { + let dictionaryArray: [{String: String}] = [{"name": "foo"}, {"name": "bar"}] + for dictionary in dictionaryArray { + dictionaryArray[0]["name"] = "hello" + } + + return dictionaryArray[0] + } + `) + + result, err := inter.Invoke("test") + require.NoError(t, err) + + require.IsType(t, &interpreter.DictionaryValue{}, result) + dictionary := result.(*interpreter.DictionaryValue) + + require.Equal(t, 1, dictionary.Count()) + + val, present := dictionary.Get( + inter, + interpreter.EmptyLocationRange, + interpreter.NewUnmeteredStringValue("name"), + ) + assert.True(t, present) + assert.Equal(t, interpreter.NewUnmeteredStringValue("hello"), val) + }) + + t.Run("dictionary", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun test(): {String: String} { + let nestedDictionary: {String: {String: String}} = {"a": {"name": "foo"}, "b": {"name": "bar"}} + nestedDictionary.forEachKey(fun (key: String): Bool { + var dictionary = nestedDictionary[key]! + dictionary["name"] = "hello" + return true + }) + + return nestedDictionary["a"]! + } + `) + + result, err := inter.Invoke("test") + require.NoError(t, err) + + // dictionary `{"name": "foo"}` should stay unchanged, because what's mutated is a copy. + + require.IsType(t, &interpreter.DictionaryValue{}, result) + dictionary := result.(*interpreter.DictionaryValue) + + require.Equal(t, 1, dictionary.Count()) + + val, present := dictionary.Get( + inter, + interpreter.EmptyLocationRange, + interpreter.NewUnmeteredStringValue("name"), + ) + assert.True(t, present) + assert.Equal(t, interpreter.NewUnmeteredStringValue("foo"), val) + }) +} diff --git a/runtime/tests/interpreter/interpreter_test.go b/runtime/tests/interpreter/interpreter_test.go index 5e56e230bd..f7b3d7363b 100644 --- a/runtime/tests/interpreter/interpreter_test.go +++ b/runtime/tests/interpreter/interpreter_test.go @@ -1985,7 +1985,111 @@ func TestInterpretHostFunctionWithVariableArguments(t *testing.T) { ReturnTypeAnnotation: sema.NewTypeAnnotation( sema.VoidType, ), - RequiredArgumentCount: sema.RequiredArgumentCount(1), + Arity: &sema.Arity{Min: 1}, + }, + ``, + func(invocation interpreter.Invocation) interpreter.Value { + called = true + + require.Len(t, invocation.ArgumentTypes, 3) + assert.IsType(t, sema.IntType, invocation.ArgumentTypes[0]) + assert.IsType(t, sema.BoolType, invocation.ArgumentTypes[1]) + assert.IsType(t, sema.StringType, invocation.ArgumentTypes[2]) + + require.Len(t, invocation.Arguments, 3) + + inter := invocation.Interpreter + + AssertValuesEqual( + t, + inter, + interpreter.NewUnmeteredIntValueFromInt64(1), + invocation.Arguments[0], + ) + + AssertValuesEqual( + t, + inter, + interpreter.TrueValue, + invocation.Arguments[1], + ) + + AssertValuesEqual( + t, + inter, + interpreter.NewUnmeteredStringValue("test"), + invocation.Arguments[2], + ) + + return interpreter.Void + }, + ) + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(testFunction) + + checker, err := sema.NewChecker( + program, + TestLocation, + nil, + &sema.Config{ + BaseValueActivation: baseValueActivation, + AccessCheckMode: sema.AccessCheckModeStrict, + }, + ) + require.NoError(t, err) + + err = checker.Check() + require.NoError(t, err) + + storage := newUnmeteredInMemoryStorage() + + baseActivation := activations.NewActivation(nil, interpreter.BaseActivation) + interpreter.Declare(baseActivation, testFunction) + + inter, err := interpreter.NewInterpreter( + interpreter.ProgramFromChecker(checker), + checker.Location, + &interpreter.Config{ + Storage: storage, + BaseActivation: baseActivation, + }, + ) + require.NoError(t, err) + + err = inter.Interpret() + require.NoError(t, err) + + assert.True(t, called) +} + +func TestInterpretHostFunctionWithOptionalArguments(t *testing.T) { + + t.Parallel() + + const code = ` + pub let nothing = test(1, true, "test") + ` + program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) + + require.NoError(t, err) + + called := false + + testFunction := stdlib.NewStandardLibraryFunction( + "test", + &sema.FunctionType{ + Parameters: []sema.Parameter{ + { + Label: sema.ArgumentLabelNotRequired, + Identifier: "value", + TypeAnnotation: sema.NewTypeAnnotation(sema.IntType), + }, + }, + ReturnTypeAnnotation: sema.NewTypeAnnotation( + sema.VoidType, + ), + Arity: &sema.Arity{Min: 1, Max: 3}, }, ``, func(invocation interpreter.Invocation) interpreter.Value { @@ -5058,6 +5162,7 @@ func TestInterpretReferenceFailableDowncasting(t *testing.T) { atree.Address(storageAddress), true, nil, + nil, ) domain := storagePath.Domain.Identifier() @@ -7919,7 +8024,14 @@ func TestInterpretResourceMovingAndBorrowing(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") @@ -8682,7 +8794,7 @@ func TestInterpretNonStorageReference(t *testing.T) { <-create NFT(id: 2) ] - let nftRef = (&resources[1] as &NFT?)! + let nftRef = &resources[1] as &NFT let nftRef2 = nftRef nftRef2.id = 3 @@ -10395,142 +10507,1198 @@ func TestInterpretArrayFirstIndexDoesNotExist(t *testing.T) { ) } -func TestInterpretOptionalReference(t *testing.T) { - +func TestInterpretArrayReverse(t *testing.T) { t.Parallel() - inter := parseCheckAndInterpret(t, - ` - fun present(): &Int { - let x: Int? = 1 - let y = &x as &Int? - return y! - } + inter := parseCheckAndInterpret(t, ` + let xs = [1, 2, 3, 100, 200] + let ys = [100, 467, 297, 23] + let xs_fixed: [Int; 5] = [1, 2, 3, 100, 200] + let ys_fixed: [Int; 4] = [100, 467, 297, 23] + let emptyVals: [Int] = [] + let emptyVals_fixed: [Int; 0] = [] - fun absent(): &Int { - let x: Int? = nil - let y = &x as &Int? - return y! - } - `, - ) + fun reversexs(): [Int] { + return xs.reverse() + } + fun originalxs(): [Int] { + return xs + } - value, err := inter.Invoke("present") - require.NoError(t, err) - require.Equal( - t, - &interpreter.EphemeralReferenceValue{ - Value: interpreter.NewUnmeteredIntValueFromInt64(1), - BorrowedType: sema.IntType, - }, - value, - ) + fun reverseys(): [Int] { + return ys.reverse() + } + fun originalys(): [Int] { + return ys + } - _, err = inter.Invoke("absent") - RequireError(t, err) + fun reversexs_fixed(): [Int; 5] { + return xs_fixed.reverse() + } + fun originalxs_fixed(): [Int; 5] { + return xs_fixed + } - var forceNilError interpreter.ForceNilError - require.ErrorAs(t, err, &forceNilError) -} + fun reverseys_fixed(): [Int; 4] { + return ys_fixed.reverse() + } + fun originalys_fixed(): [Int; 4] { + return ys_fixed + } -func TestInterpretCastingBoxing(t *testing.T) { + fun reverseempty(): [Int] { + return emptyVals.reverse() + } + fun originalempty(): [Int] { + return emptyVals + } - t.Parallel() + fun reverseempty_fixed(): [Int; 0] { + return emptyVals_fixed.reverse() + } + fun originalempty_fixed(): [Int; 0] { + return emptyVals_fixed + } - t.Run("failable cast", func(t *testing.T) { + pub struct TestStruct { + pub var test: Int - t.Parallel() + init(_ t: Int) { + self.test = t + } + } - inter := parseCheckAndInterpret(t, ` - let a = (1 as? Int?!)?.getType() - `) + let sa = [TestStruct(1), TestStruct(2), TestStruct(3)] + let sa_fixed: [TestStruct; 3] = [TestStruct(1), TestStruct(2), TestStruct(3)] - variable := inter.Globals.Get("a") - require.NotNil(t, variable) + fun reversesa(): [Int] { + let sa_rev = sa.reverse() - require.Equal( - t, - interpreter.NewUnmeteredSomeValueNonCopying( - interpreter.TypeValue{ - Type: interpreter.PrimitiveStaticTypeInt, - }, - ), - variable.GetValue(), - ) - }) + let res: [Int] = []; + for s in sa_rev { + res.append(s.test) + } - t.Run("force cast", func(t *testing.T) { + return res + } + fun originalsa(): [Int] { + let res: [Int] = []; + for s in sa { + res.append(s.test) + } + + return res + } - t.Parallel() + fun reversesa_fixed(): [Int] { + let sa_rev = sa_fixed.reverse() - inter := parseCheckAndInterpret(t, ` - let a = (1 as! Int?)?.getType() - `) + let res: [Int] = []; + for s in sa_rev { + res.append(s.test) + } - variable := inter.Globals.Get("a") - require.NotNil(t, variable) + return res + } + fun originalsa_fixed(): [Int] { + let res: [Int] = []; + for s in sa_fixed { + res.append(s.test) + } + + return res + } + `) - require.Equal( + runValidCase := func(t *testing.T, reverseFuncName, originalFuncName string, reversedArray, originalArray *interpreter.ArrayValue) { + val, err := inter.Invoke(reverseFuncName) + require.NoError(t, err) + + AssertValuesEqual( t, - interpreter.NewUnmeteredSomeValueNonCopying( - interpreter.TypeValue{ - Type: interpreter.PrimitiveStaticTypeInt, - }, - ), - variable.GetValue(), + inter, + reversedArray, + val, ) - }) - - t.Run("cast", func(t *testing.T) { - - t.Parallel() - inter := parseCheckAndInterpret(t, ` - let a = (1 as Int?)?.getType() - `) - - variable := inter.Globals.Get("a") - require.NotNil(t, variable) + origVal, err := inter.Invoke(originalFuncName) + require.NoError(t, err) - require.Equal( + // Original array remains unchanged + AssertValuesEqual( t, - interpreter.NewUnmeteredSomeValueNonCopying( - interpreter.TypeValue{ - Type: interpreter.PrimitiveStaticTypeInt, - }, - ), - variable.GetValue(), + inter, + originalArray, + origVal, ) - }) -} + } -func TestInterpretNilCoalesceReference(t *testing.T) { + for _, suffix := range []string{"_fixed", ""} { + fixed := suffix == "_fixed" - t.Parallel() + var arrayType interpreter.ArrayStaticType + if fixed { + arrayType = &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + } else { + arrayType = &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + } - baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) - baseValueActivation.DeclareValue(stdlib.PanicFunction) + setFixedSize := func(size int64) { + if fixed { + constSized, ok := arrayType.(*interpreter.ConstantSizedStaticType) + assert.True(t, ok) - baseActivation := activations.NewActivation(nil, interpreter.BaseActivation) - interpreter.Declare(baseActivation, stdlib.PanicFunction) + constSized.Size = size + } + } - inter, err := parseCheckAndInterpretWithOptions(t, - ` - let xs = {"a": 2} - let ref = &xs["a"] as &Int? ?? panic("no a") - `, - ParseCheckAndInterpretOptions{ - CheckerConfig: &sema.Config{ - BaseValueActivation: baseValueActivation, - }, - Config: &interpreter.Config{ - BaseActivation: baseActivation, - }, - }, - ) - require.NoError(t, err) + setFixedSize(0) + runValidCase(t, "reverseempty"+suffix, "originalempty"+suffix, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + ), interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + )) - variable := inter.Globals.Get("ref") + setFixedSize(5) + runValidCase(t, "reversexs"+suffix, "originalxs"+suffix, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(200), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(1), + ), interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(200), + )) + + setFixedSize(4) + runValidCase(t, "reverseys"+suffix, "originalys"+suffix, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(23), + interpreter.NewUnmeteredIntValueFromInt64(297), + interpreter.NewUnmeteredIntValueFromInt64(467), + interpreter.NewUnmeteredIntValueFromInt64(100), + ), interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + arrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(467), + interpreter.NewUnmeteredIntValueFromInt64(297), + interpreter.NewUnmeteredIntValueFromInt64(23), + )) + + runValidCase(t, "reversesa"+suffix, "originalsa"+suffix, + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(1), + ), interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + )) + } +} + +func TestInterpretArrayFilter(t *testing.T) { + + runValidCase := func( + t *testing.T, + inter *interpreter.Interpreter, + filterFuncName, + originalFuncName string, + filteredArray, originalArray *interpreter.ArrayValue, + ) { + val, err := inter.Invoke(filterFuncName) + require.NoError(t, err) + + AssertValuesEqual( + t, + inter, + filteredArray, + val, + ) + + origVal, err := inter.Invoke(originalFuncName) + require.NoError(t, err) + + // Original array remains unchanged + AssertValuesEqual( + t, + inter, + originalArray, + origVal, + ) + } + + t.Run("with variable sized empty array", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let emptyVals: [Int] = [] + + let onlyEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + fun filterempty(): [Int] { + return emptyVals.filter(onlyEven) + } + fun originalempty(): [Int] { + return emptyVals + } + `) + + emptyVarSizedArray := interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + ) + + runValidCase( + t, + inter, + "filterempty", + "originalempty", + emptyVarSizedArray, + emptyVarSizedArray, + ) + }) + + t.Run("with variable sized array of integer", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let xs = [1, 2, 3, 100, 201] + + let onlyEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + fun filterxs(): [Int] { + return xs.filter(onlyEven) + } + fun originalxs(): [Int] { + return xs + } + `) + + varSizedArrayType := &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + + runValidCase( + t, + inter, + "filterxs", + "originalxs", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(100), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(201), + ), + ) + }) + + t.Run("with variable sized array of struct", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let onlyOddStruct = + fun (_ x: TestStruct): Bool { + return x.test % 2 == 1 + } + + let sa = [TestStruct(1), TestStruct(2), TestStruct(3)] + fun filtersa(): [Int] { + let sa_filtered = sa.filter(onlyOddStruct) + let res: [Int] = []; + for s in sa_filtered { + res.append(s.test) + } + return res + } + fun originalsa(): [Int] { + let res: [Int] = []; + for s in sa { + res.append(s.test) + } + return res + } + `) + + varSizedArrayType := &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + + runValidCase( + t, + inter, + "filtersa", + "originalsa", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) + + t.Run("with fixed sized empty array", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let emptyVals_fixed: [Int; 0] = [] + + let onlyEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + fun filterempty_fixed(): [Int] { + return emptyVals_fixed.filter(onlyEven) + } + fun originalempty_fixed(): [Int; 0] { + return emptyVals_fixed + } + `) + + runValidCase( + t, + inter, + "filterempty_fixed", + "originalempty_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 0, + }, + common.ZeroAddress, + ), + ) + }) + + t.Run("with fixed sized array of integer", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let xs_fixed: [Int; 5] = [1, 2, 3, 100, 201] + + let onlyEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + fun filterxs_fixed(): [Int] { + return xs_fixed.filter(onlyEven) + } + fun originalxs_fixed(): [Int; 5] { + return xs_fixed + } + `) + + runValidCase( + t, + inter, + "filterxs_fixed", + "originalxs_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(100), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 5, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(201), + ), + ) + }) + + t.Run("with fixed sized array of struct", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let onlyOddStruct = + fun (_ x: TestStruct): Bool { + return x.test % 2 == 1 + } + + let sa_fixed: [TestStruct; 3] = [TestStruct(1), TestStruct(2), TestStruct(3)] + + fun filtersa_fixed(): [Int] { + let sa_rev = sa_fixed.filter(onlyOddStruct) + let res: [Int] = []; + for s in sa_rev { + res.append(s.test) + } + return res + } + fun originalsa_fixed(): [Int] { + let res: [Int] = []; + for s in sa_fixed { + res.append(s.test) + } + return res + } + `) + + runValidCase( + t, + inter, + "filtersa_fixed", + "originalsa_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) +} + +func TestInterpretArrayMap(t *testing.T) { + t.Parallel() + + runValidCase := func( + t *testing.T, + inter *interpreter.Interpreter, + mapFuncName, + originalFuncName string, + mappedArray, originalArray *interpreter.ArrayValue, + ) { + val, err := inter.Invoke(mapFuncName) + require.NoError(t, err) + + AssertValuesEqual( + t, + inter, + mappedArray, + val, + ) + + origVal, err := inter.Invoke(originalFuncName) + require.NoError(t, err) + + // Original array remains unchanged + AssertValuesEqual( + t, + inter, + originalArray, + origVal, + ) + } + + t.Run("with variable sized empty array", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let emptyVals: [Int] = [] + + let plusTen = + fun (_ x: Int): Int { + return x + 10 + } + + fun mapempty(): [Int] { + return emptyVals.map(plusTen) + } + fun originalempty(): [Int] { + return emptyVals + } + `) + + emptyVarSizedArray := interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + ) + + runValidCase( + t, + inter, + "mapempty", + "originalempty", + emptyVarSizedArray, + emptyVarSizedArray, + ) + }) + + t.Run("with variable sized array of integer to Int16", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let xs = [1, 2, 3, 100, 201] + + let plusTen = + fun (_ x: Int): Int16 { + return Int16(x) + 10 + } + + fun mapxs(): [Int16] { + return xs.map(plusTen) + } + fun originalxs(): [Int] { + return xs + } + `) + + runValidCase( + t, + inter, + "mapxs", + "originalxs", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt16, + }, + common.ZeroAddress, + interpreter.NewUnmeteredInt16Value(11), + interpreter.NewUnmeteredInt16Value(12), + interpreter.NewUnmeteredInt16Value(13), + interpreter.NewUnmeteredInt16Value(110), + interpreter.NewUnmeteredInt16Value(211), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(201), + ), + ) + }) + + t.Run("with variable sized array of struct to Int", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let innerValueMinusOne = + fun (_ x: TestStruct): Int { + return x.test - 1 + } + + let sa = [TestStruct(1), TestStruct(2), TestStruct(3)] + fun mapsa(): [Int] { + return sa.map(innerValueMinusOne) + } + fun originalsa(): [Int] { + let res: [Int] = []; + for s in sa { + res.append(s.test) + } + return res + } + `) + + varSizedArrayType := &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + + runValidCase( + t, + inter, + "mapsa", + "originalsa", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(0), + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) + + t.Run("with variable sized array of int to struct", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let intPlusTenToStruct = + fun (_ x: Int): TestStruct { + return TestStruct(x + 10) + } + + let orig = [1, 2, 3] + fun mapToStruct(): [Int] { + let mapped = orig.map(intPlusTenToStruct) + let res: [Int] = []; + for s in mapped { + res.append(s.test) + } + return res + } + fun original(): [Int] { + return orig + } + `) + + varSizedArrayType := &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + } + + runValidCase( + t, + inter, + "mapToStruct", + "original", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(11), + interpreter.NewUnmeteredIntValueFromInt64(12), + interpreter.NewUnmeteredIntValueFromInt64(13), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + varSizedArrayType, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) + + t.Run("with fixed sized empty array", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let emptyVals_fixed: [Int; 0] = [] + + let trueForEven = + fun (_ x: Int): Bool { + return x % 2 == 0 + } + + fun mapempty_fixed(): [Bool; 0] { + return emptyVals_fixed.map(trueForEven) + } + fun originalempty_fixed(): [Int; 0] { + return emptyVals_fixed + } + `) + + runValidCase( + t, + inter, + "mapempty_fixed", + "originalempty_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeBool, + Size: 0, + }, + common.ZeroAddress, + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 0, + }, + common.ZeroAddress, + ), + ) + }) + + t.Run("with fixed sized array of integer to Int16", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let xs_fixed: [Int; 5] = [1, 2, 3, 100, 201] + + let plusTen = + fun (_ x: Int): Int16 { + return Int16(x) + 10 + } + + fun mapxs_fixed(): [Int16; 5] { + return xs_fixed.map(plusTen) + } + fun originalxs_fixed(): [Int; 5] { + return xs_fixed + } + `) + + runValidCase( + t, + inter, + "mapxs_fixed", + "originalxs_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt16, + Size: 5, + }, + common.ZeroAddress, + interpreter.NewUnmeteredInt16Value(11), + interpreter.NewUnmeteredInt16Value(12), + interpreter.NewUnmeteredInt16Value(13), + interpreter.NewUnmeteredInt16Value(110), + interpreter.NewUnmeteredInt16Value(211), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 5, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + interpreter.NewUnmeteredIntValueFromInt64(100), + interpreter.NewUnmeteredIntValueFromInt64(201), + ), + ) + }) + + t.Run("with fixed sized array of struct to Int", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let innerValueMinusOne = + fun (_ x: TestStruct): Int { + return x.test - 1 + } + + let sa_fixed: [TestStruct; 3] = [TestStruct(1), TestStruct(2), TestStruct(3)] + + fun mapsa_fixed(): [Int; 3] { + return sa_fixed.map(innerValueMinusOne) + } + fun originalsa_fixed(): [Int] { + let res: [Int] = []; + for s in sa_fixed { + res.append(s.test) + } + return res + } + `) + + runValidCase( + t, + inter, + "mapsa_fixed", + "originalsa_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 3, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(0), + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) + + t.Run("with fixed sized array of Int to Struct", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + pub struct TestStruct { + pub var test: Int + + init(_ t: Int) { + self.test = t + } + } + + let intPlusTenToStruct = + fun (_ x: Int): TestStruct { + return TestStruct(x + 10) + } + + let array_fixed: [Int; 3] = [1, 2, 3] + + fun map_fixed(): [Int] { + let sa = array_fixed.map(intPlusTenToStruct) + let res: [Int] = []; + for s in sa { + res.append(s.test) + } + return res + } + fun original_fixed(): [Int; 3] { + return array_fixed + } + `) + + runValidCase( + t, + inter, + "map_fixed", + "original_fixed", + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.VariableSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(11), + interpreter.NewUnmeteredIntValueFromInt64(12), + interpreter.NewUnmeteredIntValueFromInt64(13), + ), + interpreter.NewArrayValue( + inter, + interpreter.EmptyLocationRange, + &interpreter.ConstantSizedStaticType{ + Type: interpreter.PrimitiveStaticTypeInt, + Size: 3, + }, + common.ZeroAddress, + interpreter.NewUnmeteredIntValueFromInt64(1), + interpreter.NewUnmeteredIntValueFromInt64(2), + interpreter.NewUnmeteredIntValueFromInt64(3), + ), + ) + }) +} + +func TestInterpretOptionalReference(t *testing.T) { + + t.Parallel() + + t.Run("present", func(t *testing.T) { + + inter := parseCheckAndInterpret(t, ` + fun present(): &Int { + let x: Int? = 1 + let y = &x as &Int? + return y! + } + `) + + value, err := inter.Invoke("present") + require.NoError(t, err) + require.Equal( + t, + &interpreter.EphemeralReferenceValue{ + Value: interpreter.NewUnmeteredIntValueFromInt64(1), + BorrowedType: sema.IntType, + }, + value, + ) + + }) + + t.Run("absent", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun absent(): &Int { + let x: Int? = nil + let y = &x as &Int? + return y! + } + `) + + _, err := inter.Invoke("absent") + RequireError(t, err) + + var forceNilError interpreter.ForceNilError + require.ErrorAs(t, err, &forceNilError) + }) +} + +func TestInterpretCastingBoxing(t *testing.T) { + + t.Parallel() + + t.Run("failable cast", func(t *testing.T) { + + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let a = (1 as? Int?!)?.getType() + `) + + variable := inter.Globals.Get("a") + require.NotNil(t, variable) + + require.Equal( + t, + interpreter.NewUnmeteredSomeValueNonCopying( + interpreter.TypeValue{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + ), + variable.GetValue(), + ) + }) + + t.Run("force cast", func(t *testing.T) { + + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let a = (1 as! Int?)?.getType() + `) + + variable := inter.Globals.Get("a") + require.NotNil(t, variable) + + require.Equal( + t, + interpreter.NewUnmeteredSomeValueNonCopying( + interpreter.TypeValue{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + ), + variable.GetValue(), + ) + }) + + t.Run("cast", func(t *testing.T) { + + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + let a = (1 as Int?)?.getType() + `) + + variable := inter.Globals.Get("a") + require.NotNil(t, variable) + + require.Equal( + t, + interpreter.NewUnmeteredSomeValueNonCopying( + interpreter.TypeValue{ + Type: interpreter.PrimitiveStaticTypeInt, + }, + ), + variable.GetValue(), + ) + }) +} + +func TestInterpretNilCoalesceReference(t *testing.T) { + + t.Parallel() + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(stdlib.PanicFunction) + + baseActivation := activations.NewActivation(nil, interpreter.BaseActivation) + interpreter.Declare(baseActivation, stdlib.PanicFunction) + + inter, err := parseCheckAndInterpretWithOptions(t, + ` + let xs = {"a": 2} + let ref = &xs["a"] as &Int? ?? panic("no a") + `, + ParseCheckAndInterpretOptions{ + CheckerConfig: &sema.Config{ + BaseValueActivation: baseValueActivation, + }, + Config: &interpreter.Config{ + BaseActivation: baseActivation, + }, + }, + ) + require.NoError(t, err) + + variable := inter.Globals.Get("ref") require.NotNil(t, variable) require.Equal( @@ -10729,19 +11897,23 @@ func TestInterpretCompositeTypeHandler(t *testing.T) { t.Parallel() - testType := &sema.CompositeType{} + testType := interpreter.CompositeStaticType{ + Location: stdlib.FlowLocation{}, + QualifiedIdentifier: "AccountContractAdded", + TypeID: "flow.AccountContractAdded", + } inter, err := parseCheckAndInterpretWithOptions(t, ` fun test(): Type? { - return CompositeType("TEST") + return CompositeType("flow.AccountContractAdded") } `, ParseCheckAndInterpretOptions{ Config: &interpreter.Config{ CompositeTypeHandler: func(location common.Location, typeID common.TypeID) *sema.CompositeType { - if typeID == "TEST" { - return testType + if _, ok := location.(stdlib.FlowLocation); ok { + return stdlib.FlowEventTypes[typeID] } return nil @@ -10754,10 +11926,8 @@ func TestInterpretCompositeTypeHandler(t *testing.T) { value, err := inter.Invoke("test") require.NoError(t, err) - testStaticType := interpreter.ConvertSemaToStaticType(nil, testType) - require.Equal(t, - interpreter.NewUnmeteredSomeValueNonCopying(interpreter.NewUnmeteredTypeValue(testStaticType)), + interpreter.NewUnmeteredSomeValueNonCopying(interpreter.NewUnmeteredTypeValue(testType)), value, ) } diff --git a/runtime/tests/interpreter/memory_metering_test.go b/runtime/tests/interpreter/memory_metering_test.go index ab51805ed2..22a8c38335 100644 --- a/runtime/tests/interpreter/memory_metering_test.go +++ b/runtime/tests/interpreter/memory_metering_test.go @@ -705,7 +705,8 @@ func TestInterpretSimpleCompositeMetering(t *testing.T) { meter := newTestMemoryGauge() inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) - _, err := inter.Invoke("main", newTestAuthAccountValue(meter, randomAddressValue())) + addressValue := newRandomValueGenerator().randomAddressValue() + _, err := inter.Invoke("main", newTestAuthAccountValue(meter, addressValue)) require.NoError(t, err) assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindSimpleCompositeValueBase)) @@ -724,7 +725,8 @@ func TestInterpretSimpleCompositeMetering(t *testing.T) { meter := newTestMemoryGauge() inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) - _, err := inter.Invoke("main", newTestPublicAccountValue(meter, randomAddressValue())) + addressValue := newRandomValueGenerator().randomAddressValue() + _, err := inter.Invoke("main", newTestPublicAccountValue(meter, addressValue)) require.NoError(t, err) assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindSimpleCompositeValueBase)) @@ -8423,7 +8425,7 @@ func TestInterpretASTMetering(t *testing.T) { k() // identifier, invocation var l = c ? 1 : 2 // conditional, identifier, integer x2 var m = d as AnyStruct // casting, identifier - var n = &d as &AnyStruct // reference, casting, identifier + var n = &d as &AnyStruct? // reference, casting, identifier var o = d! // force, identifier var p = /public/somepath // path } diff --git a/runtime/tests/interpreter/reference_test.go b/runtime/tests/interpreter/reference_test.go index 48b256df50..34abede312 100644 --- a/runtime/tests/interpreter/reference_test.go +++ b/runtime/tests/interpreter/reference_test.go @@ -737,7 +737,14 @@ func TestInterpretReferenceUseAfterShiftStatementMove(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") @@ -876,23 +883,6 @@ func TestInterpretReferenceExpressionOfOptional(t *testing.T) { value := inter.Globals.Get("ref").GetValue() require.IsType(t, interpreter.Nil, value) }) - - t.Run("upcast to optional", func(t *testing.T) { - - t.Parallel() - - inter := parseCheckAndInterpret(t, ` - let i: Int = 1 - let ref = &i as &Int? - `) - - value := inter.Globals.Get("ref").GetValue() - require.IsType(t, &interpreter.SomeValue{}, value) - - innerValue := value.(*interpreter.SomeValue). - InnerValue(inter, interpreter.EmptyLocationRange) - require.IsType(t, &interpreter.EphemeralReferenceValue{}, innerValue) - }) } func TestInterpretReferenceTrackingOnInvocation(t *testing.T) { @@ -935,3 +925,74 @@ func TestInterpretReferenceTrackingOnInvocation(t *testing.T) { require.NoError(t, err) }) } + +func TestInterpretInvalidReferenceToOptionalConfusion(t *testing.T) { + + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + struct S { + fun foo() {} + } + + fun main() { + let y: AnyStruct? = nil + let z: AnyStruct = y + let ref = &z as auth &AnyStruct + let s = ref as! &S + s.foo() + } + `) + + _, err := inter.Invoke("main") + RequireError(t, err) + + require.ErrorAs(t, err, &interpreter.ForceCastTypeMismatchError{}) +} + +func TestInterpretReferenceToOptional(t *testing.T) { + + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + fun main(): AnyStruct { + let y: Int? = nil + let z: AnyStruct = y + return &z as auth &AnyStruct + } + `) + + value, err := inter.Invoke("main") + require.NoError(t, err) + + AssertValuesEqual( + t, + inter, + &interpreter.EphemeralReferenceValue{ + Value: interpreter.Nil, + BorrowedType: sema.AnyStructType, + Authorized: true, + }, + value, + ) +} + +func TestInterpretInvalidatedReferenceToOptional(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + resource Foo {} + + fun main(): AnyStruct { + let y: @Foo? <- create Foo() + let z: @AnyResource <- y + var ref = &z as &AnyResource + + destroy z + return ref + } + `) + + _, err := inter.Invoke("main") + require.NoError(t, err) +} diff --git a/runtime/tests/interpreter/resources_test.go b/runtime/tests/interpreter/resources_test.go index e8b95a1402..cd7f20e49d 100644 --- a/runtime/tests/interpreter/resources_test.go +++ b/runtime/tests/interpreter/resources_test.go @@ -189,7 +189,14 @@ func TestInterpretImplicitResourceRemovalFromContainer(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") @@ -311,7 +318,14 @@ func TestInterpretImplicitResourceRemovalFromContainer(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") @@ -428,7 +442,14 @@ func TestInterpretImplicitResourceRemovalFromContainer(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") @@ -550,7 +571,14 @@ func TestInterpretImplicitResourceRemovalFromContainer(t *testing.T) { r1, err := inter.Invoke("createR1") require.NoError(t, err) - r1 = r1.Transfer(inter, interpreter.EmptyLocationRange, atree.Address{1}, false, nil) + r1 = r1.Transfer( + inter, + interpreter.EmptyLocationRange, + atree.Address{1}, + false, + nil, + nil, + ) r1Type := checker.RequireGlobalType(t, inter.Program.Elaboration, "R1") diff --git a/runtime/tests/interpreter/values_test.go b/runtime/tests/interpreter/values_test.go index 0c13a00ce0..68233b183d 100644 --- a/runtime/tests/interpreter/values_test.go +++ b/runtime/tests/interpreter/values_test.go @@ -55,9 +55,8 @@ func TestRandomMapOperations(t *testing.T) { t.Parallel() - seed := time.Now().UnixNano() - fmt.Printf("Seed used for map opearations test: %d \n", seed) - rand.Seed(seed) + r := newRandomValueGenerator() + t.Logf("seed: %d", r.seed) storage := newUnmeteredInMemoryStorage() inter, err := interpreter.NewInterpreter( @@ -79,7 +78,7 @@ func TestRandomMapOperations(t *testing.T) { ) require.NoError(t, err) - numberOfValues := randomInt(containerMaxSize) + numberOfValues := r.randomInt(containerMaxSize) var testMap, copyOfTestMap *interpreter.DictionaryValue var storageSize, slabCounts int @@ -90,8 +89,8 @@ func TestRandomMapOperations(t *testing.T) { t.Run("construction", func(t *testing.T) { keyValues := make([]interpreter.Value, numberOfValues*2) for i := 0; i < numberOfValues; i++ { - key := randomHashableValue(inter) - value := randomStorableValue(inter, 0) + key := r.randomHashableValue(inter) + value := r.randomStorableValue(inter, 0) entries.put(inter, key, value) @@ -149,6 +148,7 @@ func TestRandomMapOperations(t *testing.T) { newOwner, false, nil, + nil, ).(*interpreter.DictionaryValue) require.Equal(t, entries.size(), copyOfTestMap.Count()) @@ -211,8 +211,8 @@ func TestRandomMapOperations(t *testing.T) { // Insert for i := 0; i < numberOfValues; i++ { - key := randomHashableValue(inter) - value := randomStorableValue(inter, 0) + key := r.randomHashableValue(inter) + value := r.randomStorableValue(inter, 0) newEntries.put(inter, key, value) @@ -239,8 +239,8 @@ func TestRandomMapOperations(t *testing.T) { keyValues := make([][2]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - key := randomHashableValue(inter) - value := randomStorableValue(inter, 0) + key := r.randomHashableValue(inter) + value := r.randomStorableValue(inter, 0) newEntries.put(inter, key, value) @@ -316,7 +316,7 @@ func TestRandomMapOperations(t *testing.T) { keyValues := make([][2]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { // Create a random enum as key - key := generateRandomHashableValue(inter, Enum) + key := r.generateRandomHashableValue(inter, randomValueKindEnum) value := interpreter.Void newEntries.put(inter, key, value) @@ -360,7 +360,7 @@ func TestRandomMapOperations(t *testing.T) { // Generate unique key var key interpreter.Value for { - key = randomHashableValue(inter) + key = r.randomHashableValue(inter) var foundConflict bool for j := 0; j < i; j++ { @@ -376,7 +376,7 @@ func TestRandomMapOperations(t *testing.T) { } keyValues[i][0] = key - keyValues[i][1] = randomStorableValue(inter, 0) + keyValues[i][1] = r.randomStorableValue(inter, 0) } dictionary := interpreter.NewDictionaryValueWithAddress( @@ -406,7 +406,7 @@ func TestRandomMapOperations(t *testing.T) { return false } - return randomInt(1) == 1 + return r.randomInt(1) == 1 } for insertCount < numberOfValues || dictionary.Count() > 0 { @@ -460,8 +460,8 @@ func TestRandomMapOperations(t *testing.T) { keyValues := make([]interpreter.Value, numberOfValues*2) for i := 0; i < numberOfValues; i++ { - key := randomHashableValue(inter) - value := randomStorableValue(inter, 0) + key := r.randomHashableValue(inter) + value := r.randomStorableValue(inter, 0) entries.put(inter, key, value) @@ -488,6 +488,7 @@ func TestRandomMapOperations(t *testing.T) { newOwner, true, nil, + nil, ).(*interpreter.DictionaryValue) require.Equal(t, entries.size(), movedDictionary.Count()) @@ -518,9 +519,8 @@ func TestRandomArrayOperations(t *testing.T) { t.Skip("smoke tests are disabled") } - seed := time.Now().UnixNano() - fmt.Printf("Seed used for array opearations test: %d \n", seed) - rand.Seed(seed) + r := newRandomValueGenerator() + t.Logf("seed: %d", r.seed) storage := newUnmeteredInMemoryStorage() inter, err := interpreter.NewInterpreter( @@ -540,7 +540,7 @@ func TestRandomArrayOperations(t *testing.T) { ) require.NoError(t, err) - numberOfValues := randomInt(containerMaxSize) + numberOfValues := r.randomInt(containerMaxSize) var testArray, copyOfTestArray *interpreter.ArrayValue var storageSize, slabCounts int @@ -551,7 +551,7 @@ func TestRandomArrayOperations(t *testing.T) { t.Run("construction", func(t *testing.T) { values := make([]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - value := randomStorableValue(inter, 0) + value := r.randomStorableValue(inter, 0) elements[i] = value values[i] = value.Clone(inter) } @@ -603,6 +603,7 @@ func TestRandomArrayOperations(t *testing.T) { newOwner, false, nil, + nil, ).(*interpreter.ArrayValue) require.Equal(t, len(elements), copyOfTestArray.Count()) @@ -653,7 +654,7 @@ func TestRandomArrayOperations(t *testing.T) { require.Equal(t, 0, testArray.Count()) for i := 0; i < numberOfValues; i++ { - element := randomStorableValue(inter, 0) + element := r.randomStorableValue(inter, 0) newElements[i] = element testArray.Insert( @@ -688,7 +689,7 @@ func TestRandomArrayOperations(t *testing.T) { require.Equal(t, 0, testArray.Count()) for i := 0; i < numberOfValues; i++ { - element := randomStorableValue(inter, 0) + element := r.randomStorableValue(inter, 0) newElements[i] = element testArray.Append( @@ -711,7 +712,7 @@ func TestRandomArrayOperations(t *testing.T) { newElements := make([]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - newElements[i] = randomStorableValue(inter, 0) + newElements[i] = r.randomStorableValue(inter, 0) } testArray = interpreter.NewArrayValue( @@ -762,7 +763,7 @@ func TestRandomArrayOperations(t *testing.T) { elements := make([]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - elements[i] = randomStorableValue(inter, 0) + elements[i] = r.randomStorableValue(inter, 0) } testArray = interpreter.NewArrayValue( @@ -791,7 +792,7 @@ func TestRandomArrayOperations(t *testing.T) { return false } - return randomInt(1) == 1 + return r.randomInt(1) == 1 } for insertCount < numberOfValues || testArray.Count() > 0 { @@ -831,7 +832,7 @@ func TestRandomArrayOperations(t *testing.T) { elements := make([]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - value := randomStorableValue(inter, 0) + value := r.randomStorableValue(inter, 0) elements[i] = value values[i] = value.Clone(inter) } @@ -858,6 +859,7 @@ func TestRandomArrayOperations(t *testing.T) { newOwner, true, nil, + nil, ).(*interpreter.ArrayValue) require.Equal(t, len(elements), movedArray.Count()) @@ -882,9 +884,8 @@ func TestRandomCompositeValueOperations(t *testing.T) { t.Skip("smoke tests are disabled") } - seed := time.Now().UnixNano() - fmt.Printf("Seed used for compsoite opearations test: %d \n", seed) - rand.Seed(seed) + r := newRandomValueGenerator() + t.Logf("seed: %d", r.seed) storage := newUnmeteredInMemoryStorage() inter, err := interpreter.NewInterpreter( @@ -908,11 +909,11 @@ func TestRandomCompositeValueOperations(t *testing.T) { var storageSize, slabCounts int var orgFields map[string]interpreter.Value - fieldsCount := randomInt(compositeMaxFields) + fieldsCount := r.randomInt(compositeMaxFields) orgOwner := common.Address{'A'} t.Run("construction", func(t *testing.T) { - testComposite, orgFields = newCompositeValue(orgOwner, fieldsCount, inter) + testComposite, orgFields = r.randomCompositeValue(orgOwner, fieldsCount, inter, 0) storageSize, slabCounts = getSlabStorageSize(t, storage) @@ -946,6 +947,7 @@ func TestRandomCompositeValueOperations(t *testing.T) { newOwner, false, nil, + nil, ).(*interpreter.CompositeValue) for name, orgValue := range orgFields { @@ -986,6 +988,7 @@ func TestRandomCompositeValueOperations(t *testing.T) { newOwner, false, nil, + nil, ).(*interpreter.CompositeValue) require.NoError(t, err) @@ -998,7 +1001,7 @@ func TestRandomCompositeValueOperations(t *testing.T) { }) t.Run("move", func(t *testing.T) { - composite, fields := newCompositeValue(orgOwner, fieldsCount, inter) + composite, fields := r.randomCompositeValue(orgOwner, fieldsCount, inter, 0) owner := composite.GetOwner() assert.Equal(t, orgOwner, owner) @@ -1010,6 +1013,7 @@ func TestRandomCompositeValueOperations(t *testing.T) { newOwner, true, nil, + nil, ).(*interpreter.CompositeValue) // Cleanup the slab of original composite. @@ -1027,15 +1031,16 @@ func TestRandomCompositeValueOperations(t *testing.T) { }) } -func newCompositeValue( +func (r randomValueGenerator) randomCompositeValue( orgOwner common.Address, fieldsCount int, inter *interpreter.Interpreter, + currentDepth int, ) (*interpreter.CompositeValue, map[string]interpreter.Value) { orgFields := make(map[string]interpreter.Value, fieldsCount) - identifier := randomUTF8String() + identifier := r.randomUTF8String() location := common.AddressLocation{ Address: orgOwner, @@ -1047,7 +1052,7 @@ func newCompositeValue( fieldNames := make(map[string]any, fieldsCount) for i := 0; i < fieldsCount; { - fieldName := randomUTF8String() + fieldName := r.randomUTF8String() // avoid duplicate field names if _, ok := fieldNames[fieldName]; ok { @@ -1057,7 +1062,7 @@ func newCompositeValue( field := interpreter.NewUnmeteredCompositeField( fieldName, - randomStorableValue(inter, 0), + r.randomStorableValue(inter, currentDepth+1), ) fields[i] = field @@ -1121,158 +1126,183 @@ func getSlabStorageSize(t *testing.T, storage interpreter.InMemoryStorage) (tota return } -func randomStorableValue(inter *interpreter.Interpreter, currentDepth int) interpreter.Value { +type randomValueGenerator struct { + seed int64 + rand *rand.Rand +} + +func newRandomValueGenerator() randomValueGenerator { + seed := time.Now().UnixNano() + + return randomValueGenerator{ + seed: seed, + rand: rand.New(rand.NewSource(seed)), + } +} +func (r randomValueGenerator) randomStorableValue(inter *interpreter.Interpreter, currentDepth int) interpreter.Value { n := 0 if currentDepth < containerMaxDepth { - n = randomInt(Composite) + n = r.randomInt(randomValueKindComposite) } else { - n = randomInt(IDCapability) + n = r.randomInt(randomValueKindIDCapability) } switch n { // Non-hashable - case Void: + case randomValueKindVoid: return interpreter.Void - case Nil: + case randomValueKindNil: return interpreter.Nil - case Dictionary_1, Dictionary_2: - return randomDictionaryValue(inter, currentDepth) - case Array_1, Array_2: - return randomArrayValue(inter, currentDepth) - case Composite: - return randomCompositeValue(inter, common.CompositeKindStructure, currentDepth) - case PathCapability: + case randomValueKindDictionaryVariant1, + randomValueKindDictionaryVariant2: + return r.randomDictionaryValue(inter, currentDepth) + case randomValueKindArrayVariant1, + randomValueKindArrayVariant2: + return r.randomArrayValue(inter, currentDepth) + case randomValueKindComposite: + fieldsCount := r.randomInt(compositeMaxFields) + v, _ := r.randomCompositeValue(common.ZeroAddress, fieldsCount, inter, currentDepth) + return v + case randomValueKindPathCapability: return interpreter.NewUnmeteredPathCapabilityValue( - randomAddressValue(), - randomPathValue(), + r.randomAddressValue(), + r.randomPathValue(), interpreter.ReferenceStaticType{ Authorized: false, BorrowedType: interpreter.PrimitiveStaticTypeAnyStruct, }, ) - case IDCapability: + case randomValueKindIDCapability: return interpreter.NewUnmeteredIDCapabilityValue( - interpreter.UInt64Value(randomInt(math.MaxInt-1)), - randomAddressValue(), + interpreter.UInt64Value(r.randomInt(math.MaxInt-1)), + r.randomAddressValue(), interpreter.ReferenceStaticType{ Authorized: false, BorrowedType: interpreter.PrimitiveStaticTypeAnyStruct, }, ) - case Some: + case randomValueKindSome: return interpreter.NewUnmeteredSomeValueNonCopying( - randomStorableValue(inter, currentDepth+1), + r.randomStorableValue(inter, currentDepth+1), ) // Hashable default: - return generateRandomHashableValue(inter, n) + return r.generateRandomHashableValue(inter, n) } } -func randomHashableValue(interpreter *interpreter.Interpreter) interpreter.Value { - return generateRandomHashableValue(interpreter, randomInt(Enum)) +func (r randomValueGenerator) randomHashableValue(interpreter *interpreter.Interpreter) interpreter.Value { + return r.generateRandomHashableValue(interpreter, r.randomInt(randomValueKindEnum)) } -func generateRandomHashableValue(inter *interpreter.Interpreter, n int) interpreter.Value { +func (r randomValueGenerator) generateRandomHashableValue(inter *interpreter.Interpreter, n int) interpreter.Value { switch n { - // Int - case Int: - return interpreter.NewUnmeteredIntValueFromInt64(int64(sign()) * rand.Int63()) - case Int8: - return interpreter.NewUnmeteredInt8Value(int8(randomInt(math.MaxUint8))) - case Int16: - return interpreter.NewUnmeteredInt16Value(int16(randomInt(math.MaxUint16))) - case Int32: - return interpreter.NewUnmeteredInt32Value(int32(sign()) * rand.Int31()) - case Int64: - return interpreter.NewUnmeteredInt64Value(int64(sign()) * rand.Int63()) - case Int128: - return interpreter.NewUnmeteredInt128ValueFromInt64(int64(sign()) * rand.Int63()) - case Int256: - return interpreter.NewUnmeteredInt256ValueFromInt64(int64(sign()) * rand.Int63()) - - // UInt - case UInt: - return interpreter.NewUnmeteredUIntValueFromUint64(rand.Uint64()) - case UInt8: - return interpreter.NewUnmeteredUInt8Value(uint8(randomInt(math.MaxUint8))) - case UInt16: - return interpreter.NewUnmeteredUInt16Value(uint16(randomInt(math.MaxUint16))) - case UInt32: - return interpreter.NewUnmeteredUInt32Value(rand.Uint32()) - case UInt64_1, UInt64_2, UInt64_3, UInt64_4: // should be more common - return interpreter.NewUnmeteredUInt64Value(rand.Uint64()) - case UInt128: - return interpreter.NewUnmeteredUInt128ValueFromUint64(rand.Uint64()) - case UInt256: - return interpreter.NewUnmeteredUInt256ValueFromUint64(rand.Uint64()) - - // Word - case Word8: - return interpreter.NewUnmeteredWord8Value(uint8(randomInt(math.MaxUint8))) - case Word16: - return interpreter.NewUnmeteredWord16Value(uint16(randomInt(math.MaxUint16))) - case Word32: - return interpreter.NewUnmeteredWord32Value(rand.Uint32()) - case Word64: - return interpreter.NewUnmeteredWord64Value(rand.Uint64()) - case Word128: - return interpreter.NewUnmeteredWord128ValueFromUint64(rand.Uint64()) - case Word256: - return interpreter.NewUnmeteredWord256ValueFromUint64(rand.Uint64()) - - // Fixed point - case Fix64: - return interpreter.NewUnmeteredFix64ValueWithInteger(int64(sign())*rand.Int63n(sema.Fix64TypeMaxInt), interpreter.EmptyLocationRange) - case UFix64: + // Int* + case randomValueKindInt: + return interpreter.NewUnmeteredIntValueFromInt64(int64(r.randomSign()) * r.rand.Int63()) + case randomValueKindInt8: + return interpreter.NewUnmeteredInt8Value(int8(r.randomInt(math.MaxUint8))) + case randomValueKindInt16: + return interpreter.NewUnmeteredInt16Value(int16(r.randomInt(math.MaxUint16))) + case randomValueKindInt32: + return interpreter.NewUnmeteredInt32Value(int32(r.randomSign()) * r.rand.Int31()) + case randomValueKindInt64: + return interpreter.NewUnmeteredInt64Value(int64(r.randomSign()) * r.rand.Int63()) + case randomValueKindInt128: + return interpreter.NewUnmeteredInt128ValueFromInt64(int64(r.randomSign()) * r.rand.Int63()) + case randomValueKindInt256: + return interpreter.NewUnmeteredInt256ValueFromInt64(int64(r.randomSign()) * r.rand.Int63()) + + // UInt* + case randomValueKindUInt: + return interpreter.NewUnmeteredUIntValueFromUint64(r.rand.Uint64()) + case randomValueKindUInt8: + return interpreter.NewUnmeteredUInt8Value(uint8(r.randomInt(math.MaxUint8))) + case randomValueKindUInt16: + return interpreter.NewUnmeteredUInt16Value(uint16(r.randomInt(math.MaxUint16))) + case randomValueKindUInt32: + return interpreter.NewUnmeteredUInt32Value(r.rand.Uint32()) + case randomValueKindUInt64Variant1, + randomValueKindUInt64Variant2, + randomValueKindUInt64Variant3, + randomValueKindUInt64Variant4: // should be more common + return interpreter.NewUnmeteredUInt64Value(r.rand.Uint64()) + case randomValueKindUInt128: + return interpreter.NewUnmeteredUInt128ValueFromUint64(r.rand.Uint64()) + case randomValueKindUInt256: + return interpreter.NewUnmeteredUInt256ValueFromUint64(r.rand.Uint64()) + + // Word* + case randomValueKindWord8: + return interpreter.NewUnmeteredWord8Value(uint8(r.randomInt(math.MaxUint8))) + case randomValueKindWord16: + return interpreter.NewUnmeteredWord16Value(uint16(r.randomInt(math.MaxUint16))) + case randomValueKindWord32: + return interpreter.NewUnmeteredWord32Value(r.rand.Uint32()) + case randomValueKindWord64: + return interpreter.NewUnmeteredWord64Value(r.rand.Uint64()) + case randomValueKindWord128: + return interpreter.NewUnmeteredWord128ValueFromUint64(r.rand.Uint64()) + case randomValueKindWord256: + return interpreter.NewUnmeteredWord256ValueFromUint64(r.rand.Uint64()) + + // (U)Fix* + case randomValueKindFix64: + return interpreter.NewUnmeteredFix64ValueWithInteger( + int64(r.randomSign())*r.rand.Int63n(sema.Fix64TypeMaxInt), + interpreter.EmptyLocationRange, + ) + case randomValueKindUFix64: return interpreter.NewUnmeteredUFix64ValueWithInteger( - uint64(rand.Int63n( + uint64(r.rand.Int63n( int64(sema.UFix64TypeMaxInt), )), interpreter.EmptyLocationRange, ) // String - case String_1, String_2, String_3, String_4: // small string - should be more common - size := randomInt(255) - return interpreter.NewUnmeteredStringValue(randomUTF8StringOfSize(size)) - case String_5: // large string - size := randomInt(4048) + 255 - return interpreter.NewUnmeteredStringValue(randomUTF8StringOfSize(size)) - - case Bool_True: + case randomValueKindStringVariant1, + randomValueKindStringVariant2, + randomValueKindStringVariant3, + randomValueKindStringVariant4: // small string - should be more common + size := r.randomInt(255) + return interpreter.NewUnmeteredStringValue(r.randomUTF8StringOfSize(size)) + case randomValueKindStringVariant5: // large string + size := r.randomInt(4048) + 255 + return interpreter.NewUnmeteredStringValue(r.randomUTF8StringOfSize(size)) + + case randomValueKindBoolVariantTrue: return interpreter.TrueValue - case Bool_False: + case randomValueKindBoolVariantFalse: return interpreter.FalseValue - case Address: - return randomAddressValue() + case randomValueKindAddress: + return r.randomAddressValue() - case Path: - return randomPathValue() + case randomValueKindPath: + return r.randomPathValue() - case Enum: + case randomValueKindEnum: // Get a random integer subtype to be used as the raw-type of enum - typ := randomInt(Word64) + typ := r.randomInt(randomValueKindWord64) - rawValue := generateRandomHashableValue(inter, typ).(interpreter.NumberValue) + rawValue := r.generateRandomHashableValue(inter, typ).(interpreter.NumberValue) - identifier := randomUTF8String() + identifier := r.randomUTF8String() - address := make([]byte, 8) - rand.Read(address) + address := r.randomAddressValue() location := common.AddressLocation{ - Address: common.MustBytesToAddress(address), + Address: common.Address(address), Name: identifier, } enumType := &sema.CompositeType{ Identifier: identifier, - EnumRawType: intSubtype(typ), + EnumRawType: r.intSubtype(typ), Kind: common.CompositeKindEnum, Location: location, } @@ -1304,27 +1334,27 @@ func generateRandomHashableValue(inter *interpreter.Interpreter, n int) interpre return enum default: - panic(fmt.Sprintf("unsupported: %d", n)) + panic(fmt.Sprintf("unsupported: %d", n)) } } -func sign() int { - if randomInt(1) == 1 { +func (r randomValueGenerator) randomSign() int { + if r.randomInt(1) == 1 { return 1 } return -1 } -func randomAddressValue() interpreter.AddressValue { +func (r randomValueGenerator) randomAddressValue() interpreter.AddressValue { data := make([]byte, 8) - rand.Read(data) + r.rand.Read(data) return interpreter.NewUnmeteredAddressValueFromBytes(data) } -func randomPathValue() interpreter.PathValue { - randomDomain := rand.Intn(len(common.AllPathDomains)) - identifier := randomUTF8String() +func (r randomValueGenerator) randomPathValue() interpreter.PathValue { + randomDomain := r.rand.Intn(len(common.AllPathDomains)) + identifier := r.randomUTF8String() return interpreter.PathValue{ Domain: common.AllPathDomains[randomDomain], @@ -1332,17 +1362,17 @@ func randomPathValue() interpreter.PathValue { } } -func randomDictionaryValue( +func (r randomValueGenerator) randomDictionaryValue( inter *interpreter.Interpreter, currentDepth int, ) interpreter.Value { - entryCount := randomInt(innerContainerMaxSize) + entryCount := r.randomInt(innerContainerMaxSize) keyValues := make([]interpreter.Value, entryCount*2) for i := 0; i < entryCount; i++ { - key := randomHashableValue(inter) - value := randomStorableValue(inter, currentDepth+1) + key := r.randomHashableValue(inter) + value := r.randomStorableValue(inter, currentDepth+1) keyValues[i*2] = key keyValues[i*2+1] = value } @@ -1359,16 +1389,16 @@ func randomDictionaryValue( ) } -func randomInt(upperBound int) int { - return rand.Intn(upperBound + 1) +func (r randomValueGenerator) randomInt(upperBound int) int { + return r.rand.Intn(upperBound + 1) } -func randomArrayValue(inter *interpreter.Interpreter, currentDepth int) interpreter.Value { - elementsCount := randomInt(innerContainerMaxSize) +func (r randomValueGenerator) randomArrayValue(inter *interpreter.Interpreter, currentDepth int) interpreter.Value { + elementsCount := r.randomInt(innerContainerMaxSize) elements := make([]interpreter.Value, elementsCount) for i := 0; i < elementsCount; i++ { - value := randomStorableValue(inter, currentDepth+1) + value := r.randomStorableValue(inter, currentDepth+1) elements[i] = value.Clone(inter) } @@ -1383,182 +1413,135 @@ func randomArrayValue(inter *interpreter.Interpreter, currentDepth int) interpre ) } -func randomCompositeValue( - inter *interpreter.Interpreter, - kind common.CompositeKind, - currentDepth int, -) interpreter.Value { - - identifier := randomUTF8String() - - address := make([]byte, 8) - rand.Read(address) - - location := common.AddressLocation{ - Address: common.MustBytesToAddress(address), - Name: identifier, - } - - fieldsCount := randomInt(compositeMaxFields) - fields := make([]interpreter.CompositeField, fieldsCount) - - for i := 0; i < fieldsCount; i++ { - fieldName := randomUTF8String() - - fields[i] = interpreter.NewUnmeteredCompositeField( - fieldName, - randomStorableValue(inter, currentDepth+1), - ) - } - - compositeType := &sema.CompositeType{ - Location: location, - Identifier: identifier, - Kind: kind, - } - - compositeType.Members = &sema.StringMemberOrderedMap{} - for _, field := range fields { - compositeType.Members.Set( - field.Name, - sema.NewUnmeteredPublicConstantFieldMember( - compositeType, - field.Name, - sema.AnyStructType, // TODO: handle resources - "", - ), - ) - } - - // Add the type to the elaboration, to short-circuit the type-lookup - inter.Program.Elaboration.SetCompositeType( - compositeType.ID(), - compositeType, - ) - - return interpreter.NewCompositeValue( - inter, - interpreter.EmptyLocationRange, - location, - identifier, - kind, - fields, - common.ZeroAddress, - ) -} - -func intSubtype(n int) sema.Type { +func (r randomValueGenerator) intSubtype(n int) sema.Type { switch n { // Int - case Int: + case randomValueKindInt: return sema.IntType - case Int8: + case randomValueKindInt8: return sema.Int8Type - case Int16: + case randomValueKindInt16: return sema.Int16Type - case Int32: + case randomValueKindInt32: return sema.Int32Type - case Int64: + case randomValueKindInt64: return sema.Int64Type - case Int128: + case randomValueKindInt128: return sema.Int128Type - case Int256: + case randomValueKindInt256: return sema.Int256Type // UInt - case UInt: + case randomValueKindUInt: return sema.UIntType - case UInt8: + case randomValueKindUInt8: return sema.UInt8Type - case UInt16: + case randomValueKindUInt16: return sema.UInt16Type - case UInt32: + case randomValueKindUInt32: return sema.UInt32Type - case UInt64_1, UInt64_2, UInt64_3, UInt64_4: + case randomValueKindUInt64Variant1, + randomValueKindUInt64Variant2, + randomValueKindUInt64Variant3, + randomValueKindUInt64Variant4: return sema.UInt64Type - case UInt128: + case randomValueKindUInt128: return sema.UInt128Type - case UInt256: + case randomValueKindUInt256: return sema.UInt256Type // Word - case Word8: + case randomValueKindWord8: return sema.Word8Type - case Word16: + case randomValueKindWord16: return sema.Word16Type - case Word32: + case randomValueKindWord32: return sema.Word32Type - case Word64: + case randomValueKindWord64: return sema.Word64Type - case Word128: + case randomValueKindWord128: return sema.Word128Type - case Word256: + case randomValueKindWord256: return sema.Word256Type default: - panic(fmt.Sprintf("unsupported: %d", n)) + panic(fmt.Sprintf("unsupported: %d", n)) } } const ( // Hashable values - Int = iota - Int8 - Int16 - Int32 - Int64 - Int128 - Int256 - - UInt - UInt8 - UInt16 - UInt32 - UInt64_1 - UInt64_2 - UInt64_3 - UInt64_4 - UInt128 - UInt256 - - Word8 - Word16 - Word32 - Word64 - Word128 - Word256 - - Fix64 - UFix64 - - String_1 - String_2 - String_3 - String_4 - String_5 - - Bool_True - Bool_False - Path - Address - Enum + // Int* + randomValueKindInt = iota + randomValueKindInt8 + randomValueKindInt16 + randomValueKindInt32 + randomValueKindInt64 + randomValueKindInt128 + randomValueKindInt256 + + // UInt* + randomValueKindUInt + randomValueKindUInt8 + randomValueKindUInt16 + randomValueKindUInt32 + randomValueKindUInt64Variant1 + randomValueKindUInt64Variant2 + randomValueKindUInt64Variant3 + randomValueKindUInt64Variant4 + randomValueKindUInt128 + randomValueKindUInt256 + + // Word* + randomValueKindWord8 + randomValueKindWord16 + randomValueKindWord32 + randomValueKindWord64 + randomValueKindWord128 + randomValueKindWord256 + + // (U)Fix* + randomValueKindFix64 + randomValueKindUFix64 - // Non-hashable values + // String + randomValueKindStringVariant1 + randomValueKindStringVariant2 + randomValueKindStringVariant3 + randomValueKindStringVariant4 + randomValueKindStringVariant5 + + randomValueKindBoolVariantTrue + randomValueKindBoolVariantFalse + randomValueKindPath + randomValueKindAddress + randomValueKindEnum - Void - Nil // `Never?` - PathCapability - IDCapability + // Non-hashable values + randomValueKindVoid + randomValueKindNil // `Never?` + randomValueKindPathCapability + randomValueKindIDCapability // Containers - Some - Array_1 - Array_2 - Dictionary_1 - Dictionary_2 - Composite + randomValueKindSome + randomValueKindArrayVariant1 + randomValueKindArrayVariant2 + randomValueKindDictionaryVariant1 + randomValueKindDictionaryVariant2 + randomValueKindComposite ) +func (r randomValueGenerator) randomUTF8String() string { + return r.randomUTF8StringOfSize(8) +} + +func (r randomValueGenerator) randomUTF8StringOfSize(size int) string { + identifier := make([]byte, size) + r.rand.Read(identifier) + return strings.ToValidUTF8(string(identifier), "$") +} + type valueMap struct { values map[any]interpreter.Value keys map[any]interpreter.Value @@ -1629,13 +1612,3 @@ func (m *valueMap) internalKey(inter *interpreter.Interpreter, key interpreter.V func (m *valueMap) size() int { return len(m.keys) } - -func randomUTF8String() string { - return randomUTF8StringOfSize(8) -} - -func randomUTF8StringOfSize(size int) string { - identifier := make([]byte, size) - rand.Read(identifier) - return strings.ToValidUTF8(string(identifier), "$") -} diff --git a/runtime/tests/utils/utils.go b/runtime/tests/utils/utils.go index c630385a63..8835a83c6b 100644 --- a/runtime/tests/utils/utils.go +++ b/runtime/tests/utils/utils.go @@ -28,8 +28,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/errors" "github.com/onflow/cadence/runtime/interpreter" + "github.com/onflow/cadence/runtime/sema" "github.com/onflow/cadence/runtime/common" ) @@ -207,6 +209,16 @@ func RequireError(t *testing.T, err error) { _ = err.Error() + if hasImportLocation, ok := err.(common.HasLocation); ok { + location := hasImportLocation.ImportLocation() + assert.NotNil(t, location) + } + + if hasPosition, ok := err.(ast.HasPosition); ok { + _ = hasPosition.StartPosition() + _ = hasPosition.EndPosition(nil) + } + if hasErrorNotes, ok := err.(errors.ErrorNotes); ok { for _, note := range hasErrorNotes.ErrorNotes() { _ = note.Message() @@ -216,4 +228,8 @@ func RequireError(t *testing.T, err error) { if hasSecondaryError, ok := err.(errors.SecondaryError); ok { _ = hasSecondaryError.SecondaryError() } + + if hasSuggestedFixes, ok := err.(sema.HasSuggestedFixes); ok { + _ = hasSuggestedFixes.SuggestFixes("") + } } diff --git a/tools/analysis/diagnostic.go b/tools/analysis/diagnostic.go index d273fa75c4..5a6179dbcd 100644 --- a/tools/analysis/diagnostic.go +++ b/tools/analysis/diagnostic.go @@ -21,17 +21,12 @@ package analysis import ( "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/sema" ) -type SuggestedFix struct { - Message string - TextEdits []TextEdit -} +type SuggestedFix = sema.SuggestedFix -type TextEdit struct { - Replacement string - ast.Range -} +type TextEdit = sema.TextEdit type Diagnostic struct { Location common.Location @@ -41,3 +36,7 @@ type Diagnostic struct { SuggestedFixes []SuggestedFix ast.Range } + +func (d Diagnostic) SuggestFixes(_ string) []SuggestedFix { + return d.SuggestedFixes +} diff --git a/tools/batch-script/go.mod b/tools/batch-script/go.mod index 50521aad3a..39fb396bfa 100644 --- a/tools/batch-script/go.mod +++ b/tools/batch-script/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/cadence/tools/batch-script -go 1.18 +go 1.20 require ( github.com/onflow/cadence v0.21.2 diff --git a/tools/compatibility-check/cmd/check_diff/main.go b/tools/compatibility-check/cmd/check_diff/main.go deleted file mode 100644 index c1e7188e60..0000000000 --- a/tools/compatibility-check/cmd/check_diff/main.go +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Cadence - The resource-oriented smart contract programming language - * - * Copyright Dapper Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "os" - - "github.com/rs/zerolog/log" - - "github.com/sergi/go-diff/diffmatchpatch" -) - -func main() { - if len(os.Args) < 2 { - log.Error().Msg("not enough arguments. Usage: old_checking_results new_checking_results") - return - } - - oldResultsPath := os.Args[1] - newResultsPath := os.Args[2] - - oldResultsFile, err := os.ReadFile(oldResultsPath) - if err != nil { - log.Err(err).Msgf("failed to open file: %s", oldResultsPath) - return - } - - newResultsFile, err := os.ReadFile(newResultsPath) - if err != nil { - log.Err(err).Msgf("failed to open file: %s", newResultsPath) - return - } - - compareBytes(oldResultsFile, newResultsFile) -} - -func compareBytes(old, new []byte) { - dmp := diffmatchpatch.New() - - diffs := dmp.DiffMain(string(old), string(new), false) - - changes := make([]diffmatchpatch.Diff, 0) - - // Filter out only the diff chunks with changes. - // No need to print the equal chunks. - for _, diff := range diffs { - if diff.Type == diffmatchpatch.DiffEqual { - continue - } - changes = append(changes, diff) - } - - fmt.Println(dmp.DiffPrettyText(changes)) - - if len(changes) > 0 { - log.Fatal().Msg("found differences") - } -} diff --git a/tools/compatibility-check/go.mod b/tools/compatibility-check/go.mod index e9d3b6135c..baed296863 100644 --- a/tools/compatibility-check/go.mod +++ b/tools/compatibility-check/go.mod @@ -1,11 +1,10 @@ module github.com/onflow/cadence/tools/compatibility_check -go 1.19 +go 1.20 require ( github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121 github.com/rs/zerolog v1.26.1 - github.com/sergi/go-diff v1.2.0 github.com/stretchr/testify v1.7.3 ) @@ -15,6 +14,7 @@ require ( github.com/fxamacker/cbor/v2 v2.4.1-0.20220515183430-ad2eae63303f // indirect github.com/fxamacker/circlehash v0.3.0 // indirect github.com/klauspost/cpuid/v2 v2.0.14 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect github.com/onflow/atree v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/tools/compatibility-check/go.sum b/tools/compatibility-check/go.sum index cbc3f58844..765ad9dce2 100644 --- a/tools/compatibility-check/go.sum +++ b/tools/compatibility-check/go.sum @@ -1,6 +1,7 @@ github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk= github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -14,11 +15,10 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.14 h1:QRqdp6bb9M9S5yyKeYteXKuoKE4p0tGlra81fKOpWH8= github.com/klauspost/cpuid/v2 v2.0.14/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= @@ -26,20 +26,20 @@ github.com/onflow/atree v0.4.0 h1:+TbNisavAkukAKhgQ4plWnvR9o5+SkwPIsi3jaeAqKs= github.com/onflow/atree v0.4.0/go.mod h1:7Qe1xaW0YewvouLXrugzMFUYXNoRQ8MT/UsVAWx1Ndo= github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121 h1:pOJOFoX1fEwoXyzhU9Q8VtGUlZUnMCj4LcuOJdBnLgk= github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121/go.mod h1:hhktaaXlJmxnfLgH2HG0cftcUWScdfjO/CTZkzaom/g= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a h1:s7GrsqeorVkFR1vGmQ6WVL9nup0eyQCC+YVUeSQLH/Q= github.com/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.3 h1:dAm0YRdRQlWojc3CrCRgPBzG5f941d0zvAKu7qY4e+I= github.com/stretchr/testify v1.7.3/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -98,9 +98,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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/tools/constructorcheck/go.mod b/tools/constructorcheck/go.mod index 1a9332f039..92a60226b2 100644 --- a/tools/constructorcheck/go.mod +++ b/tools/constructorcheck/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/cadence/tools/constructorcheck -go 1.19 +go 1.20 require golang.org/x/tools v0.6.0 diff --git a/tools/golangci-lint/go.mod b/tools/golangci-lint/go.mod index 07fa12d3f7..cd92d2b227 100644 --- a/tools/golangci-lint/go.mod +++ b/tools/golangci-lint/go.mod @@ -1,6 +1,6 @@ -module github.com/filecoin-project/tools/golangci-lint +module github.com/onflow/cadence/tools/golangci-lint -go 1.19 +go 1.20 require github.com/golangci/golangci-lint v1.51.2 diff --git a/tools/maprange/go.mod b/tools/maprange/go.mod index f606575814..bc581c315e 100644 --- a/tools/maprange/go.mod +++ b/tools/maprange/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/cadence/tools/maprange -go 1.19 +go 1.20 require golang.org/x/tools v0.6.0 diff --git a/tools/unkeyed/go.mod b/tools/unkeyed/go.mod index b002306faf..bb7edb9629 100644 --- a/tools/unkeyed/go.mod +++ b/tools/unkeyed/go.mod @@ -1,6 +1,6 @@ module github.com/onflow/cadence/tools/unkeyed -go 1.19 +go 1.20 require ( golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 diff --git a/tools/update/config.yaml b/tools/update/config.yaml index 0185413f01..42d1ed12e5 100644 --- a/tools/update/config.yaml +++ b/tools/update/config.yaml @@ -70,6 +70,7 @@ repos: - onflow/flow-go - onflow/flow-emulator - onflow/cadence-tools/lint + - onflow/cadence-tools/test - onflow/flow-cli/flowkit - repo: onflow/flow-cli diff --git a/version.go b/version.go index ab5ca8fdf7..7f8e0767df 100644 --- a/version.go +++ b/version.go @@ -21,4 +21,4 @@ package cadence -const Version = "v0.39.12" +const Version = "v0.40.0"