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

Introduce InclusiveRange<T: Integer> type #2523

Merged
merged 88 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 86 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
ec147bd
Introduce InclusiveRange
darkdrag00nv2 Jun 19, 2023
9517f7e
Validate that the step is always non-zero
darkdrag00nv2 Jun 19, 2023
f48199c
Validate that step takes the direction of sequence towards end
darkdrag00nv2 Jun 19, 2023
d13a39c
More tests
darkdrag00nv2 Jun 21, 2023
258e541
Add invalid case tests in checker
darkdrag00nv2 Jun 25, 2023
4fbe486
Add interpreter test cases
darkdrag00nv2 Jun 29, 2023
9458718
Use nil for location range of composite value
darkdrag00nv2 Jul 3, 2023
c962d1c
Add missing semicolon
darkdrag00nv2 Jul 3, 2023
5a01dde
Convert and assert needle value at callsite
darkdrag00nv2 Jul 3, 2023
87cdcc5
Store a lazy lookup table for IntegerValue in interpreter
darkdrag00nv2 Jul 3, 2023
ac00e1e
Format the error message for sequence moving away from end.
darkdrag00nv2 Jul 9, 2023
fc47776
Break mod operation into multiple lines.
darkdrag00nv2 Jul 9, 2023
74af213
Format NewInclusiveRangeValueWithStep call into multiple lines
darkdrag00nv2 Jul 9, 2023
18b4859
Declare and initialize result on the same line
darkdrag00nv2 Jul 9, 2023
a867b65
fix lint
darkdrag00nv2 Jul 9, 2023
e36333e
return early in contains if needle = lower/upper bound
darkdrag00nv2 Jul 9, 2023
d36a76e
remove runtime/format/range.go as it not needed
darkdrag00nv2 Jul 9, 2023
91ea40f
Add import/export support for InclusiveRange
darkdrag00nv2 Jul 21, 2023
6fd4f27
Add encoding/decoding/storage tests and fix bugs
darkdrag00nv2 Jul 25, 2023
5386f43
Add conformance checks for CompositeValue which are not CompositeType
darkdrag00nv2 Jul 25, 2023
d72ddf5
Add more tests - values, dynamic casting, ccf, json
darkdrag00nv2 Jul 27, 2023
ae29179
Make cachedIntegerValues a global value
darkdrag00nv2 Jul 27, 2023
efb0b74
Ensure that inner type is an integer in runtime type constructor
darkdrag00nv2 Jul 27, 2023
96fe558
Remove dead code for super type of InclusiveRangeType
darkdrag00nv2 Jul 27, 2023
4dac857
Take Sema type in param instead of calculating in constructor
darkdrag00nv2 Jul 27, 2023
aa36e25
Split out construction of InclusiveRange into a third-private function
darkdrag00nv2 Jul 27, 2023
6b03f03
Add more tests case for ccf encoding/decoding
darkdrag00nv2 Aug 5, 2023
b1d81fa
Remove redundant error from return type
darkdrag00nv2 Aug 12, 2023
cec3966
Return InclusiveRangeType from exportInclusiveRangeType
darkdrag00nv2 Aug 12, 2023
2c9b4a3
Update runtime/tests/checker/range_value_test.go
darkdrag00nv2 Aug 12, 2023
184189b
use []error instead of []interface{}
darkdrag00nv2 Aug 12, 2023
d981a16
Update runtime/stdlib/range.go
darkdrag00nv2 Aug 12, 2023
0a9b4f8
Update runtime/stdlib/range.go
darkdrag00nv2 Aug 12, 2023
be883f8
Update runtime/interpreter/value_range.go
darkdrag00nv2 Aug 12, 2023
8440ae7
Update runtime/interpreter/value_range.go
darkdrag00nv2 Aug 12, 2023
44d4d62
Update runtime/interpreter/value_range.go
darkdrag00nv2 Aug 12, 2023
2b31f2c
Update runtime/interpreter/value.go
darkdrag00nv2 Aug 12, 2023
e582b6c
use constructor instead of direct init; also fix compilation error
darkdrag00nv2 Aug 12, 2023
112114f
Use TypeValue instead of PathLinkValue in encoding_test
darkdrag00nv2 Aug 12, 2023
dec5f50
Extract sequence direction check to a separate function
darkdrag00nv2 Aug 12, 2023
47fc917
Predefine list of fields and use in conformance check
darkdrag00nv2 Aug 12, 2023
6fbc1a5
Use type switch for exporting InclusiveRange
darkdrag00nv2 Aug 12, 2023
1b1f450
Use type switch in conformance check
darkdrag00nv2 Aug 12, 2023
79ff403
Minor nits and add test coverage for Import InclusiveRangeType
darkdrag00nv2 Aug 13, 2023
59b0457
Infer type in importing InclusiveRange, also improve readability of c…
darkdrag00nv2 Aug 14, 2023
16ddd41
Refactor InclusiveRange import flow and add more test cases
darkdrag00nv2 Aug 20, 2023
d43a0c5
Add tests for missing failure scenario
darkdrag00nv2 Aug 20, 2023
e94c03f
Fix comment
darkdrag00nv2 Aug 25, 2023
c4c13ff
Remove comment.
darkdrag00nv2 Aug 25, 2023
ac26a8b
Use `Equal()` instead of `==` and `!=` operators
darkdrag00nv2 Aug 25, 2023
5b3d817
Extract elementType as a local variable and use.
darkdrag00nv2 Aug 25, 2023
7cca141
Compare with empty string instead of calculating length of string
darkdrag00nv2 Aug 25, 2023
bed0e37
Rename TestInclusiveRangeConstructionValid -> TestCheckInclusiveRange…
darkdrag00nv2 Aug 25, 2023
5b187d5
Rename TestInclusiveRangeConstructionInvalid -> TestCheckInclusiveRan…
darkdrag00nv2 Aug 25, 2023
257043e
Fix typo and build
darkdrag00nv2 Aug 25, 2023
1fa90d3
Use decodeCBORArrayWithKnownSize
darkdrag00nv2 Aug 25, 2023
7e5c801
Use inline type instead of CBOR array in InclusiveRange type
darkdrag00nv2 Aug 25, 2023
80e9f2e
Use stricter multiplicity annotation.
darkdrag00nv2 Aug 25, 2023
c7db732
use r.MemberType directly instead of r.ElementType function
darkdrag00nv2 Aug 25, 2023
e2a8436
Add TestGetValueForIntegerType
darkdrag00nv2 Aug 25, 2023
5de89b1
Add runtime type tests for InclusiveRangeType
darkdrag00nv2 Aug 25, 2023
f44c8a5
Fix build and tests since we have Arity support now
darkdrag00nv2 Aug 27, 2023
a4d4c96
Add runtime to load and call contains
darkdrag00nv2 Aug 27, 2023
1d54260
Handle each level of multi-level type separately.
darkdrag00nv2 Sep 6, 2023
131a163
Remove unnecessary nesting.
darkdrag00nv2 Sep 6, 2023
d169d09
Extract local variable for invocation.Interpreter
darkdrag00nv2 Sep 6, 2023
cf5edc8
Use StaticType.Equal
darkdrag00nv2 Sep 6, 2023
e47dbad
Add comment on not metering memory usage of getValueForIntegerType
darkdrag00nv2 Sep 7, 2023
5d1b13f
Move GetValueForIntegerType to a new file
darkdrag00nv2 Sep 7, 2023
bceada1
Make InclusiveRange of values.go a pointer type
darkdrag00nv2 Sep 7, 2023
1f96574
Handle MemberType as potentially nil in InclusiveRangeType
darkdrag00nv2 Sep 7, 2023
e6eeaed
Add test case for usage of InclusiveRange without inner type
darkdrag00nv2 Sep 10, 2023
5f2ddd8
Add a mutex in range_value_test.go to protect concurrent access to th…
darkdrag00nv2 Sep 10, 2023
d97eef6
Add checkParameterizedTypeIsInstantiated
darkdrag00nv2 Sep 22, 2023
7904b95
Use IsSameTypeKind
darkdrag00nv2 Sep 22, 2023
8732e3d
Add test case in TestCheckTypeArguments
darkdrag00nv2 Sep 24, 2023
34a43de
Merge branch 'feature/range-type' into range_type
turbolent Oct 3, 2023
81aed0f
fix qualified string and type ID generation
turbolent Oct 3, 2023
1af52af
improve small integer cache
turbolent Oct 3, 2023
56c8ac7
remove unnecessary assertion
turbolent Oct 3, 2023
9315a88
Separate functions for static type conformance check
darkdrag00nv2 Oct 4, 2023
dd77fb7
Add runtime test to save and load InclusiveRange in two transactions
darkdrag00nv2 Oct 4, 2023
d80f426
Revert the TestRuntimeStorageMultipleTransactionsInclusiveRangeFuncti…
darkdrag00nv2 Oct 5, 2023
10f48af
Add test case for comparing InclusiveRange
darkdrag00nv2 Oct 5, 2023
64b1b0d
Add test case for inclusive range instantiation with 2 type args
darkdrag00nv2 Oct 5, 2023
4445c56
Add test case to indicate unsupported storage of inclusive range
darkdrag00nv2 Oct 6, 2023
db22c2c
Make InclusiveRange type non-storable
darkdrag00nv2 Oct 7, 2023
1ca3adc
Remove auth account storage test for InclusiveRange
darkdrag00nv2 Oct 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
373 changes: 373 additions & 0 deletions encoding/ccf/ccf_test.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions encoding/ccf/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const (
CBORTagReferenceType
CBORTagRestrictedType
CBORTagCapabilityType
_
CBORTagInclusiveRangeType
_
_
_
Expand Down Expand Up @@ -120,7 +120,7 @@ const (
CBORTagRestrictedTypeValue
CBORTagCapabilityTypeValue
CBORTagFunctionTypeValue
_
CBORTagInclusiveRangeTypeValue // InclusiveRange is stored as a composite value.
_
_
_
Expand Down
54 changes: 54 additions & 0 deletions encoding/ccf/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ func (d *Decoder) decodeTypeAndValue(types *cadenceTypeByCCFTypeID) (cadence.Val
// / path-value
// / path-capability-value
// / id-capability-value
// / inclusiverange-value
// / function-value
// / type-value
//
Expand Down Expand Up @@ -507,6 +508,9 @@ func (d *Decoder) decodeValue(t cadence.Type, types *cadenceTypeByCCFTypeID) (ca
case *cadence.ResourceType:
return d.decodeResource(t, types)

case *cadence.InclusiveRangeType:
return d.decodeInclusiveRange(t, types)

case *cadence.StructType:
return d.decodeStruct(t, types)

Expand Down Expand Up @@ -1309,6 +1313,52 @@ func (d *Decoder) decodeEnum(typ *cadence.EnumType, types *cadenceTypeByCCFTypeI
return v.WithType(typ), nil
}

// decodeInclusiveRange decodes encoded inclusiverange-value as
// language=CDDL
// inclusiverange-value = [
//
// start: value,
// end: value,
// step: value,
//
// ]
func (d *Decoder) decodeInclusiveRange(typ *cadence.InclusiveRangeType, types *cadenceTypeByCCFTypeID) (cadence.Value, error) {
// Decode array head of length 3.
err := decodeCBORArrayWithKnownSize(d.dec, 3)
if err != nil {
return nil, err
}
darkdrag00nv2 marked this conversation as resolved.
Show resolved Hide resolved

elementType := typ.ElementType

// Decode start.
start, err := d.decodeValue(elementType, types)
if err != nil {
return nil, err
}

// Decode end.
end, err := d.decodeValue(elementType, types)
if err != nil {
return nil, err
}

// Decode step.
step, err := d.decodeValue(elementType, types)
if err != nil {
return nil, err
}

v := cadence.NewMeteredInclusiveRange(
d.gauge,
start,
end,
step,
)

return v.WithType(typ), nil
}

// decodePath decodes path-value as
// language=CDDL
// path-value = [
Expand Down Expand Up @@ -1442,6 +1492,7 @@ func (d *Decoder) decodeCapability(typ *cadence.CapabilityType, types *cadenceTy
// / varsized-array-type-value
// / constsized-array-type-value
// / dict-type-value
// / inclusiverange-type-value
// / struct-type-value
// / resource-type-value
// / contract-type-value
Expand Down Expand Up @@ -1482,6 +1533,9 @@ func (d *Decoder) decodeTypeValue(visited *cadenceTypeByCCFTypeID) (cadence.Type
case CBORTagDictTypeValue:
return d.decodeDictType(visited, d.decodeTypeValue)

case CBORTagInclusiveRangeTypeValue:
return d.decodeInclusiveRangeType(visited, d.decodeTypeValue)

case CBORTagCapabilityTypeValue:
return d.decodeCapabilityType(visited, d.decodeNullableTypeValue)

Expand Down
34 changes: 34 additions & 0 deletions encoding/ccf/decode_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
// / reference-type
// / restricted-type
// / capability-type
// / inclusiverange-type
// / type-ref
//
// All exported Cadence types needs to be handled in this function,
Expand All @@ -71,6 +72,9 @@
case CBORTagDictType:
return d.decodeDictType(types, d.decodeInlineType)

case CBORTagInclusiveRangeType:
return d.decodeInclusiveRangeType(types, d.decodeInlineType)

case CBORTagReferenceType:
return d.decodeReferenceType(types, d.decodeInlineType)

Expand Down Expand Up @@ -436,6 +440,36 @@
return cadence.NewMeteredDictionaryType(d.gauge, keyType, elementType), nil
}

// decodeInclusiveRangeType decodes inclusiverange-type or inclusiverange-type-value as
// language=CDDL
// inclusiverange-type =
//
// ; cbor-tag-inclusiverange-type
// #6.145(inline-type)
//
// inclusiverange-type-value =
//
// ; cbor-tag-inclusiverange-type-value
// #6.194(type-value)
//
// NOTE: decodeTypeFn is responsible for decoding inline-type or type-value.
func (d *Decoder) decodeInclusiveRangeType(
types *cadenceTypeByCCFTypeID,
decodeTypeFn decodeTypeFn,
) (cadence.Type, error) {
// element 0: element type (inline-type or type-value)
elementType, err := decodeTypeFn(types)
if err != nil {
return nil, err
}

if elementType == nil {
return nil, errors.New("unexpected nil type as inclusiverange element type")
}

Check warning on line 468 in encoding/ccf/decode_type.go

View check run for this annotation

Codecov / codecov/patch

encoding/ccf/decode_type.go#L467-L468

Added lines #L467 - L468 were not covered by tests
darkdrag00nv2 marked this conversation as resolved.
Show resolved Hide resolved

return cadence.NewMeteredInclusiveRangeType(d.gauge, elementType), nil
}

// decodeCapabilityType decodes capability-type or capability-type-value as
// language=CDDL
// capability-type =
Expand Down
52 changes: 52 additions & 0 deletions encoding/ccf/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@
// / path-value
// / path-capability-value
// / id-capability-value
// / inclusiverange-value
// / function-value
// / type-value
//
Expand Down Expand Up @@ -563,6 +564,9 @@
case cadence.Dictionary:
return e.encodeDictionary(v, tids)

case *cadence.InclusiveRange:
return e.encodeInclusiveRange(v, tids)

case cadence.Struct:
return e.encodeStruct(v, tids)

Expand Down Expand Up @@ -977,6 +981,34 @@
return encodedPairs, nil
}

// encodeInclusiveRange encodes cadence.InclusiveRange as
// language=CDDL
// inclusiverange-value = [3*3 (key: value, value: value)]
func (e *Encoder) encodeInclusiveRange(v *cadence.InclusiveRange, tids ccfTypeIDByCadenceType) error {
staticElementType := v.InclusiveRangeType.ElementType

// Encode array head with array size of 3.
err := e.enc.EncodeArrayHead(3)
if err != nil {
return err
}

Check warning on line 994 in encoding/ccf/encode.go

View check run for this annotation

Codecov / codecov/patch

encoding/ccf/encode.go#L993-L994

Added lines #L993 - L994 were not covered by tests

// Encode start key as value.
err = e.encodeValue(v.Start, staticElementType, tids)
if err != nil {
return err
}

Check warning on line 1000 in encoding/ccf/encode.go

View check run for this annotation

Codecov / codecov/patch

encoding/ccf/encode.go#L999-L1000

Added lines #L999 - L1000 were not covered by tests

// Encode end as value.
err = e.encodeValue(v.End, staticElementType, tids)
if err != nil {
return err
}

Check warning on line 1006 in encoding/ccf/encode.go

View check run for this annotation

Codecov / codecov/patch

encoding/ccf/encode.go#L1005-L1006

Added lines #L1005 - L1006 were not covered by tests

// Encode step key as value.
return e.encodeValue(v.Step, staticElementType, tids)
}

// encodeStruct encodes cadence.Struct as
// language=CDDL
// composite-value = [* (field: value)]
Expand Down Expand Up @@ -1232,6 +1264,7 @@
// / reference-type-value
// / restricted-type-value
// / capability-type-value
// / inclusiverange-type-value
// / type-value-ref
//
// TypeValue is used differently from inline type or type definition.
Expand Down Expand Up @@ -1282,6 +1315,9 @@
case *cadence.ContractType:
return e.encodeContractTypeValue(typ, visited)

case *cadence.InclusiveRangeType:
return e.encodeInclusiveRangeTypeValue(typ, visited)

case *cadence.StructInterfaceType:
return e.encodeStructInterfaceTypeValue(typ, visited)

Expand Down Expand Up @@ -1411,6 +1447,22 @@
)
}

// encodeInclusiveRangeTypeValue encodes cadence.InclusiveRangeType as
// language=CDDL
// inclusiverange-type-value =
//
// ; cbor-tag-inclusiverange-type-value
// #6.194(type-value)
func (e *Encoder) encodeInclusiveRangeTypeValue(typ *cadence.InclusiveRangeType, visited ccfTypeIDByCadenceType) error {
rawTagNum := []byte{0xd8, CBORTagInclusiveRangeTypeValue}
return e.encodeInclusiveRangeTypeWithRawTag(
typ,
visited,
e.encodeTypeValue,
rawTagNum,
)
}

// encodeReferenceTypeValue encodes cadence.ReferenceType as
// language=CDDL
// reference-type-value =
Expand Down
41 changes: 41 additions & 0 deletions encoding/ccf/encode_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
// / reference-type
// / restricted-type
// / capability-type
// / inclusiverange-type
// / type-ref
//
// All exported Cadence types need to be supported by this function,
Expand All @@ -62,6 +63,9 @@
case *cadence.DictionaryType:
return e.encodeDictType(typ, tids)

case *cadence.InclusiveRangeType:
return e.encodeInclusiveRangeType(typ, tids)

case cadence.CompositeType, cadence.InterfaceType:
id, err := tids.id(typ)
if err != nil {
Expand Down Expand Up @@ -296,6 +300,43 @@
return encodeTypeFn(typ.ElementType, tids)
}

// encodeInclusiveRangeType encodes cadence.InclusiveRangeType as
// language=CDDL
// inclusiverange-type =
//
// ; cbor-tag-inclusiverange-type
// #6.145(inline-type)
func (e *Encoder) encodeInclusiveRangeType(
typ *cadence.InclusiveRangeType,
tids ccfTypeIDByCadenceType,
) error {
rawTagNum := []byte{0xd8, CBORTagInclusiveRangeType}
return e.encodeInclusiveRangeTypeWithRawTag(
typ,
tids,
e.encodeInlineType,
rawTagNum,
)
}

// encodeInclusiveRangeTypeWithRawTag encodes cadence.InclusiveRangeType
// with given tag number and encode type function.
func (e *Encoder) encodeInclusiveRangeTypeWithRawTag(
typ *cadence.InclusiveRangeType,
tids ccfTypeIDByCadenceType,
encodeTypeFn encodeTypeFn,
rawTagNumber []byte,
) error {
// Encode CBOR tag number.
err := e.enc.EncodeRawBytes(rawTagNumber)
if err != nil {
return err
}

Check warning on line 334 in encoding/ccf/encode_type.go

View check run for this annotation

Codecov / codecov/patch

encoding/ccf/encode_type.go#L333-L334

Added lines #L333 - L334 were not covered by tests

// Encode element type with given encodeTypeFn
return encodeTypeFn(typ.ElementType, tids)
}

// encodeReferenceType encodes cadence.ReferenceType as
// language=CDDL
// reference-type =
Expand Down
3 changes: 2 additions & 1 deletion encoding/ccf/traverse_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ func (ct *compositeTypes) traverseType(typ cadence.Type) (checkRuntimeType bool)
cadence.IntegerType,
cadence.SignedIntegerType,
cadence.FixedPointType,
cadence.SignedFixedPointType:
cadence.SignedFixedPointType,
*cadence.InclusiveRangeType:
// TODO: Maybe there are more types that we can skip checking runtime type for composite type.

return false
Expand Down
31 changes: 31 additions & 0 deletions encoding/json/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ const (
returnKey = "return"
typeBoundKey = "typeBound"
functionTypeKey = "functionType"
elementKey = "element"
startKey = "start"
endKey = "end"
stepKey = "step"
)

func (d *Decoder) decodeJSON(v any) cadence.Value {
Expand Down Expand Up @@ -222,6 +226,8 @@ func (d *Decoder) decodeJSON(v any) cadence.Value {
return d.decodeEvent(valueJSON)
case contractTypeStr:
return d.decodeContract(valueJSON)
case inclusiveRangeTypeStr:
return d.decodeInclusiveRange(valueJSON)
case pathTypeStr:
return d.decodePath(valueJSON)
case typeTypeStr:
Expand Down Expand Up @@ -866,6 +872,26 @@ func (d *Decoder) decodeEnum(valueJSON any) cadence.Enum {
))
}

func (d *Decoder) decodeInclusiveRange(valueJSON any) *cadence.InclusiveRange {
obj := toObject(valueJSON)

start := obj.GetValue(d, startKey)
end := obj.GetValue(d, endKey)
step := obj.GetValue(d, stepKey)

value := cadence.NewMeteredInclusiveRange(
d.gauge,
start,
end,
step,
)

return value.WithType(cadence.NewMeteredInclusiveRangeType(
d.gauge,
start.Type(),
))
}

func (d *Decoder) decodePath(valueJSON any) cadence.Path {
obj := toObject(valueJSON)

Expand Down Expand Up @@ -1185,6 +1211,11 @@ func (d *Decoder) decodeType(valueJSON any, results typeDecodingResults) cadence
d.decodeType(obj.Get(keyKey), results),
d.decodeType(obj.Get(valueKey), results),
)
case "InclusiveRange":
return cadence.NewMeteredInclusiveRangeType(
d.gauge,
d.decodeType(obj.Get(elementKey), results),
)
case "ConstantSizedArray":
size := toUInt(obj.Get(sizeKey))
return cadence.NewMeteredConstantSizedArrayType(
Expand Down
Loading
Loading