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ć <milos.zivkovic@tendermint.com> Co-authored-by: Morgan <git@howl.moe>
- Loading branch information