Skip to content

Commit

Permalink
Skeleton implementation of Range with constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdrag00nv2 committed Jun 9, 2023
1 parent f2aa9b5 commit b595d86
Show file tree
Hide file tree
Showing 19 changed files with 952 additions and 155 deletions.
3 changes: 3 additions & 0 deletions runtime/common/memorykind.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const (
MemoryKindVariableSizedStaticType
MemoryKindConstantSizedStaticType
MemoryKindDictionaryStaticType
MemoryKindRangeStaticType
MemoryKindOptionalStaticType
MemoryKindRestrictedStaticType
MemoryKindReferenceStaticType
Expand All @@ -90,6 +91,7 @@ const (
MemoryKindCadenceArrayValueBase
MemoryKindCadenceArrayValueLength
MemoryKindCadenceDictionaryValue
MemoryKindCadenceRangeValue
MemoryKindCadenceKeyValuePair
MemoryKindCadenceStructValueBase
MemoryKindCadenceStructValueSize
Expand All @@ -116,6 +118,7 @@ const (
MemoryKindCadenceVariableSizedArrayType
MemoryKindCadenceConstantSizedArrayType
MemoryKindCadenceDictionaryType
MemoryKindCadenceRangeType
MemoryKindCadenceField
MemoryKindCadenceParameter
MemoryKindCadenceTypeParameter
Expand Down
311 changes: 157 additions & 154 deletions runtime/common/memorykind_string.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions runtime/common/metering.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ var (
VariableSizedStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindVariableSizedStaticType)
ConstantSizedStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindConstantSizedStaticType)
DictionaryStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindDictionaryStaticType)
RangeStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindRangeStaticType)
OptionalStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindOptionalStaticType)
RestrictedStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindRestrictedStaticType)
ReferenceStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindReferenceStaticType)
Expand All @@ -191,6 +192,7 @@ var (
// Cadence external values

CadenceDictionaryValueMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceDictionaryValue)
CadenceRangeValueMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceRangeValue)
CadenceArrayValueBaseMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceArrayValueBase)
CadenceStructValueBaseMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceStructValueBase)
CadenceResourceValueBaseMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceResourceValueBase)
Expand Down Expand Up @@ -219,6 +221,7 @@ var (
CadenceContractInterfaceTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceContractInterfaceType)
CadenceContractTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceContractType)
CadenceDictionaryTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceDictionaryType)
CadenceRangeTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceRangeType)
CadenceEnumTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceEnumType)
CadenceEventTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceEventType)
CadenceFunctionTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCadenceFunctionType)
Expand Down Expand Up @@ -266,6 +269,7 @@ var (

VariableSizedStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(2) // []
DictionaryStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(4) // {: }
RangeStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(7) // Range<>
OptionalStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(1) // ?
AuthReferenceStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(5) // auth&
ReferenceStaticTypeStringMemoryUsage = NewRawStringMemoryUsage(1) // &
Expand Down
27 changes: 27 additions & 0 deletions runtime/format/range.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 format

import (
"fmt"
)

func Range(start, endInclusive string) string {
return fmt.Sprintf("Range{ start: %s, endInclusive: %s }", start, endInclusive)
}
20 changes: 20 additions & 0 deletions runtime/interpreter/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ const (
CBORTagVariableSizedStaticType
CBORTagConstantSizedStaticType
CBORTagDictionaryStaticType
CBORTagRangeStaticType
CBORTagOptionalStaticType
CBORTagReferenceStaticType
CBORTagRestrictedStaticType
Expand Down Expand Up @@ -1496,6 +1497,25 @@ func (t DictionaryStaticType) Encode(e *cbor.StreamEncoder) error {
return t.ValueType.Encode(e)
}

// Encode encodes RangeStaticType as
//
// cbor.Tag{
// Number: CBORTagRangeStaticType,
// Content: StaticType(v.Type),
// }
func (t RangeStaticType) Encode(e *cbor.StreamEncoder) error {
// Encode tag number and array head
err := e.EncodeRawBytes([]byte{
// tag number
0xd8, CBORTagRangeStaticType,
})
if err != nil {
return err
}

return t.ElementType.Encode(e)
}

// NOTE: NEVER change, only add/increment; ensure uint64
const (
// encodedRestrictedStaticTypeTypeFieldKey uint64 = 0
Expand Down
33 changes: 33 additions & 0 deletions runtime/interpreter/interpreter_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,39 @@ func (interpreter *Interpreter) testComparison(left, right Value, expression *as
}
}

func (interpreter *Interpreter) createRange(left, right IntegerValue, expression *ast.BinaryExpression) *RangeValue {
locationRange := LocationRange{
Location: interpreter.Location,
HasPosition: expression,
}

leftComparable, leftOk := left.(ComparableValue)
rightComparable, rightOk := right.(ComparableValue)

if !leftOk || !rightOk {
panic(errors.NewUnreachableError())
}

leftStaticType := left.StaticType(interpreter)
rightStaticType := right.StaticType(interpreter)
if leftStaticType != rightStaticType {
// Checker would only allow same type on both sides of the create range expression.
panic(errors.NewUnreachableError())
}

if leftComparable.Greater(interpreter, rightComparable, locationRange) {
panic(InvalidOperandsError{
Operation: expression.Operation,
LeftType: leftStaticType,
RightType: rightStaticType,
LocationRange: locationRange,
})
}

rangeStaticType := RangeStaticType{ElementType: leftStaticType}
return NewRangeValue(interpreter, locationRange, left, right, rangeStaticType)
}

func (interpreter *Interpreter) VisitUnaryExpression(expression *ast.UnaryExpression) Value {
value := interpreter.evalExpression(expression.Expression)

Expand Down
58 changes: 58 additions & 0 deletions runtime/interpreter/statictype.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,53 @@ func (t VariableSizedStaticType) Equal(other StaticType) bool {
return t.Type.Equal(otherVariableSizedType.Type)
}

// RangeStaticType

type RangeStaticType struct {
ElementType StaticType
}

var _ StaticType = RangeStaticType{}
var _ atree.TypeInfo = RangeStaticType{}

func NewRangeStaticType(
memoryGauge common.MemoryGauge,
elementType StaticType,
) RangeStaticType {
common.UseMemory(memoryGauge, common.RangeStaticTypeMemoryUsage)

return RangeStaticType{
ElementType: elementType,
}
}

func (RangeStaticType) isStaticType() {}

func (RangeStaticType) elementSize() uint {
return UnknownElementSize
}

func (t RangeStaticType) String() string {
return fmt.Sprintf("Range<%s>", t.ElementType)
}

func (t RangeStaticType) MeteredString(memoryGauge common.MemoryGauge) string {
common.UseMemory(memoryGauge, common.RangeStaticTypeStringMemoryUsage)

elementStr := t.ElementType.MeteredString(memoryGauge)

return fmt.Sprintf("Range<%s>", elementStr)
}

func (t RangeStaticType) Equal(other StaticType) bool {
otherRangeType, ok := other.(RangeStaticType)
if !ok {
return false
}

return t.ElementType.Equal(otherRangeType.ElementType)
}

// ConstantSizedStaticType

type ConstantSizedStaticType struct {
Expand Down Expand Up @@ -769,6 +816,17 @@ func ConvertStaticToSemaType(
valueType,
), nil

case RangeStaticType:
elementType, err := ConvertStaticToSemaType(memoryGauge, t.ElementType, getInterface, getComposite)
if err != nil {
return nil, err
}

return sema.NewRangeType(
memoryGauge,
elementType,
), nil

case OptionalStaticType:
ty, err := ConvertStaticToSemaType(memoryGauge, t.Type, getInterface, getComposite)
if err != nil {
Expand Down
139 changes: 139 additions & 0 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -17811,6 +17811,145 @@ func (v *DictionaryValue) IsResourceKinded(interpreter *Interpreter) bool {
return *v.isResourceKinded
}

// RangeValue
type RangeValue struct {
Type RangeStaticType
semaType *sema.RangeType
start IntegerValue
endInclusive IntegerValue
}

func NewRangeValue(
interpreter *Interpreter,
locationRange LocationRange,
start IntegerValue,
endInclusive IntegerValue,
rangeType RangeStaticType,
) *RangeValue {
return &RangeValue{
start: start,
endInclusive: endInclusive,
Type: rangeType,
}
}

var _ Value = &RangeValue{}
var _ atree.Storable = &RangeValue{}
var _ EquatableValue = &RangeValue{}
var _ MemberAccessibleValue = &RangeValue{}

func (*RangeValue) isValue() {}

func (v *RangeValue) Accept(interpreter *Interpreter, visitor Visitor) {
descend := visitor.VisitRangeValue(interpreter, v)
if !descend {
return
}

v.Walk(interpreter, func(value Value) {
value.Accept(interpreter, visitor)
})
}

func (v *RangeValue) Walk(interpreter *Interpreter, walkChild func(Value)) {
// NO-OP
}

func (v *RangeValue) GetMember(interpreter *Interpreter, locationRange LocationRange, name string) Value {
return nil
}

func (*RangeValue) RemoveMember(_ *Interpreter, _ LocationRange, _ string) Value {
// Ranges have no removable members (fields / functions)
panic(errors.NewUnreachableError())
}

func (*RangeValue) SetMember(_ *Interpreter, _ LocationRange, _ string, _ Value) bool {
// Ranges have no settable members (fields / functions)
panic(errors.NewUnreachableError())
}

func (v *RangeValue) ConformsToStaticType(
_ *Interpreter,
_ LocationRange,
_ TypeConformanceResults,
) bool {
return true
}

func (v *RangeValue) Storable(_ atree.SlabStorage, _ atree.Address, _ uint64) (atree.Storable, error) {
return v, nil
}

func (*RangeValue) NeedsStoreTo(_ atree.Address) bool {
return false
}

func (*RangeValue) IsResourceKinded(_ *Interpreter) bool {
return false
}

func (v *RangeValue) Transfer(
interpreter *Interpreter,
_ LocationRange,
_ atree.Address,
remove bool,
storable atree.Storable,
) Value {
if remove {
interpreter.RemoveReferencedSlab(storable)
}
return v
}

func (v *RangeValue) Clone(_ *Interpreter) Value {
return v
}

func (*RangeValue) DeepRemove(_ *Interpreter) {
// NO-OP
}

func (v *RangeValue) ByteSize() uint32 {
return 0
}

func (v *RangeValue) StoredValue(_ atree.SlabStorage) (atree.Value, error) {
return v, nil
}

func (*RangeValue) ChildStorables() []atree.Storable {
return nil
}

func (r *RangeValue) String() string {
return r.RecursiveString(SeenReferences{})
}

func (*RangeValue) IsImportable(interpreter *Interpreter) bool {
panic("unimplemented IsImportable")
}

func (r *RangeValue) MeteredString(memoryGauge common.MemoryGauge, seenReferences SeenReferences) string {
return format.Range(r.start.String(), r.endInclusive.String())
}

func (r *RangeValue) RecursiveString(seenReferences SeenReferences) string {
return r.MeteredString(nil, seenReferences)
}

func (r *RangeValue) StaticType(interpreter *Interpreter) StaticType {
return r.Type
}

func (*RangeValue) Equal(interpreter *Interpreter, locationRange LocationRange, other Value) bool {
panic("unimplemented Equal")
}

func (*RangeValue) Encode(*atree.Encoder) error {
panic("unimplemented Encode")
}

// OptionalValue

type OptionalValue interface {
Expand Down
Loading

0 comments on commit b595d86

Please sign in to comment.