forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: named and unnamed type assignment 3 of 3 (gnolang#2367)
This is the last part of the solution for issue gnolang#1141. The 1 of 3 of the solution can be found in PR gnolang#1143. The 2 of 3 of the solution can be found in PR gnolang#1246 It decomposes function calls that return multiple values in the preprocess. ### Here is the problem to solve: ` u1, n2 = x() ` How do we ensure that the returned multiple values from a function call adhere to named and unnamed type assignment specifications? Additionally, we want to solve this problem during preprocessing instead of at runtime to minimize the impact on runtime performance. ### The main ideas: u1, n2 = x() << decompose the statement to the following two lines // .tmp_1, .tmp_2 := x() // u1, n2 = .tmp_1, .tmp_2 then we can apply name and unname type conversion specs to the second line. u1, n2 = _tmp_1, _tmp_2 ### Here are the example code and the explanation ``` // decompose_filetest.gno package main type nat []int func x() (nat, []int) { a := nat{1} b := []int{2} return a, b } func main() { var u1 []int var n2 nat u1, n2 = x() // .tmp_1, .tmp_2 := x() // u1, n2 = .tmp_1, .tmp_2 println(u1) println(n2) } // Output: // slice[(1 int)] // (slice[(2 int)] main.nat) ``` ### Here is the simplified recursive tree of the transformation in the preprocess <img width="1336" alt="image" src="https://github.com/gnolang/gno/assets/90544084/306a4770-457d-4131-a82a-2de5c6b0dadf"> ### Here are the major steps involved in this decomposition during preprocessing: - Create hidden temporary name expressions .tmp1, .tmp2. In Go, a leading dot is not valid in variable names, ensuring that users cannot create names that clash with these hidden variables. - Create two statements in the block: one for defining and one for assigning. ``` .tmp1, .tmp2 := x() u1, n2 = .tmp_1, .tmp_2 ``` - Preprocess each newly created statements - Replace the original statement with the two newly created statements. ### Here are two additional changes to facilitate above. - Update the FuncValue's body in `updates := pn.PrepareNewValues(pv) `since its source Body has been changed during preprocessing. - Replace all ` for index := range Body` with `for i:=0; i < len(Body); i++` in transcribe.go since the body length might change due to the decomposition. <!-- please provide a detailed description of the changes made in this pull request. --> <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [x] No breaking changes were made - [x] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details> --------- Co-authored-by: Miloš Živković <[email protected]> Co-authored-by: Morgan <[email protected]>
- Loading branch information
Showing
20 changed files
with
793 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package main | ||
|
||
type nat []int | ||
|
||
func x() (nat, []int) { | ||
a := nat{1} | ||
b := []int{2} | ||
return a, b | ||
} | ||
|
||
func main() { | ||
var u1 []int | ||
var n2 nat | ||
|
||
_, n2 = x() | ||
// .tmp1, .tmp_2 := x() | ||
// _, u2 = .tmp1, .tmp_2 | ||
|
||
println(u1) | ||
println(n2) | ||
|
||
} | ||
|
||
// Output: | ||
// (nil []int) | ||
// (slice[(2 int)] main.nat) |
26 changes: 26 additions & 0 deletions
26
gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package main | ||
|
||
type nat []int | ||
|
||
func x() (nat, []int) { | ||
a := nat{1} | ||
b := []int{2} | ||
return a, b | ||
} | ||
|
||
func main() { | ||
var u1 []int | ||
var n2 nat | ||
|
||
u1, _ = x() | ||
// .tmp1, .tmp_2 := x() | ||
// u1, _ = .tmp1, .tmp_2 | ||
|
||
println(u1) | ||
println(n2) | ||
|
||
} | ||
|
||
// Output: | ||
// slice[(1 int)] | ||
// (nil main.nat) |
Oops, something went wrong.