-
Notifications
You must be signed in to change notification settings - Fork 140
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 stringer #3594
base: feature/string-templates
Are you sure you want to change the base?
Introduce stringer #3594
Conversation
@RZhang05 is this ready to be reviewed? or are there any pending changes? |
It is ready, note that there are some questions left in the code marked with TODO however. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
runtime/sema/type.go
Outdated
// STRINGERTODO: other options? how to make existing simple types | ||
// conform to an intersection type? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't so much about conforming these types to an intersection type, but an interface, Stringer
.
At the moment we don't have a means to specify a subtype relationship for simple types, so we might want to add that, i.e. generalize this solution a bit.
Note that the intersection type might contain multiple interfaces, e.g. might not just be {Stringer}
, so checking the first element is not sufficient.
There's also no need, and it is not sufficient, to compare the names only, it is better to check for pointer equality here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment we don't have a means to specify a subtype relationship for simple types, so we might want to add that, i.e. generalize this solution a bit.
In 5f16333, I added the functionality for simple types to conform to an interface.
Not sure the best approach in general for all string convertible types to conform to Stringer
since there are types such as TheAddressType
and NumberType
which are not SimpleType
s so I've left the edge case check in for those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a ConformingType
interface as suggested by #3594 (comment).
runtime/sema/type.go
Outdated
for len(interfaceTypes) > 0 { | ||
lastIndex := len(interfaceTypes) - 1 | ||
interfaceType := interfaceTypes[lastIndex] | ||
interfaceTypes[lastIndex] = nil | ||
interfaceTypes = interfaceTypes[:lastIndex] | ||
|
||
NativeInterfaceTypes[interfaceType.QualifiedIdentifier()] = interfaceType | ||
|
||
nestedTypes := interfaceType.NestedTypes | ||
if nestedTypes == nil { | ||
continue | ||
} | ||
|
||
nestedTypes.Foreach(func(_ string, nestedType Type) { | ||
nestedInterfaceType, ok := nestedType.(*InterfaceType) | ||
if !ok { | ||
return | ||
} | ||
|
||
interfaceTypes = append(interfaceTypes, nestedInterfaceType) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to refactor this into a function, and also use it in the init
block initializing NativeCompositeTypes
runtime/sema/stringer.go
Outdated
"github.com/onflow/cadence/runtime/common" | ||
) | ||
|
||
const StringerTypeName = "Stringer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately we cannot define a single interface that users could implement for both structs and resources. To begin with we're only adding a struct interface, but we might also want to provide another resource interface in the future. We might want to consider naming this so it indicates that it is only for structs, e.g. StructStringer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!
runtime/sema/gen/main.go
Outdated
@@ -164,6 +164,9 @@ type typeDecl struct { | |||
memberDeclarations []ast.Declaration | |||
nestedTypes []*typeDecl | |||
hasConstructor bool | |||
|
|||
// used in simpleType generation | |||
conformances []string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe consider making this more type-safe by using a []common.TypeID
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to an InterfaceType
for simplicity
runtime/sema/gen/main.go
Outdated
common.CompositeKindContract: | ||
break | ||
default: | ||
panic(fmt.Sprintf("%s declarations are not supported", compositeKind.Name())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
panic(fmt.Sprintf("%s declarations are not supported", compositeKind.Name())) | |
panic(fmt.Sprintf("%s interface declarations are not supported", compositeKind.Name())) |
runtime/sema/gen/main.go
Outdated
@@ -736,8 +741,151 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ | |||
return | |||
} | |||
|
|||
func (*generator) VisitInterfaceDeclaration(_ *ast.InterfaceDeclaration) struct{} { | |||
panic("interface declarations are not supported") | |||
func (g *generator) VisitInterfaceDeclaration(decl *ast.InterfaceDeclaration) (_ struct{}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there anything significantly different from VisitCompositeDeclaration
? If the code generation is pretty much the same, maybe refactor it into a common function
runtime/sema/gen/main.go
Outdated
@@ -1591,6 +1739,9 @@ func simpleTypeLiteral(ty *typeDecl) dst.Expr { | |||
// Comparable: false, | |||
// Exportable: false, | |||
// Importable: false, | |||
// comformances: []*InterfaceType { | |||
// StructStringer, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// StructStringer, | |
// StructStringerType, |
runtime/sema/gen/main.go
Outdated
@@ -2069,6 +2240,100 @@ func compositeTypeLiteral(ty *typeDecl) dst.Expr { | |||
} | |||
} | |||
|
|||
func interfaceTypeExpr(ty *typeDecl) dst.Expr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: Is there anything significantly different from the composite-related functions (compositeTypeExpr
, compositeTypeLiteral
)? If the code generation is pretty much the same, maybe refactor it into a common function
runtime/sema/type.go
Outdated
@@ -7244,11 +7276,18 @@ const AddressTypeName = "Address" | |||
|
|||
// AddressType represents the address type | |||
type AddressType struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above for NumericType
runtime/sema/type.go
Outdated
nestedCompositeType, ok := nestedType.(*CompositeType) | ||
if !ok { | ||
return | ||
} | ||
|
||
types = append(types, nestedCompositeType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add all nested types (e.g. interface types), not just composite types
nestedCompositeType, ok := nestedType.(*CompositeType) | |
if !ok { | |
return | |
} | |
types = append(types, nestedCompositeType) | |
types = append(types, nestedType) |
runtime/sema/type.go
Outdated
nestedInterfaceType, ok := nestedType.(*InterfaceType) | ||
if !ok { | ||
return | ||
} | ||
|
||
types = append(types, nestedInterfaceType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
nestedInterfaceType, ok := nestedType.(*InterfaceType) | |
if !ok { | |
return | |
} | |
types = append(types, nestedInterfaceType) | |
types = append(types, nestedType) |
runtime/sema/type.go
Outdated
types = append(types, nestedInterfaceType) | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a default
case and panic(errors.NewUnreachableError())
runtime/sema/gen/main.go
Outdated
@@ -736,8 +741,151 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ | |||
return | |||
} | |||
|
|||
func (*generator) VisitInterfaceDeclaration(_ *ast.InterfaceDeclaration) struct{} { | |||
panic("interface declarations are not supported") | |||
func (g *generator) VisitInterfaceDeclaration(decl *ast.InterfaceDeclaration) (_ struct{}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test case to sema/gen/testdata
1e12760
to
fab5f6c
Compare
… introduce-stringer
49b69f8
to
b9243e3
Compare
Working towards #3579
Description
A simple
Stringer
struct interface. It is intended in the future that all types which implementStringer
can be used in string templates.feature/string-templates
branchFiles changed
in the Github PR explorer