Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple interpreter values from interpreter #3698

Merged
merged 9 commits into from
Feb 12, 2025
2 changes: 1 addition & 1 deletion cmd/decode-state-values/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ func loadStorageKey(

if composite, ok := v.(*interpreter.CompositeValue); ok &&
composite.Kind == common.CompositeKindResource &&
composite.ResourceUUID(inter, interpreter.EmptyLocationRange) == nil {
composite.ResourceUUID(inter) == nil {

log.Printf(
"Failed to get UUID for resource @ 0x%x %s",
Expand Down
14 changes: 7 additions & 7 deletions interpreter/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ func TestInterpretAccountStorageLoad(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue := value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.CompositeValue{}, innerValue)

Expand Down Expand Up @@ -790,7 +790,7 @@ func TestInterpretAccountStorageLoad(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue := value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.CompositeValue{}, innerValue)

Expand Down Expand Up @@ -872,7 +872,7 @@ func TestInterpretAccountStorageCopy(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue := value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.CompositeValue{}, innerValue)

Expand Down Expand Up @@ -1005,7 +1005,7 @@ func TestInterpretAccountStorageBorrow(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue := value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.StorageReferenceValue{}, innerValue)

Expand Down Expand Up @@ -1044,7 +1044,7 @@ func TestInterpretAccountStorageBorrow(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue = value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue = value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.StorageReferenceValue{}, innerValue)

Expand Down Expand Up @@ -1183,7 +1183,7 @@ func TestInterpretAccountStorageBorrow(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue := value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.StorageReferenceValue{}, innerValue)

Expand Down Expand Up @@ -1222,7 +1222,7 @@ func TestInterpretAccountStorageBorrow(t *testing.T) {

require.IsType(t, &interpreter.SomeValue{}, value)

innerValue = value.(*interpreter.SomeValue).InnerValue(inter, interpreter.EmptyLocationRange)
innerValue = value.(*interpreter.SomeValue).InnerValue()

assert.IsType(t, &interpreter.StorageReferenceValue{}, innerValue)

Expand Down
4 changes: 2 additions & 2 deletions interpreter/attachments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1517,8 +1517,8 @@ func TestInterpretAttachmentDestructor(t *testing.T) {

require.Len(t, events, 2)
require.Equal(t, "A.ResourceDestroyed", events[0].QualifiedIdentifier)
require.Equal(t, interpreter.NewUnmeteredStringValue("foo"), events[0].GetField(inter, interpreter.EmptyLocationRange, "foo"))
require.Equal(t, interpreter.NewIntValueFromInt64(nil, 2), events[0].GetField(inter, interpreter.EmptyLocationRange, "bar"))
require.Equal(t, interpreter.NewUnmeteredStringValue("foo"), events[0].GetField(inter, "foo"))
require.Equal(t, interpreter.NewIntValueFromInt64(nil, 2), events[0].GetField(inter, "bar"))
require.Equal(t, "R.ResourceDestroyed", events[1].QualifiedIdentifier)
})
}
Expand Down
2 changes: 1 addition & 1 deletion interpreter/builtinfunctions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func TestInterpretAddressFromString(t *testing.T) {
addressOpt, ok := res.(*interpreter.SomeValue)
require.True(t, ok)

innerValue := addressOpt.InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := addressOpt.InnerValue()
addressVal, ok := innerValue.(interpreter.AddressValue)
require.True(t, ok)
require.Equal(t, expected, addressVal.ToAddress().HexWithPrefix())
Expand Down
23 changes: 8 additions & 15 deletions interpreter/dynamic_casting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,7 @@ func TestInterpretDynamicCastingStruct(t *testing.T) {

require.IsType(t,
&interpreter.CompositeValue{},
inter.Globals.Get("y").GetValue(inter).(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
inter.Globals.Get("y").GetValue(inter).(*interpreter.SomeValue).InnerValue(),
)
})
}
Expand Down Expand Up @@ -757,8 +756,7 @@ func testResourceCastValid(t *testing.T, types, fromType string, targetType stri

require.IsType(t,
&interpreter.CompositeValue{},
value.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
value.(*interpreter.SomeValue).InnerValue(),
)

case ast.OperationForceCast:
Expand Down Expand Up @@ -903,8 +901,7 @@ func testStructCastValid(t *testing.T, types, fromType string, targetType string

require.IsType(t,
&interpreter.CompositeValue{},
value.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
value.(*interpreter.SomeValue).InnerValue(),
)

case ast.OperationForceCast:
Expand Down Expand Up @@ -1214,7 +1211,7 @@ func TestInterpretDynamicCastingArray(t *testing.T) {
require.IsType(t, zValue, &interpreter.SomeValue{})
zSome := zValue.(*interpreter.SomeValue)

innerValue := zSome.InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := zSome.InnerValue()
require.IsType(t, innerValue, &interpreter.ArrayValue{})
innerArray := innerValue.(*interpreter.ArrayValue)

Expand Down Expand Up @@ -2279,8 +2276,7 @@ func testReferenceCastValid(t *testing.T, types, fromType, targetType string, op

require.IsType(t,
&interpreter.EphemeralReferenceValue{},
value.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
value.(*interpreter.SomeValue).InnerValue(),
)

case ast.OperationForceCast:
Expand Down Expand Up @@ -4108,8 +4104,7 @@ func TestInterpretDynamicCastingOptionalUnwrapping(t *testing.T) {

require.IsType(t,
&interpreter.CompositeValue{},
value.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
value.(*interpreter.SomeValue).InnerValue(),
)
})

Expand Down Expand Up @@ -4164,8 +4159,7 @@ func TestInterpretDynamicCastingOptionalUnwrapping(t *testing.T) {

require.IsType(t,
&interpreter.CompositeValue{},
result.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
result.(*interpreter.SomeValue).InnerValue(),
)

})
Expand Down Expand Up @@ -4201,8 +4195,7 @@ func TestInterpretDynamicCastingOptionalUnwrapping(t *testing.T) {

require.IsType(t,
&interpreter.CompositeValue{},
result.(*interpreter.SomeValue).
InnerValue(inter, interpreter.EmptyLocationRange),
result.(*interpreter.SomeValue).InnerValue(),
)

})
Expand Down
2 changes: 1 addition & 1 deletion interpreter/enum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ func TestInterpretEnumInContract(t *testing.T) {
require.IsType(t, &interpreter.CompositeValue{}, c)
contract := c.(*interpreter.CompositeValue)

eValue := contract.GetField(inter, interpreter.EmptyLocationRange, "e")
eValue := contract.GetField(inter, "e")
require.NotNil(t, eValue)

require.IsType(t, &interpreter.CompositeValue{}, eValue)
Expand Down
10 changes: 5 additions & 5 deletions interpreter/function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestInterpretResultVariable(t *testing.T) {
t,
inter,
interpreter.UInt8Value(1),
resource.GetField(inter, interpreter.EmptyLocationRange, "id"),
resource.GetField(inter, "id"),
)
})

Expand Down Expand Up @@ -93,7 +93,7 @@ func TestInterpretResultVariable(t *testing.T) {
require.IsType(t, &interpreter.SomeValue{}, result)
someValue := result.(*interpreter.SomeValue)

innerValue := someValue.InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := someValue.InnerValue()
require.IsType(t, &interpreter.CompositeValue{}, innerValue)

resource := innerValue.(*interpreter.CompositeValue)
Expand All @@ -102,7 +102,7 @@ func TestInterpretResultVariable(t *testing.T) {
t,
inter,
interpreter.UInt8Value(1),
resource.GetField(inter, interpreter.EmptyLocationRange, "id"),
resource.GetField(inter, "id"),
)
})

Expand Down Expand Up @@ -157,7 +157,7 @@ func TestInterpretResultVariable(t *testing.T) {
require.IsType(t, &interpreter.SomeValue{}, result)
someValue := result.(*interpreter.SomeValue)

innerValue := someValue.InnerValue(inter, interpreter.EmptyLocationRange)
innerValue := someValue.InnerValue()
require.IsType(t, &interpreter.CompositeValue{}, innerValue)

resource := innerValue.(*interpreter.CompositeValue)
Expand All @@ -166,7 +166,7 @@ func TestInterpretResultVariable(t *testing.T) {
t,
inter,
interpreter.UInt8Value(1),
resource.GetField(inter, interpreter.EmptyLocationRange, "id"),
resource.GetField(inter, "id"),
)
})

Expand Down
10 changes: 6 additions & 4 deletions interpreter/hashablevalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ package interpreter

import (
"github.com/onflow/atree"

"github.com/onflow/cadence/common"
)

// HashableValue is an immutable value that can be hashed
type HashableValue interface {
Value
HashInput(interpreter *Interpreter, locationRange LocationRange, scratch []byte) []byte
HashInput(memoryGauge common.MemoryGauge, locationRange LocationRange, scratch []byte) []byte
}

func newHashInputProvider(interpreter *Interpreter, locationRange LocationRange) atree.HashInputProvider {
func newHashInputProvider(memoryGauge common.MemoryGauge, locationRange LocationRange) atree.HashInputProvider {
return func(value atree.Value, scratch []byte) ([]byte, error) {
hashInput := MustConvertStoredValue(interpreter, value).(HashableValue).
HashInput(interpreter, locationRange, scratch)
hashInput := MustConvertStoredValue(memoryGauge, value).(HashableValue).
HashInput(memoryGauge, locationRange, scratch)
return hashInput, nil
}
}
Expand Down
24 changes: 15 additions & 9 deletions interpreter/inclusive_range_iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package interpreter

import (
"github.com/onflow/cadence/common"
"github.com/onflow/cadence/errors"
"github.com/onflow/cadence/sema"
)
Expand All @@ -35,19 +36,24 @@ type InclusiveRangeIterator struct {

var _ ValueIterator = &InclusiveRangeIterator{}

type InclusiveRangeIteratorContext interface {
common.MemoryGauge
NumberValueArithmeticContext
}

func NewInclusiveRangeIterator(
interpreter *Interpreter,
context InclusiveRangeIteratorContext,
locationRange LocationRange,
v *CompositeValue,
typ InclusiveRangeStaticType,
) *InclusiveRangeIterator {
startValue := getFieldAsIntegerValue(interpreter, v, locationRange, sema.InclusiveRangeTypeStartFieldName)
startValue := getFieldAsIntegerValue(context, v, sema.InclusiveRangeTypeStartFieldName)

zeroValue := GetSmallIntegerValue(0, typ.ElementType)
endValue := getFieldAsIntegerValue(interpreter, v, locationRange, sema.InclusiveRangeTypeEndFieldName)
endValue := getFieldAsIntegerValue(context, v, sema.InclusiveRangeTypeEndFieldName)

stepValue := getFieldAsIntegerValue(interpreter, v, locationRange, sema.InclusiveRangeTypeStepFieldName)
stepNegative := stepValue.Less(interpreter, zeroValue, locationRange)
stepValue := getFieldAsIntegerValue(context, v, sema.InclusiveRangeTypeStepFieldName)
stepNegative := stepValue.Less(context, zeroValue, locationRange)

return &InclusiveRangeIterator{
rangeValue: v,
Expand All @@ -58,18 +64,18 @@ func NewInclusiveRangeIterator(
}
}

func (i *InclusiveRangeIterator) Next(interpreter *Interpreter, locationRange LocationRange) Value {
func (i *InclusiveRangeIterator) Next(context ValueIteratorContext, locationRange LocationRange) Value {
valueToReturn := i.next

// Ensure that valueToReturn is within the bounds.
if i.stepNegative && bool(valueToReturn.Less(interpreter, i.end, locationRange)) {
if i.stepNegative && bool(valueToReturn.Less(context, i.end, locationRange)) {
return nil
} else if !i.stepNegative && bool(valueToReturn.Greater(interpreter, i.end, locationRange)) {
} else if !i.stepNegative && bool(valueToReturn.Greater(context, i.end, locationRange)) {
return nil
}

// Update the next value.
nextValueToReturn, ok := valueToReturn.Plus(interpreter, i.step, locationRange).(IntegerValue)
nextValueToReturn, ok := valueToReturn.Plus(context, i.step, locationRange).(IntegerValue)
if !ok {
panic(errors.NewUnreachableError())
}
Expand Down
4 changes: 2 additions & 2 deletions interpreter/inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func TestInspectValue(t *testing.T) {
// Get actually stored values.
// The values above were removed when they were inserted into the containers.

optionalValue := compositeValue.GetField(inter, EmptyLocationRange, "value").(*SomeValue)
arrayValue := optionalValue.InnerValue(inter, EmptyLocationRange).(*ArrayValue)
optionalValue := compositeValue.GetField(inter, "value").(*SomeValue)
arrayValue := optionalValue.InnerValue().(*ArrayValue)
dictValue := arrayValue.Get(inter, EmptyLocationRange, 0).(*DictionaryValue)
dictValueKey := NewUnmeteredStringValue("hello world")

Expand Down
55 changes: 55 additions & 0 deletions interpreter/interface.go
turbolent marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright Flow Foundation
*
* 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 (
"github.com/onflow/cadence/common"
"github.com/onflow/cadence/sema"
)

type TypeConverter interface {
MustConvertStaticToSemaType(staticType StaticType) sema.Type
}

var _ TypeConverter = &Interpreter{}

type SubTypeChecker interface {
IsSubTypeOfSemaType(staticSubType StaticType, superType sema.Type) bool
}

var _ SubTypeChecker = &Interpreter{}

type StorageReader interface {
ReadStored(
storageAddress common.Address,
domain common.StorageDomain,
identifier StorageMapKey,
) Value
}

var _ StorageReader = &Interpreter{}

type ValueStaticTypeContext interface {
common.MemoryGauge
StorageReader
TypeConverter
SubTypeChecker
}

var _ ValueStaticTypeContext = &Interpreter{}
Loading
Loading