Skip to content

Commit

Permalink
Merge pull request #3570 from onflow/bastian/type-fields
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Oct 16, 2024
2 parents 8d4dea7 + d90d449 commit 4a2d406
Show file tree
Hide file tree
Showing 4 changed files with 479 additions and 0 deletions.
82 changes: 82 additions & 0 deletions runtime/interpreter/value_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
package interpreter

import (
"strings"

"github.com/onflow/atree"

"github.com/onflow/cadence/runtime/common"
Expand Down Expand Up @@ -172,6 +174,86 @@ func (v TypeValue) GetMember(interpreter *Interpreter, _ LocationRange, name str
}

return AsBoolValue(elaboration.IsRecovered)

case sema.MetaTypeAddressFieldName:
staticType := v.Type
if staticType == nil {
return Nil
}

var location common.Location

switch staticType := staticType.(type) {
case *CompositeStaticType:
location = staticType.Location

case *InterfaceStaticType:
location = staticType.Location

default:
return Nil
}

addressLocation, ok := location.(common.AddressLocation)
if !ok {
return Nil
}

addressValue := NewAddressValue(
interpreter,
addressLocation.Address,
)
return NewSomeValueNonCopying(
interpreter,
addressValue,
)

case sema.MetaTypeContractNameFieldName:
staticType := v.Type
if staticType == nil {
return Nil
}

var location common.Location
var qualifiedIdentifier string

switch staticType := staticType.(type) {
case *CompositeStaticType:
location = staticType.Location
qualifiedIdentifier = staticType.QualifiedIdentifier

case *InterfaceStaticType:
location = staticType.Location
qualifiedIdentifier = staticType.QualifiedIdentifier

default:
return Nil
}

switch location.(type) {
case common.AddressLocation,
common.StringLocation:

separatorIndex := strings.Index(qualifiedIdentifier, ".")
contractNameLength := len(qualifiedIdentifier)
if separatorIndex >= 0 {
contractNameLength = separatorIndex
}

contractNameValue := NewStringValue(
interpreter,
common.NewStringMemoryUsage(contractNameLength),
func() string {
return qualifiedIdentifier[0:contractNameLength]
},
)

return NewSomeValueNonCopying(interpreter, contractNameValue)

default:
return Nil
}

}

return nil
Expand Down
32 changes: 32 additions & 0 deletions runtime/sema/meta_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@ const metaTypeIsRecoveredFieldDocString = `
The type was defined through a recovered program
`

const MetaTypeAddressFieldName = "address"

var MetaTypeAddressFieldType = &OptionalType{
Type: TheAddressType,
}

const metaTypeAddressFieldDocString = `
The address of the type, if it was declared in a contract deployed to an account
`

const MetaTypeContractNameFieldName = "contractName"

var MetaTypeContractNameFieldType = &OptionalType{
Type: StringType,
}

const metaTypeContractNameFieldDocString = `
The contract name of the type, if it was declared in a contract
`

func init() {
MetaType.Members = func(t *SimpleType) map[string]MemberResolver {
return MembersAsResolvers([]*Member{
Expand All @@ -90,6 +110,18 @@ func init() {
MetaTypeIsRecoveredFieldType,
metaTypeIsRecoveredFieldDocString,
),
NewUnmeteredPublicConstantFieldMember(
t,
MetaTypeAddressFieldName,
MetaTypeAddressFieldType,
metaTypeAddressFieldDocString,
),
NewUnmeteredPublicConstantFieldMember(
t,
MetaTypeContractNameFieldName,
MetaTypeContractNameFieldType,
metaTypeContractNameFieldDocString,
),
})
}
}
21 changes: 21 additions & 0 deletions runtime/tests/checker/metatype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,27 @@ func TestCheckMetaTypeIsRecovered(t *testing.T) {
let type: Type = Type<Int>()
let isRecovered: Bool = type.isRecovered
`)
require.NoError(t, err)
}

func TestCheckMetaTypeAddress(t *testing.T) {

t.Parallel()

_, err := ParseAndCheck(t, `
let type: Type = Type<Int>()
let address: Address = type.address!
`)
require.NoError(t, err)
}

func TestCheckMetaTypeContractName(t *testing.T) {

t.Parallel()

_, err := ParseAndCheck(t, `
let type: Type = Type<Int>()
let contractName: String = type.contractName!
`)
require.NoError(t, err)
}
Loading

0 comments on commit 4a2d406

Please sign in to comment.