From 5cc310066fbd5555d3fe0e8013ca9f83446f4320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 6 Dec 2024 15:49:32 -0800 Subject: [PATCH] lazily compute fields of account type values --- interpreter/value_account.go | 45 ++---- .../value_account_accountcapabilities.go | 43 +++-- interpreter/value_account_capabilities.go | 54 ++++--- interpreter/value_account_contracts.go | 51 +++--- interpreter/value_account_inbox.go | 40 +++-- interpreter/value_account_storage.go | 152 ++++++++---------- .../value_account_storagecapabilities.go | 43 +++-- interpreter/value_authaccount_keys.go | 40 +++-- 8 files changed, 271 insertions(+), 197 deletions(-) diff --git a/interpreter/value_account.go b/interpreter/value_account.go index 998c8e98fd..23f012704f 100644 --- a/interpreter/value_account.go +++ b/interpreter/value_account.go @@ -55,44 +55,29 @@ func NewAccountValue( sema.AccountTypeAddressFieldName: address, } - var storage Value - var contracts Value - var keys Value - var inbox Value - var capabilities Value - - computeField := func(name string, inter *Interpreter, locationRange LocationRange) Value { + computeLazyStoredField := func(name string) Value { switch name { case sema.AccountTypeStorageFieldName: - if storage == nil { - storage = storageConstructor() - } - return storage + return storageConstructor() case sema.AccountTypeContractsFieldName: - if contracts == nil { - contracts = contractsConstructor() - } - return contracts + return contractsConstructor() case sema.AccountTypeKeysFieldName: - if keys == nil { - keys = keysConstructor() - } - return keys + return keysConstructor() case sema.AccountTypeInboxFieldName: - if inbox == nil { - inbox = inboxConstructor() - } - return inbox + return inboxConstructor() case sema.AccountTypeCapabilitiesFieldName: - if capabilities == nil { - capabilities = capabilitiesConstructor() - } - return capabilities + return capabilitiesConstructor() + } + + return nil + } + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { + switch name { case sema.AccountTypeBalanceFieldName: return accountBalanceGet() @@ -100,7 +85,11 @@ func NewAccountValue( return accountAvailableBalanceGet() } - return nil + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field } var str string diff --git a/interpreter/value_account_accountcapabilities.go b/interpreter/value_account_accountcapabilities.go index 81922f9ab7..b271870b6d 100644 --- a/interpreter/value_account_accountcapabilities.go +++ b/interpreter/value_account_accountcapabilities.go @@ -41,6 +41,35 @@ func NewAccountAccountCapabilitiesValue( issueWithTypeFunction BoundFunctionGenerator, ) *SimpleCompositeValue { + var accountCapabilities *SimpleCompositeValue + + fields := map[string]Value{} + + computeLazyStoredField := func(name string) Value { + switch name { + case sema.Account_AccountCapabilitiesTypeGetControllerFunctionName: + return getControllerFunction(accountCapabilities) + case sema.Account_AccountCapabilitiesTypeGetControllersFunctionName: + return getControllersFunction(accountCapabilities) + case sema.Account_AccountCapabilitiesTypeForEachControllerFunctionName: + return forEachControllerFunction(accountCapabilities) + case sema.Account_AccountCapabilitiesTypeIssueFunctionName: + return issueFunction(accountCapabilities) + case sema.Account_AccountCapabilitiesTypeIssueWithTypeFunctionName: + return issueWithTypeFunction(accountCapabilities) + } + + return nil + } + + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field + } + var str string stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { if str == "" { @@ -51,24 +80,16 @@ func NewAccountAccountCapabilitiesValue( return str } - accountCapabilities := NewSimpleCompositeValue( + accountCapabilities = NewSimpleCompositeValue( gauge, account_AccountCapabilitiesTypeID, account_AccountCapabilitiesStaticType, account_AccountCapabilitiesFieldNames, - nil, - nil, + fields, + computeField, nil, stringer, ) - accountCapabilities.Fields = map[string]Value{ - sema.Account_AccountCapabilitiesTypeGetControllerFunctionName: getControllerFunction(accountCapabilities), - sema.Account_AccountCapabilitiesTypeGetControllersFunctionName: getControllersFunction(accountCapabilities), - sema.Account_AccountCapabilitiesTypeForEachControllerFunctionName: forEachControllerFunction(accountCapabilities), - sema.Account_AccountCapabilitiesTypeIssueFunctionName: issueFunction(accountCapabilities), - sema.Account_AccountCapabilitiesTypeIssueWithTypeFunctionName: issueWithTypeFunction(accountCapabilities), - } - return accountCapabilities } diff --git a/interpreter/value_account_capabilities.go b/interpreter/value_account_capabilities.go index a6ab1f55fe..2c854ff948 100644 --- a/interpreter/value_account_capabilities.go +++ b/interpreter/value_account_capabilities.go @@ -29,6 +29,10 @@ import ( var account_CapabilitiesTypeID = sema.AccountCapabilitiesType.ID() var account_CapabilitiesStaticType StaticType = PrimitiveStaticTypeAccount_Capabilities +var account_CapabilitiesFieldNames = []string{ + sema.Account_CapabilitiesTypeStorageFieldName, + sema.Account_CapabilitiesTypeAccountFieldName, +} func NewAccountCapabilitiesValue( gauge common.MemoryGauge, @@ -42,27 +46,39 @@ func NewAccountCapabilitiesValue( accountCapabilitiesConstructor func() Value, ) Value { - var storageCapabilities Value - var accountCapabilities Value + var capabilities *SimpleCompositeValue + + fields := map[string]Value{} - computeField := func(name string, inter *Interpreter, locationRange LocationRange) Value { + computeLazyStoredField := func(name string) Value { switch name { case sema.Account_CapabilitiesTypeStorageFieldName: - if storageCapabilities == nil { - storageCapabilities = storageCapabilitiesConstructor() - } - return storageCapabilities - + return storageCapabilitiesConstructor() case sema.Account_CapabilitiesTypeAccountFieldName: - if accountCapabilities == nil { - accountCapabilities = accountCapabilitiesConstructor() - } - return accountCapabilities + return accountCapabilitiesConstructor() + case sema.Account_CapabilitiesTypeGetFunctionName: + return getFunction(capabilities) + case sema.Account_CapabilitiesTypeBorrowFunctionName: + return borrowFunction(capabilities) + case sema.Account_CapabilitiesTypeExistsFunctionName: + return existsFunction(capabilities) + case sema.Account_CapabilitiesTypePublishFunctionName: + return publishFunction(capabilities) + case sema.Account_CapabilitiesTypeUnpublishFunctionName: + return unpublishFunction(capabilities) } return nil } + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field + } + var str string stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { if str == "" { @@ -73,24 +89,16 @@ func NewAccountCapabilitiesValue( return str } - capabilities := NewSimpleCompositeValue( + capabilities = NewSimpleCompositeValue( gauge, account_CapabilitiesTypeID, account_CapabilitiesStaticType, - nil, - nil, + account_CapabilitiesFieldNames, + fields, computeField, nil, stringer, ) - capabilities.Fields = map[string]Value{ - sema.Account_CapabilitiesTypeGetFunctionName: getFunction(capabilities), - sema.Account_CapabilitiesTypeBorrowFunctionName: borrowFunction(capabilities), - sema.Account_CapabilitiesTypeExistsFunctionName: existsFunction(capabilities), - sema.Account_CapabilitiesTypePublishFunctionName: publishFunction(capabilities), - sema.Account_CapabilitiesTypeUnpublishFunctionName: unpublishFunction(capabilities), - } - return capabilities } diff --git a/interpreter/value_account_contracts.go b/interpreter/value_account_contracts.go index 83ae25552a..9b10a89e34 100644 --- a/interpreter/value_account_contracts.go +++ b/interpreter/value_account_contracts.go @@ -45,18 +45,42 @@ func NewAccountContractsValue( namesGetter ContractNamesGetter, ) Value { - computeField := func( - name string, - interpreter *Interpreter, - locationRange LocationRange, - ) Value { + var accountContracts *SimpleCompositeValue + + fields := map[string]Value{} + + computeLazyStoredField := func(name string) Value { switch name { - case sema.Account_ContractsTypeNamesFieldName: - return namesGetter(interpreter, locationRange) + case sema.Account_ContractsTypeAddFunctionName: + return addFunction(accountContracts) + case sema.Account_ContractsTypeGetFunctionName: + return getFunction(accountContracts) + case sema.Account_ContractsTypeBorrowFunctionName: + return borrowFunction(accountContracts) + case sema.Account_ContractsTypeRemoveFunctionName: + return removeFunction(accountContracts) + case sema.Account_ContractsTypeUpdateFunctionName: + return updateFunction(accountContracts) + case sema.Account_ContractsTypeTryUpdateFunctionName: + return tryUpdateFunction(accountContracts) } + return nil } + computeField := func(name string, inter *Interpreter, locationRange LocationRange) Value { + switch name { + case sema.Account_ContractsTypeNamesFieldName: + return namesGetter(inter, locationRange) + } + + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field + } + var str string stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { if str == "" { @@ -67,25 +91,16 @@ func NewAccountContractsValue( return str } - accountContracts := NewSimpleCompositeValue( + accountContracts = NewSimpleCompositeValue( gauge, account_ContractsTypeID, account_ContractsStaticType, account_ContractsFieldNames, - nil, + fields, computeField, nil, stringer, ) - accountContracts.Fields = map[string]Value{ - sema.Account_ContractsTypeAddFunctionName: addFunction(accountContracts), - sema.Account_ContractsTypeGetFunctionName: getFunction(accountContracts), - sema.Account_ContractsTypeBorrowFunctionName: borrowFunction(accountContracts), - sema.Account_ContractsTypeRemoveFunctionName: removeFunction(accountContracts), - sema.Account_ContractsTypeUpdateFunctionName: updateFunction(accountContracts), - sema.Account_ContractsTypeTryUpdateFunctionName: tryUpdateFunction(accountContracts), - } - return accountContracts } diff --git a/interpreter/value_account_inbox.go b/interpreter/value_account_inbox.go index 9681ddb331..1a926aa55c 100644 --- a/interpreter/value_account_inbox.go +++ b/interpreter/value_account_inbox.go @@ -29,6 +29,7 @@ import ( var account_InboxTypeID = sema.Account_InboxType.ID() var account_InboxStaticType StaticType = PrimitiveStaticTypeAccount_Inbox +var account_InboxFieldNames []string = nil // NewAccountInboxValue constructs an Account.Inbox value. func NewAccountInboxValue( @@ -39,6 +40,31 @@ func NewAccountInboxValue( claimFunction BoundFunctionGenerator, ) Value { + var accountInbox *SimpleCompositeValue + + fields := map[string]Value{} + + computeLazyStoredField := func(name string) Value { + switch name { + case sema.Account_InboxTypePublishFunctionName: + return publishFunction(accountInbox) + case sema.Account_InboxTypeUnpublishFunctionName: + return unpublishFunction(accountInbox) + case sema.Account_InboxTypeClaimFunctionName: + return claimFunction(accountInbox) + } + + return nil + } + + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field + } + var str string stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { if str == "" { @@ -49,22 +75,16 @@ func NewAccountInboxValue( return str } - accountInbox := NewSimpleCompositeValue( + accountInbox = NewSimpleCompositeValue( gauge, account_InboxTypeID, account_InboxStaticType, - nil, - nil, - nil, + account_InboxFieldNames, + fields, + computeField, nil, stringer, ) - accountInbox.Fields = map[string]Value{ - sema.Account_InboxTypePublishFunctionName: publishFunction(accountInbox), - sema.Account_InboxTypeUnpublishFunctionName: unpublishFunction(accountInbox), - sema.Account_InboxTypeClaimFunctionName: claimFunction(accountInbox), - } - return accountInbox } diff --git a/interpreter/value_account_storage.go b/interpreter/value_account_storage.go index 0531b5f67a..80fd60c908 100644 --- a/interpreter/value_account_storage.go +++ b/interpreter/value_account_storage.go @@ -29,6 +29,7 @@ import ( var account_StorageTypeID = sema.Account_StorageType.ID() var account_StorageStaticType StaticType = PrimitiveStaticTypeAccount_Storage +var account_StorageFieldNames []string = nil // NewAccountStorageValue constructs an Account.Storage value. func NewAccountStorageValue( @@ -38,113 +39,94 @@ func NewAccountStorageValue( storageCapacityGet func(interpreter *Interpreter) UInt64Value, ) Value { - var str string - stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { - if str == "" { - common.UseMemory(interpreter, common.AccountStorageStringMemoryUsage) - addressStr := address.MeteredString(interpreter, seenReferences, locationRange) - str = fmt.Sprintf("Account.Storage(%s)", addressStr) - } - return str - } + var storageValue *SimpleCompositeValue - storageValue := NewSimpleCompositeValue( - gauge, - account_StorageTypeID, - account_StorageStaticType, - nil, - nil, - nil, - nil, - stringer, - ) - - var forEachStoredFunction FunctionValue - var forEachPublicFunction FunctionValue - var typeFunction FunctionValue - var loadFunction FunctionValue - var copyFunction FunctionValue - var saveFunction FunctionValue - var borrowFunction FunctionValue - var checkFunction FunctionValue + fields := map[string]Value{} - storageValue.ComputeField = func(name string, inter *Interpreter, locationRange LocationRange) Value { + computeLazyStoredField := func(name string, inter *Interpreter) Value { switch name { - case sema.Account_StorageTypePublicPathsFieldName: - return inter.publicAccountPaths(address, locationRange) - - case sema.Account_StorageTypeStoragePathsFieldName: - return inter.storageAccountPaths(address, locationRange) - case sema.Account_StorageTypeForEachPublicFunctionName: - if forEachPublicFunction == nil { - forEachPublicFunction = inter.newStorageIterationFunction( - storageValue, - sema.Account_StorageTypeForEachPublicFunctionType, - address, - common.PathDomainPublic, - sema.PublicPathType, - ) - } - return forEachPublicFunction + return inter.newStorageIterationFunction( + storageValue, + sema.Account_StorageTypeForEachPublicFunctionType, + address, + common.PathDomainPublic, + sema.PublicPathType, + ) case sema.Account_StorageTypeForEachStoredFunctionName: - if forEachStoredFunction == nil { - forEachStoredFunction = inter.newStorageIterationFunction( - storageValue, - sema.Account_StorageTypeForEachStoredFunctionType, - address, - common.PathDomainStorage, - sema.StoragePathType, - ) - } - return forEachStoredFunction - - case sema.Account_StorageTypeUsedFieldName: - return storageUsedGet(inter) - - case sema.Account_StorageTypeCapacityFieldName: - return storageCapacityGet(inter) + return inter.newStorageIterationFunction( + storageValue, + sema.Account_StorageTypeForEachStoredFunctionType, + address, + common.PathDomainStorage, + sema.StoragePathType, + ) case sema.Account_StorageTypeTypeFunctionName: - if typeFunction == nil { - typeFunction = inter.authAccountTypeFunction(storageValue, address) - } - return typeFunction + return inter.authAccountTypeFunction(storageValue, address) case sema.Account_StorageTypeLoadFunctionName: - if loadFunction == nil { - loadFunction = inter.authAccountLoadFunction(storageValue, address) - } - return loadFunction + return inter.authAccountLoadFunction(storageValue, address) case sema.Account_StorageTypeCopyFunctionName: - if copyFunction == nil { - copyFunction = inter.authAccountCopyFunction(storageValue, address) - } - return copyFunction + return inter.authAccountCopyFunction(storageValue, address) case sema.Account_StorageTypeSaveFunctionName: - if saveFunction == nil { - saveFunction = inter.authAccountSaveFunction(storageValue, address) - } - return saveFunction + return inter.authAccountSaveFunction(storageValue, address) case sema.Account_StorageTypeBorrowFunctionName: - if borrowFunction == nil { - borrowFunction = inter.authAccountBorrowFunction(storageValue, address) - } - return borrowFunction + return inter.authAccountBorrowFunction(storageValue, address) case sema.Account_StorageTypeCheckFunctionName: - if checkFunction == nil { - checkFunction = inter.authAccountCheckFunction(storageValue, address) - } - return checkFunction + return inter.authAccountCheckFunction(storageValue, address) } return nil } + computeField := func(name string, inter *Interpreter, locationRange LocationRange) Value { + switch name { + case sema.Account_StorageTypePublicPathsFieldName: + return inter.publicAccountPaths(address, locationRange) + + case sema.Account_StorageTypeStoragePathsFieldName: + return inter.storageAccountPaths(address, locationRange) + + case sema.Account_StorageTypeUsedFieldName: + return storageUsedGet(inter) + + case sema.Account_StorageTypeCapacityFieldName: + return storageCapacityGet(inter) + } + + field := computeLazyStoredField(name, inter) + if field != nil { + fields[name] = field + } + return field + } + + var str string + stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { + if str == "" { + common.UseMemory(interpreter, common.AccountStorageStringMemoryUsage) + addressStr := address.MeteredString(interpreter, seenReferences, locationRange) + str = fmt.Sprintf("Account.Storage(%s)", addressStr) + } + return str + } + + storageValue = NewSimpleCompositeValue( + gauge, + account_StorageTypeID, + account_StorageStaticType, + account_StorageFieldNames, + fields, + computeField, + nil, + stringer, + ) + return storageValue } diff --git a/interpreter/value_account_storagecapabilities.go b/interpreter/value_account_storagecapabilities.go index a75b549903..4ad6cf1ce7 100644 --- a/interpreter/value_account_storagecapabilities.go +++ b/interpreter/value_account_storagecapabilities.go @@ -41,6 +41,35 @@ func NewAccountStorageCapabilitiesValue( issueWithTypeFunction BoundFunctionGenerator, ) Value { + var storageCapabilities *SimpleCompositeValue + + fields := map[string]Value{} + + computeLazyStoredField := func(name string) Value { + switch name { + case sema.Account_StorageCapabilitiesTypeGetControllerFunctionName: + return getControllerFunction(storageCapabilities) + case sema.Account_StorageCapabilitiesTypeGetControllersFunctionName: + return getControllersFunction(storageCapabilities) + case sema.Account_StorageCapabilitiesTypeForEachControllerFunctionName: + return forEachControllerFunction(storageCapabilities) + case sema.Account_StorageCapabilitiesTypeIssueFunctionName: + return issueFunction(storageCapabilities) + case sema.Account_StorageCapabilitiesTypeIssueWithTypeFunctionName: + return issueWithTypeFunction(storageCapabilities) + } + + return nil + } + + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field + } + var str string stringer := func(interpreter *Interpreter, seenReferences SeenReferences, locationRange LocationRange) string { if str == "" { @@ -51,24 +80,16 @@ func NewAccountStorageCapabilitiesValue( return str } - storageCapabilities := NewSimpleCompositeValue( + storageCapabilities = NewSimpleCompositeValue( gauge, account_StorageCapabilitiesTypeID, account_StorageCapabilitiesStaticType, account_StorageCapabilitiesFieldNames, - nil, - nil, + fields, + computeField, nil, stringer, ) - storageCapabilities.Fields = map[string]Value{ - sema.Account_StorageCapabilitiesTypeGetControllerFunctionName: getControllerFunction(storageCapabilities), - sema.Account_StorageCapabilitiesTypeGetControllersFunctionName: getControllersFunction(storageCapabilities), - sema.Account_StorageCapabilitiesTypeForEachControllerFunctionName: forEachControllerFunction(storageCapabilities), - sema.Account_StorageCapabilitiesTypeIssueFunctionName: issueFunction(storageCapabilities), - sema.Account_StorageCapabilitiesTypeIssueWithTypeFunctionName: issueWithTypeFunction(storageCapabilities), - } - return storageCapabilities } diff --git a/interpreter/value_authaccount_keys.go b/interpreter/value_authaccount_keys.go index ef7e47ab0b..39085cf685 100644 --- a/interpreter/value_authaccount_keys.go +++ b/interpreter/value_authaccount_keys.go @@ -29,6 +29,7 @@ import ( var account_KeysTypeID = sema.Account_KeysType.ID() var account_KeysStaticType StaticType = PrimitiveStaticTypeAccount_Keys +var account_KeysFieldNames []string = nil // NewAccountKeysValue constructs an Account.Keys value. func NewAccountKeysValue( @@ -41,12 +42,36 @@ func NewAccountKeysValue( getKeysCount AccountKeysCountGetter, ) Value { + var accountKeys *SimpleCompositeValue + + fields := map[string]Value{} + + computeLazyStoredField := func(name string) Value { + switch name { + case sema.Account_KeysTypeAddFunctionName: + return addFunction(accountKeys) + case sema.Account_KeysTypeGetFunctionName: + return getFunction(accountKeys) + case sema.Account_KeysTypeRevokeFunctionName: + return revokeFunction(accountKeys) + case sema.Account_KeysTypeForEachFunctionName: + return forEachFunction(accountKeys) + } + + return nil + } + computeField := func(name string, _ *Interpreter, _ LocationRange) Value { switch name { case sema.Account_KeysTypeCountFieldName: return getKeysCount() } - return nil + + field := computeLazyStoredField(name) + if field != nil { + fields[name] = field + } + return field } var str string @@ -59,24 +84,17 @@ func NewAccountKeysValue( return str } - accountKeys := NewSimpleCompositeValue( + accountKeys = NewSimpleCompositeValue( gauge, account_KeysTypeID, account_KeysStaticType, - nil, - nil, + account_KeysFieldNames, + fields, computeField, nil, stringer, ) - accountKeys.Fields = map[string]Value{ - sema.Account_KeysTypeAddFunctionName: addFunction(accountKeys), - sema.Account_KeysTypeGetFunctionName: getFunction(accountKeys), - sema.Account_KeysTypeRevokeFunctionName: revokeFunction(accountKeys), - sema.Account_KeysTypeForEachFunctionName: forEachFunction(accountKeys), - } - return accountKeys }