Skip to content

Commit

Permalink
add Type.address
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Oct 15, 2024
1 parent 075bfc7 commit 32e6467
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 0 deletions.
25 changes: 25 additions & 0 deletions runtime/interpreter/value_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,31 @@ func (v TypeValue) GetMember(interpreter *Interpreter, _ LocationRange, name str
}

return AsBoolValue(elaboration.IsRecovered)

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

location, _, err := common.DecodeTypeID(interpreter, string(staticType.ID()))
if err != nil || location == nil {
return Nil
}

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

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

return nil
Expand Down
16 changes: 16 additions & 0 deletions runtime/sema/meta_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ 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
`

func init() {
MetaType.Members = func(t *SimpleType) map[string]MemberResolver {
return MembersAsResolvers([]*Member{
Expand All @@ -90,6 +100,12 @@ func init() {
MetaTypeIsRecoveredFieldType,
metaTypeIsRecoveredFieldDocString,
),
NewUnmeteredPublicConstantFieldMember(
t,
MetaTypeAddressFieldName,
MetaTypeAddressFieldType,
metaTypeAddressFieldDocString,
),
})
}
}
10 changes: 10 additions & 0 deletions runtime/tests/checker/metatype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,16 @@ 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)
}
157 changes: 157 additions & 0 deletions runtime/tests/interpreter/metatype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1067,3 +1067,160 @@ func TestInterpretMetaTypeIsRecovered(t *testing.T) {
require.ErrorIs(t, err, importErr)
})
}

func TestInterpretMetaTypeAddress(t *testing.T) {

t.Parallel()

t.Run("built-in", func(t *testing.T) {

t.Parallel()

inter := parseCheckAndInterpret(t, `
let type = Type<Int>()
let address = type.address
`)

AssertValuesEqual(
t,
inter,
interpreter.Nil,
inter.Globals.Get("address").GetValue(inter),
)
})

t.Run("address location", func(t *testing.T) {

t.Parallel()

inter := parseCheckAndInterpret(t, `
fun test(): Address? {
let type = CompositeType("A.0000000000000001.X.Y")!
return type.address
}
`)

addressLocation := common.AddressLocation{
Address: common.MustBytesToAddress([]byte{0x1}),
Name: "X",
}

inter.SharedState.Config.ImportLocationHandler =
func(_ *interpreter.Interpreter, _ common.Location) interpreter.Import {
elaboration := sema.NewElaboration(nil)
elaboration.SetCompositeType(
addressLocation.TypeID(nil, "X.Y"),
&sema.CompositeType{
Location: addressLocation,
Kind: common.CompositeKindStructure,
},
)
return interpreter.VirtualImport{
Elaboration: elaboration,
}
}

result, err := inter.Invoke("test")
require.NoError(t, err)

AssertValuesEqual(
t,
inter,
interpreter.NewUnmeteredSomeValueNonCopying(
interpreter.NewUnmeteredAddressValueFromBytes([]byte{0x1}),
),
result,
)
})

t.Run("string location", func(t *testing.T) {

t.Parallel()

inter := parseCheckAndInterpret(t, `
fun test(): Address? {
let type = CompositeType("S.test2.X.Y")!
return type.address
}
`)

stringLocation := common.StringLocation("test2")

inter.SharedState.Config.ImportLocationHandler =
func(_ *interpreter.Interpreter, _ common.Location) interpreter.Import {
elaboration := sema.NewElaboration(nil)
elaboration.SetCompositeType(
stringLocation.TypeID(nil, "X.Y"),
&sema.CompositeType{
Location: stringLocation,
Kind: common.CompositeKindStructure,
},
)
return interpreter.VirtualImport{
Elaboration: elaboration,
}
}

result, err := inter.Invoke("test")
require.NoError(t, err)

AssertValuesEqual(
t,
inter,
interpreter.Nil,
result,
)
})

t.Run("unknown", func(t *testing.T) {

t.Parallel()

valueDeclarations := []stdlib.StandardLibraryValue{
{
Name: "unknownType",
Type: sema.MetaType,
Value: interpreter.TypeValue{
Type: nil,
},
Kind: common.DeclarationKindConstant,
},
}

baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation)
for _, valueDeclaration := range valueDeclarations {
baseValueActivation.DeclareValue(valueDeclaration)
}

baseActivation := activations.NewActivation(nil, interpreter.BaseActivation)
for _, valueDeclaration := range valueDeclarations {
interpreter.Declare(baseActivation, valueDeclaration)
}

inter, err := parseCheckAndInterpretWithOptions(t,
`
let address = unknownType.address
`,
ParseCheckAndInterpretOptions{
CheckerConfig: &sema.Config{
BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation {
return baseValueActivation
},
},
Config: &interpreter.Config{
BaseActivationHandler: func(_ common.Location) *interpreter.VariableActivation {
return baseActivation
},
},
},
)
require.NoError(t, err)

AssertValuesEqual(
t,
inter,
interpreter.Nil,
inter.Globals.Get("address").GetValue(inter),
)
})
}

0 comments on commit 32e6467

Please sign in to comment.