-
Notifications
You must be signed in to change notification settings - Fork 375
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
feat(gnovm): Support all valid types for function parameters and return values in code generation for native binding #2323
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2323 +/- ##
==========================================
+ Coverage 54.64% 54.66% +0.02%
==========================================
Files 578 578
Lines 77870 77932 +62
==========================================
+ Hits 42551 42603 +52
- Misses 32149 32154 +5
- Partials 3170 3175 +5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@notJoon is this PR still relevant? Can you please update it with the latest |
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.
Looks good 💯
Pinging @thehowl / @petar-dambovaliev for a second sanity check
if !ok { | ||
return &mismatch | ||
} | ||
if err := m.typesEqual(gnoe.Key, goe.Key); err != nil { |
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.
Do these errors need to be returned raw, or can you use fmt.Errorf
to give them a bit more context?
for i := 0; i < len(gnoe.Fields.List); i++ { | ||
gnoField, goField := gnoe.Fields.List[i], goe.Fields.List[i] | ||
if len(gnoField.Names) != len(goField.Names) { | ||
return &mismatch | ||
} | ||
for j := 0; j < len(gnoField.Names); j++ { | ||
if gnoField.Names[j].Name != goField.Names[j].Name { | ||
return &mismatch | ||
} | ||
} | ||
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil { | ||
return err | ||
} | ||
} | ||
return nil |
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.
What do you think about this mini cleanup?
for i := 0; i < len(gnoe.Fields.List); i++ { | |
gnoField, goField := gnoe.Fields.List[i], goe.Fields.List[i] | |
if len(gnoField.Names) != len(goField.Names) { | |
return &mismatch | |
} | |
for j := 0; j < len(gnoField.Names); j++ { | |
if gnoField.Names[j].Name != goField.Names[j].Name { | |
return &mismatch | |
} | |
} | |
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil { | |
return err | |
} | |
} | |
return nil | |
for i, gnoField := range gnoe.Fields.List { | |
goField := goe.Fields.List[i] | |
if len(gnoField.Names) != len(goField.Names) { | |
return &mismatch | |
} | |
for j, gnoName := range gnofield.Names { | |
if gnoName.Name != goField.Names[j].Name { | |
return &mismatch | |
} | |
} | |
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil { | |
return err | |
} | |
} | |
return nil |
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.
I'm not sure if you can move this check up, before the name loop:
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil {
return err
}
for i := 0; i < len(gnoe.Methods.List); i++ { | ||
gnoField, goField := gnoe.Methods.List[i], goe.Methods.List[i] | ||
if len(gnoField.Names) != len(goField.Names) { | ||
return &mismatch | ||
} | ||
for j := 0; j < len(gnoField.Names); j++ { | ||
if gnoField.Names[j].Name != goField.Names[j].Name { | ||
return &mismatch | ||
} | ||
} | ||
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil { | ||
return err | ||
} | ||
} | ||
return nil |
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 mini cleanup as before. It also uses the correct terminology (method instead of field), since we're iterating over a method list:
for i := 0; i < len(gnoe.Methods.List); i++ { | |
gnoField, goField := gnoe.Methods.List[i], goe.Methods.List[i] | |
if len(gnoField.Names) != len(goField.Names) { | |
return &mismatch | |
} | |
for j := 0; j < len(gnoField.Names); j++ { | |
if gnoField.Names[j].Name != goField.Names[j].Name { | |
return &mismatch | |
} | |
} | |
if err := m.typesEqual(gnoField.Type, goField.Type); err != nil { | |
return err | |
} | |
} | |
return nil | |
for i, gnoMethod := range gnoe.Methods.List { | |
goMethod := goe.Methods.List[i] | |
if len(gnoMethod.Names) != len(goMethod.Names) { | |
return &mismatch | |
} | |
for j, gnoName := range gnoMethod.Names { | |
if gnoName.Name != goMethod.Names[j].Name { | |
return &mismatch | |
} | |
} | |
if err := m.typesEqual(gnoMethod.Type, goMethod.Type); err != nil { | |
return err | |
} | |
} | |
return nil |
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.
I'm not sure if you can move this check up, before the name loop:
if err := m.typesEqual(gnoMethod.Type, goMethod.Type); err != nil {
return err
}
if ok := m.fieldListsMatch(gnoe.Params, goe.Params); !ok { | ||
return &mismatch | ||
} | ||
if ok := m.fieldListsMatch(gnoe.Results, goe.Results); !ok { | ||
return &mismatch | ||
} |
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.
if ok := m.fieldListsMatch(gnoe.Params, goe.Params); !ok { | |
return &mismatch | |
} | |
if ok := m.fieldListsMatch(gnoe.Results, goe.Results); !ok { | |
return &mismatch | |
} | |
if !m.fieldListsMatch(gnoe.Params, goe.Params) || !m.fieldListsMatch(gnoe.Results, goe.Results) { | |
return &mismatch | |
} |
@@ -217,6 +217,49 @@ func Test_typesEqual(t *testing.T) { | |||
{"[]int", "[1]int", "does not match"}, | |||
{"[1]int", "[]int", "does not match"}, | |||
{"[2]int", "[2]string", "does not match"}, | |||
|
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.
You can run this testing suite in parallel with t.Parallel()
@@ -243,15 +286,106 @@ func Test_typesEqual(t *testing.T) { | |||
} | |||
} | |||
|
|||
func Test_typesEqual_SelectorExpr(t *testing.T) { |
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.
You can run this testing suite in parallel with t.Parallel()
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.
Wait. Why do you need this?
The problem is the generated code will still not convert them properly, and it shouldn't convert them properly.
If you're passing interfaces from Go to Gno and viceversa, you're doing something wrong. My last PR specifically on genstd actually removed the support for any named type: 0f2e755
Feel free to reopen this / comment with good use-case, but I don't think there's any. I'll now comment on #2317 as well. |
Description
Enhances the code generation functionality to support all valid types for function parameters and return values that will be injected to gno.
Changes
Modifies the
typesEqual
function to handle the following additional types:ast.MapType
: Recursively compare the key and value types of maps.ast.InterfaceType
: Iterate over the methods of an interface and compare their names and type. The detailed method comparision will be automatically checked in theast.FuncType
handler below.ast.StructType
: Iterate over the fileds of a struct and compare their field names and types.ast.FuncType
: Compare the parameter and result lists of functions. In this case, parameter names and named return identifiers are ignored, and only the type is checked for a one-to-one match.ast.Ellipsis
: Recursively compare the element type of ellipsis. This type is only valid when using as a parameter and cannot be return type.ast.SelectorExpr
: Compare the package path (also, consider alias) and name of selectors.part of #2317