From 76b2b92dc1975988c378c9b06ec66f7e576bfea5 Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Sun, 16 Jun 2024 18:20:48 -0700 Subject: [PATCH 01/12] feat: named and unnamed type assignment 3 of 3 --- gnovm/pkg/gnolang/nodes.go | 28 +++++++ gnovm/pkg/gnolang/preprocess.go | 75 +++++++++++++++++++ gnovm/pkg/gnolang/transcribe.go | 27 ++++--- gnovm/pkg/gnolang/values.go | 9 +++ .../decompose_unnamed1a_filetest.gno | 26 +++++++ .../decompose_unnamed1b_filetest.gno | 26 +++++++ .../decompose/decompose_unnamed2_filetest.gno | 30 ++++++++ .../decompose/decompose_unnamed_filetest.gno | 26 +++++++ 8 files changed, 238 insertions(+), 9 deletions(-) create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 482f4850b6e..0dcc0880d35 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -669,6 +669,10 @@ func (ss Body) GetBody() Body { return ss } +func (ss *Body) SetBody(nb Body) { + *ss = nb +} + func (ss Body) GetLabeledStmt(label Name) (stmt Stmt, idx int) { for idx, stmt = range ss { if label == stmt.GetLabel() { @@ -1363,6 +1367,13 @@ func (x *PackageNode) PrepareNewValues(pv *PackageValue) []TypedValue { panic("PackageNode.PrepareNewValues() package mismatch") } } + // the FuncValue Body maybe be altered during the preprocessing. + // We need to update body field from the source in the FuncValue accordingly. + for _, tv := range x.Values { + if fv, ok := tv.V.(*FuncValue); ok { + fv.UpdateBodyFromSource() + } + } pvl := len(block.Values) pnl := len(x.Values) // copy new top-level defined values/types. @@ -1468,6 +1479,7 @@ type BlockNode interface { Define(Name, TypedValue) Define2(bool, Name, Type, TypedValue) GetBody() Body + SetBody(Body) } // ---------------------------------------- @@ -1857,18 +1869,34 @@ func (x *IfStmt) GetBody() Body { panic("IfStmt has no body (but .Then and .Else do)") } +func (x *IfStmt) SetBody(b Body) { + panic("IfStmt has no body (but .Then and .Else do)") +} + func (x *SwitchStmt) GetBody() Body { panic("SwitchStmt has no body (but its cases do)") } +func (x *SwitchStmt) SetBody(b Body) { + panic("SwitchStmt has no body (but its cases do)") +} + func (x *FileNode) GetBody() Body { panic("FileNode has no body (but it does have .Decls)") } +func (x *FileNode) SetBody(b Body) { + panic("FileNode has no body (but it does have .Decls)") +} + func (x *PackageNode) GetBody() Body { panic("PackageNode has no body") } +func (x *PackageNode) SetBody(b Body) { + panic("PackageNode has no body") +} + // ---------------------------------------- // Value Path diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 88c5c2f1da4..ed1c685a36a 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1678,6 +1678,81 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { "%d variables but %s returns %d values", len(n.Lhs), cx.Func.String(), len(cft.Results))) } + + // check if we we need to decompose for named typed conversion in the function return results + decompose := false + + for i, rhsType := range cft.Results { + lt := evalStaticTypeOf(store, last, n.Lhs[i]) + if lt != nil && isNamedConversion(rhsType.Type, lt) { + decompose = true + break + } + } + + if decompose == true { + + // only enter this section if cft.Results to be converted to Lhs type for named type conversion. + // decompose a,b = x() + // tmp1, tmp2 := x() assignment statemet expression (Op=DEFINE) + // a,b = tmp1, tmp2 assignment statemet expression ( Op=ASSIGN ) + // add the new statement to last.Body + + // step1: + // create a hidden var with leading _ the curBodyLen increase every time when there is an decompostion + // because there could be multiple decomposition happens + // we use both stmt index and resturn result number to differentiate the _tmp variables created in each assignment decompostion + // ex. _tmp_3_2: this variabl is created as the 3rd statement in the block, the 2nd parameter returned from x(), + // create _tmp_1_1, tmp_1_2 .... based on number of result from x() + var tmpExprs Exprs + for i := range cft.Results { + rn := fmt.Sprintf("_tmp_%d_%d", index, i) + tmpExprs = append(tmpExprs, Nx(rn)) + } + // step2: + // tmp1, tmp2 := x() + dsx := &AssignStmt{ + Lhs: tmpExprs, + Op: DEFINE, + Rhs: n.Rhs, + } + dsx.SetLine(n.Line) + dsx = Preprocess(store, last, dsx).(*AssignStmt) + + // step3: + + // a,b = tmp1, tmp2 + // assign stmt expression + // the right hand side will be converted to call expr for nameed/unnamed covnerstion + // we make a copy of tmpExrs to prevent dsx.Lhs in the preview statement changing by the side effect + // when asx.Rhs is converted to const call expr during the preprocess of the next statement + + asx := &AssignStmt{ + Lhs: n.Lhs, + Op: ASSIGN, + Rhs: copyExprs(tmpExprs), + } + asx.SetLine(n.Line) + asx = Preprocess(store, last, asx).(*AssignStmt) + + // step4: + // replace the orignal stmt with two new stmts + body := last.GetBody() + // we need to do an in-place replacement while leaving the current node + n.Attributes = dsx.Attributes + n.Lhs = dsx.Lhs + n.Op = dsx.Op + n.Rhs = dsx.Rhs + + // insert a assignment statement a,b = tmp1,tmp2 AFTER the current statement in the last.Body. + body = append(body[:index+1], append(Body{asx}, body[index+1:]...)...) + last.SetBody(body) + } // end of the decomposition + + // Last step: we need to insert the statements to FuncValue.body of PackageNopde.Values[i].V + // updating FuncValue.body=FuncValue.Source.Body in updates := pn.PrepareNewValues(pv) during preprocess. + // we updated FuncValue from source. + case *TypeAssertExpr: // Type-assert case: a, ok := x.(type) if len(n.Lhs) != 2 { diff --git a/gnovm/pkg/gnolang/transcribe.go b/gnovm/pkg/gnolang/transcribe.go index c5b72336c83..28e97ff2b5b 100644 --- a/gnovm/pkg/gnolang/transcribe.go +++ b/gnovm/pkg/gnolang/transcribe.go @@ -271,7 +271,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc } else { cnn = cnn2.(*FuncLitExpr) } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_FUNCLIT_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -383,7 +384,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc } else { cnn = cnn2.(*BlockStmt) } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_BLOCK_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -393,7 +395,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc } case *BranchStmt: case *DeclStmt: - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_DECL_BODY, idx, cnn.Body[idx], &c).(SimpleDeclStmt) if isBreak(c) { break @@ -438,7 +441,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc return } } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_FOR_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -488,7 +492,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc } else { cnn = cnn2.(*IfCaseStmt) } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_IF_CASE_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -525,7 +530,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc return } } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_RANGE_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -565,7 +571,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc if isStopOrSkip(nc, c) { return } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_SELECTCASE_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -640,7 +647,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc return } } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_SWITCHCASE_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break @@ -666,7 +674,8 @@ func transcribe(t Transform, ns []Node, ftype TransField, index int, n Node, nc } else { cnn = cnn2.(*FuncDecl) } - for idx := range cnn.Body { + // iterate over Body; its length can change if a statement is decomposed. + for idx := 0; idx < len(cnn.Body); idx++ { cnn.Body[idx] = transcribe(t, nns, TRANS_FUNC_BODY, idx, cnn.Body[idx], &c).(Stmt) if isBreak(c) { break diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index d8d4bc58bc3..910e55a0ce0 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -595,6 +595,15 @@ func (fv *FuncValue) GetBodyFromSource(store Store) []Stmt { return fv.body } +func (fv *FuncValue) UpdateBodyFromSource() { + if fv.Source == nil { + panic(fmt.Sprintf( + "Source is missing for FuncValue %s", + fv.Name)) + } + fv.body = fv.Source.GetBody() +} + func (fv *FuncValue) GetSource(store Store) BlockNode { if rn, ok := fv.Source.(RefNode); ok { source := store.GetBlockNode(rn.GetLocation()) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno new file mode 100644 index 00000000000..aff909afcd5 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno @@ -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) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno new file mode 100644 index 00000000000..3248d9ca700 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno @@ -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) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno new file mode 100644 index 00000000000..e28b231b63e --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno @@ -0,0 +1,30 @@ +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 + // BlockStmt + { u1, n2 = x() + // _tmp_1, _tmp_2 := x() + // u1, n2 = _tmp_1, _tmp_2 + + println(u1) + println(n2) + println(u1) + println(n2) + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno new file mode 100644 index 00000000000..b2f8840e7f0 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno @@ -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, 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) From 176ad013264e5a027a3c273d8a8651b72fd6b78e Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Sun, 16 Jun 2024 19:30:34 -0700 Subject: [PATCH 02/12] chore: updated the hidden variable prefix --- gnovm/pkg/gnolang/preprocess.go | 20 +++++++++---------- .../decompose_unnamed1a_filetest.gno | 4 ++-- .../decompose_unnamed1b_filetest.gno | 4 ++-- .../decompose/decompose_unnamed2_filetest.gno | 4 ++-- .../decompose/decompose_unnamed_filetest.gno | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ed1c685a36a..0fb665b0830 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1694,23 +1694,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // only enter this section if cft.Results to be converted to Lhs type for named type conversion. // decompose a,b = x() - // tmp1, tmp2 := x() assignment statemet expression (Op=DEFINE) - // a,b = tmp1, tmp2 assignment statemet expression ( Op=ASSIGN ) + // .tmp1, .tmp2 := x() assignment statemet expression (Op=DEFINE) + // a,b = .tmp1, .tmp2 assignment statemet expression ( Op=ASSIGN ) // add the new statement to last.Body // step1: - // create a hidden var with leading _ the curBodyLen increase every time when there is an decompostion + // create a hidden var with leading . (dot) the curBodyLen increase every time when there is an decompostion // because there could be multiple decomposition happens - // we use both stmt index and resturn result number to differentiate the _tmp variables created in each assignment decompostion - // ex. _tmp_3_2: this variabl is created as the 3rd statement in the block, the 2nd parameter returned from x(), - // create _tmp_1_1, tmp_1_2 .... based on number of result from x() + // we use both stmt index and resturn result number to differentiate the .tmp variables created in each assignment decompostion + // ex. .tmp_3_2: this variabl is created as the 3rd statement in the block, the 2nd parameter returned from x(), + // create .tmp_1_1, .tmp_1_2 .... based on number of result from x() var tmpExprs Exprs for i := range cft.Results { - rn := fmt.Sprintf("_tmp_%d_%d", index, i) + rn := fmt.Sprintf(".tmp_%d_%d", index, i) tmpExprs = append(tmpExprs, Nx(rn)) } // step2: - // tmp1, tmp2 := x() + // .tmp1, .tmp2 := x() dsx := &AssignStmt{ Lhs: tmpExprs, Op: DEFINE, @@ -1721,7 +1721,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // step3: - // a,b = tmp1, tmp2 + // a,b = .tmp1, .tmp2 // assign stmt expression // the right hand side will be converted to call expr for nameed/unnamed covnerstion // we make a copy of tmpExrs to prevent dsx.Lhs in the preview statement changing by the side effect @@ -1744,7 +1744,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Op = dsx.Op n.Rhs = dsx.Rhs - // insert a assignment statement a,b = tmp1,tmp2 AFTER the current statement in the last.Body. + // insert a assignment statement a,b = .tmp1,.tmp2 AFTER the current statement in the last.Body. body = append(body[:index+1], append(Body{asx}, body[index+1:]...)...) last.SetBody(body) } // end of the decomposition diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno index aff909afcd5..0e999ca130f 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1a_filetest.gno @@ -13,8 +13,8 @@ func main() { var n2 nat _, n2 = x() - // _tmp1, _tmp_2 := x() - // _, u2 = _tmp1, _tmp_2 + // .tmp1, .tmp_2 := x() + // _, u2 = .tmp1, .tmp_2 println(u1) println(n2) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno index 3248d9ca700..9fed8f29cc6 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed1b_filetest.gno @@ -13,8 +13,8 @@ func main() { var n2 nat u1, _ = x() - // _tmp1, _tmp_2 := x() - // u1, _ = _tmp1, _tmp_2 + // .tmp1, .tmp_2 := x() + // u1, _ = .tmp1, .tmp_2 println(u1) println(n2) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno index e28b231b63e..8fe9c15eab3 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno @@ -13,8 +13,8 @@ func main() { var n2 nat // BlockStmt { u1, n2 = x() - // _tmp_1, _tmp_2 := x() - // u1, n2 = _tmp_1, _tmp_2 + // .tmp_1, .tmp_2 := x() + // u1, n2 = .tmp_1, .tmp_2 println(u1) println(n2) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno index b2f8840e7f0..44f9992a269 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed_filetest.gno @@ -13,8 +13,8 @@ func main() { var n2 nat u1, n2 = x() - // _tmp_1, _tmp_2 := x() - // u1, n2 = _tmp_1, _tmp_2 + // .tmp_1, .tmp_2 := x() + // u1, n2 = .tmp_1, .tmp_2 println(u1) println(n2) From 429ddb604a5e1a88c6c0dbf08c102681d100da0f Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Sun, 16 Jun 2024 20:31:31 -0700 Subject: [PATCH 03/12] chore: lint white space --- gnovm/pkg/gnolang/preprocess.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0fb665b0830..2944189ee75 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1689,9 +1689,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { break } } - if decompose == true { - // only enter this section if cft.Results to be converted to Lhs type for named type conversion. // decompose a,b = x() // .tmp1, .tmp2 := x() assignment statemet expression (Op=DEFINE) From 628a8f5ded790e79745048699a156a6d4e75b7b6 Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Sun, 7 Jul 2024 00:13:00 -0500 Subject: [PATCH 04/12] added more test cases and fixed typos --- gnovm/pkg/gnolang/nodes.go | 2 +- gnovm/pkg/gnolang/preprocess.go | 16 ++--- .../decompose/decompose_unnamed2_filetest.gno | 12 ++-- .../decompose_unnamed2b_filetest.gno | 48 +++++++++++++ .../decompose_unnamed2c_filetest.gno | 69 ++++++++++++++++++ .../decompose_unnamed2d_filetest.gno | 70 +++++++++++++++++++ .../decompose_unnamed2e_filetest.gno | 52 ++++++++++++++ .../decompose_unnamed2f2_filetest.gno | 46 ++++++++++++ .../decompose_unnamed2f_filetest.gno | 49 +++++++++++++ .../decompose_unnamed2g_filetest.gno | 63 +++++++++++++++++ .../decompose/decompose_unnamed3_filetest.gno | 50 +++++++++++++ .../decompose/decompose_unnamed4_filetest.gno | 39 +++++++++++ .../decompose_unnamed4b_filetest.gno | 18 +++++ .../decompose_unnamed4c_filetest.gno | 18 +++++ 14 files changed, 537 insertions(+), 15 deletions(-) create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2c_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2e_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f2_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2g_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed3_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno create mode 100644 gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 0dcc0880d35..c65d9433a99 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1367,7 +1367,7 @@ func (x *PackageNode) PrepareNewValues(pv *PackageValue) []TypedValue { panic("PackageNode.PrepareNewValues() package mismatch") } } - // the FuncValue Body maybe be altered during the preprocessing. + // The FuncValue Body may have been altered during the preprocessing. // We need to update body field from the source in the FuncValue accordingly. for _, tv := range x.Values { if fv, ok := tv.V.(*FuncValue); ok { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 2944189ee75..6d5b82e68b4 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1680,7 +1680,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { } // check if we we need to decompose for named typed conversion in the function return results - decompose := false + var decompose bool for i, rhsType := range cft.Results { lt := evalStaticTypeOf(store, last, n.Lhs[i]) @@ -1689,18 +1689,18 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { break } } - if decompose == true { + if decompose { // only enter this section if cft.Results to be converted to Lhs type for named type conversion. // decompose a,b = x() - // .tmp1, .tmp2 := x() assignment statemet expression (Op=DEFINE) - // a,b = .tmp1, .tmp2 assignment statemet expression ( Op=ASSIGN ) + // .tmp1, .tmp2 := x() assignment statement expression (Op=DEFINE) + // a,b = .tmp1, .tmp2 assignment statement expression ( Op=ASSIGN ) // add the new statement to last.Body // step1: // create a hidden var with leading . (dot) the curBodyLen increase every time when there is an decompostion // because there could be multiple decomposition happens // we use both stmt index and resturn result number to differentiate the .tmp variables created in each assignment decompostion - // ex. .tmp_3_2: this variabl is created as the 3rd statement in the block, the 2nd parameter returned from x(), + // ex. .tmp_3_2: this variable is created as the 3rd statement in the block, the 2nd parameter returned from x(), // create .tmp_1_1, .tmp_1_2 .... based on number of result from x() var tmpExprs Exprs for i := range cft.Results { @@ -1721,8 +1721,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // a,b = .tmp1, .tmp2 // assign stmt expression - // the right hand side will be converted to call expr for nameed/unnamed covnerstion - // we make a copy of tmpExrs to prevent dsx.Lhs in the preview statement changing by the side effect + // the right hand side will be converted to call expr for nameed/unnamed covnersion + // we make a copy of tmpExprs to prevent dsx.Lhs in the preview statement changing by the side effect // when asx.Rhs is converted to const call expr during the preprocess of the next statement asx := &AssignStmt{ @@ -1734,7 +1734,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { asx = Preprocess(store, last, asx).(*AssignStmt) // step4: - // replace the orignal stmt with two new stmts + // replace the original stmt with two new stmts body := last.GetBody() // we need to do an in-place replacement while leaving the current node n.Attributes = dsx.Attributes diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno index 8fe9c15eab3..db8a0838c7a 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2_filetest.gno @@ -11,16 +11,16 @@ func x() (nat, []int) { func main() { var u1 []int var n2 nat - // BlockStmt - { u1, n2 = x() - // .tmp_1, .tmp_2 := x() - // u1, n2 = .tmp_1, .tmp_2 - + // BlockStmt + { + u1, n2 = x() + // .tmp0_1, .tmp0_2 := x() + // u1, n2 = .tmp0_1, .tmp0_2 println(u1) println(n2) println(u1) println(n2) - } + } } // Output: diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2b_filetest.gno new file mode 100644 index 00000000000..6d8f05807c7 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2b_filetest.gno @@ -0,0 +1,48 @@ +package main + +type nat []int + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + var u1 []int + var n2 nat + // if block + if true { + u1, n2 = x() + // .tmp_1, .tmp_2 := x() + // u1, n2 = .tmp_1, .tmp_2 + println(u1) + println(n2) + println(u1) + println(n2) + } + // else block + if false { + + } else { + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2c_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2c_filetest.gno new file mode 100644 index 00000000000..cae371f3821 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2c_filetest.gno @@ -0,0 +1,69 @@ +package main + +type nat []int + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + var u1 []int + var n2 nat + + // if, for, range block + + if true { + u1, n2 = x() + println(u1) + println(n2) + u1, n2 = y() + println(u1) + println(n2) + + for i := 0; i < 2; i++ { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + } + + zeros := []int{0, 0} + for _, _ = range zeros { + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + } + + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno new file mode 100644 index 00000000000..32f8f8a5137 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno @@ -0,0 +1,70 @@ +package main + +type nat []int + +// gloabal variables +var u1 []int +var n2 nat + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + + // if else, for block + + if true { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + + for i := 0; i < 2; i++ { + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + } + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2e_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2e_filetest.gno new file mode 100644 index 00000000000..d73e908f6c6 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2e_filetest.gno @@ -0,0 +1,52 @@ +package main + +type nat []int + +// gloabal variables +var u1 []int +var n2 nat + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + // function block + fn() +} + +func fn() { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + + for i := 0; i < 2; i++ { + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f2_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f2_filetest.gno new file mode 100644 index 00000000000..ea8e042d18b --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f2_filetest.gno @@ -0,0 +1,46 @@ +package main + +type nat []int + +// gloabal variables +var u1 []int +var n2 nat + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} + +func main() { + fn() +} + +func fn() { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + + // function literal block + u1, n2 = func() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b + }() + println(u1) + println(n2) + println(u1) + println(n2) +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f_filetest.gno new file mode 100644 index 00000000000..05201a6bd2b --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2f_filetest.gno @@ -0,0 +1,49 @@ +package main + +type nat []int + +// gloabal variables +var u1 []int +var n2 nat + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + fn() +} + +func fn() { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + + // function literal block + func() { + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + + }() +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2g_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2g_filetest.gno new file mode 100644 index 00000000000..c8f9badc380 --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2g_filetest.gno @@ -0,0 +1,63 @@ +package main + +type nat []int + +// gloabal variables +var u1 []int +var n2 nat + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + fn() +} + +func fn() { + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + // for block + // switch case block + + for i := 0; i < 2; i++ { + switch i { + case 0: + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + default: + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + + } + } +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed3_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed3_filetest.gno new file mode 100644 index 00000000000..c8749cd862a --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed3_filetest.gno @@ -0,0 +1,50 @@ +package main + +type nat []int + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + var u1 []int + var n2 nat + + // multiple statements + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + u1, n2 = y() + println(u1) + println(n2) + println(u1) + println(n2) + u1, n2 = x() + println(u1) + println(n2) + println(u1) + println(n2) + +} + +// Output: +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(4 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) +// slice[(1 int)] +// (slice[(2 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno new file mode 100644 index 00000000000..add1f0e32dc --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno @@ -0,0 +1,39 @@ +package main + +type nat []int + +var n1, u2 = x() + +func x() (nat, []int) { + a := nat{1} + b := []int{2} + return a, b +} +func y() (nat, []int) { + a := nat{3} + b := []int{4} + return a, b +} +func main() { + + // multiple statements + println(n1) + println(u2) + + u2, n1 = y() + println(n1) + println(u2) + + n1, u2 = x() + println(n1) + println(u2) + +} + +// Output: +// (slice[(1 int)] main.nat) +// slice[(2 int)] +// (slice[(4 int)] main.nat) +// slice[(3 int)] +// (slice[(1 int)] main.nat) +// slice[(2 int)] diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno new file mode 100644 index 00000000000..cff9c0c042a --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno @@ -0,0 +1,18 @@ +package main + +type nat []int + +var n1, n2 nat = x() + +func x() (nat, []int) { + return nat{1}, nat{2} +} + +func main() { + println(n1) + println(n2) +} + +// Output: +// (slice[(1 int)] main.nat) +// (slice[(2 int)] main.nat) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno new file mode 100644 index 00000000000..f7f376b9c9a --- /dev/null +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno @@ -0,0 +1,18 @@ +package main + +type nat []int + +var u1, u2 []int = x() + +func x() (nat, []int) { + return []int{1}, nat{2} +} + +func main() { + println(u1) + println(u2) +} + +// Output: +// slice[(1 int)] +// slice[(2 int)] From 1d6d66caba79fea8eabef462373bf08d8c42d0b7 Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Sun, 7 Jul 2024 12:52:28 -0500 Subject: [PATCH 05/12] chore: lint remove white space --- gnovm/pkg/gnolang/preprocess.go | 1 - 1 file changed, 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 0247857cbcf..87e54efe409 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1751,7 +1751,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Last step: we need to insert the statements to FuncValue.body of PackageNopde.Values[i].V // updating FuncValue.body=FuncValue.Source.Body in updates := pn.PrepareNewValues(pv) during preprocess. // we updated FuncValue from source. - } } else { // len(Lhs) == len(Rhs) if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN { From 02e0915fbebe8a47039cfacc8c23232a25d1e40a Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:18:51 -0500 Subject: [PATCH 06/12] fix: add temp variable in the declaration --- gnovm/Makefile | 2 +- gnovm/pkg/gnolang/preprocess.go | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/gnovm/Makefile b/gnovm/Makefile index 6e939289fb8..5ff3af9c253 100644 --- a/gnovm/Makefile +++ b/gnovm/Makefile @@ -53,7 +53,7 @@ lint: $(rundep) github.com/golangci/golangci-lint/cmd/golangci-lint run --config ../.github/golangci.yml ./... .PHONY: fmt -fmt: +fmt: go run ./cmd/gno fmt $(GNOFMT_FLAGS) ./stdlibs/... $(rundep) mvdan.cc/gofumpt $(GOFMT_FLAGS) . diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index db1c5a78c2c..6385886633f 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" "reflect" + "strings" "sync/atomic" "github.com/gnolang/gno/tm2/pkg/errors" @@ -426,6 +427,24 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { switch n := n.(type) { // TRANS_ENTER ----------------------- case *AssignStmt: + if n.Op == DEFINE { + for _, lx := range n.Lhs { + ln := lx.(*NameExpr).Name + if ln == blankIdentifier { + // ignore. + } else if strings.HasPrefix(string(ln), ".tmp_") { + _, ok := last.GetLocalIndex(ln) + if !ok { + // initial declaration to be re-defined. + last.Define(ln, anyValue(nil)) + } else { + // do not redeclare. + } + } + } + } else { + // nothing defined. + } // TRANS_ENTER ----------------------- case *ImportDecl, *ValueDecl, *TypeDecl, *FuncDecl: From 2c9d737062242b7f4be266ea7cf1d30ce2a075af Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:12:56 -0500 Subject: [PATCH 07/12] chore: fix typos --- gnovm/pkg/gnolang/preprocess.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 6385886633f..5e5e1a67f02 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1948,8 +1948,8 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // a,b = .tmp1, .tmp2 // assign stmt expression - // the right hand side will be converted to call expr for nameed/unnamed covnersion - // we make a copy of tmpExprs to prevent dsx.Lhs in the preview statement changing by the side effect + // the right hand side will be converted to call expr for named/unnamed conversion, + // we make a copy of tmpExprs to prevent dsx.Lhs in the previous statement changing by the side effect // when asx.Rhs is converted to const call expr during the preprocess of the next statement asx := &AssignStmt{ From 2935558342e867443aadefc60503c4c2248005b9 Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:20:09 -0500 Subject: [PATCH 08/12] chore: remove unnecessary len check --- gnovm/pkg/gnolang/preprocess.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 5e5e1a67f02..a8ca0e2377f 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1899,13 +1899,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Call case: a, b = x(...) ift := evalStaticTypeOf(store, last, cx.Func) cft := getGnoFuncTypeOf(store, ift) - if len(n.Lhs) != len(cft.Results) { - panic(fmt.Sprintf( - "assignment mismatch: "+ - "%d variables but %s returns %d values", - len(n.Lhs), cx.Func.String(), len(cft.Results))) - } - // check if we we need to decompose for named typed conversion in the function return results var decompose bool From f31f880ade90f48bba8e53fc722c4e415eab957c Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:39:23 -0500 Subject: [PATCH 09/12] chore: fix more typos --- gnovm/pkg/gnolang/preprocess.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index a8ca0e2377f..29afc164356 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1917,9 +1917,9 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // add the new statement to last.Body // step1: - // create a hidden var with leading . (dot) the curBodyLen increase every time when there is an decompostion + // create a hidden var with leading . (dot) the curBodyLen increase every time when there is an decomposition // because there could be multiple decomposition happens - // we use both stmt index and resturn result number to differentiate the .tmp variables created in each assignment decompostion + // we use both stmt index and return result number to differentiate the .tmp variables created in each assignment decompostion // ex. .tmp_3_2: this variable is created as the 3rd statement in the block, the 2nd parameter returned from x(), // create .tmp_1_1, .tmp_1_2 .... based on number of result from x() var tmpExprs Exprs From 7ad004a70dce634a80dbca5bb23e082a4059f0ec Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:29:33 -0500 Subject: [PATCH 10/12] chore: better naming --- gnovm/pkg/gnolang/preprocess.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 29afc164356..312f6e8d69c 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -432,7 +432,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { ln := lx.(*NameExpr).Name if ln == blankIdentifier { // ignore. - } else if strings.HasPrefix(string(ln), ".tmp_") { + } else if strings.HasPrefix(string(ln), ".decompose_") { _, ok := last.GetLocalIndex(ln) if !ok { // initial declaration to be re-defined. @@ -1912,23 +1912,23 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if decompose { // only enter this section if cft.Results to be converted to Lhs type for named type conversion. // decompose a,b = x() - // .tmp1, .tmp2 := x() assignment statement expression (Op=DEFINE) - // a,b = .tmp1, .tmp2 assignment statement expression ( Op=ASSIGN ) + // .decompose1, .decompose2 := x() assignment statement expression (Op=DEFINE) + // a,b = .decompose1, .decompose2 assignment statement expression ( Op=ASSIGN ) // add the new statement to last.Body // step1: - // create a hidden var with leading . (dot) the curBodyLen increase every time when there is an decomposition + // create a hidden var with leading . (dot) the curBodyLen increase every time when there is a decomposition // because there could be multiple decomposition happens - // we use both stmt index and return result number to differentiate the .tmp variables created in each assignment decompostion - // ex. .tmp_3_2: this variable is created as the 3rd statement in the block, the 2nd parameter returned from x(), - // create .tmp_1_1, .tmp_1_2 .... based on number of result from x() - var tmpExprs Exprs + // we use both stmt index and return result number to differentiate the .decompose variables created in each assignment decompostion + // ex. .decompose_3_2: this variable is created as the 3rd statement in the block, the 2nd parameter returned from x(), + // create .decompose_1_1, .decompose_1_2 .... based on number of result from x() + tmpExprs := make(Exprs, 0, len(cft.Results)) for i := range cft.Results { - rn := fmt.Sprintf(".tmp_%d_%d", index, i) + rn := fmt.Sprintf(".decompose_%d_%d", index, i) tmpExprs = append(tmpExprs, Nx(rn)) } // step2: - // .tmp1, .tmp2 := x() + // .decompose1, .decompose2 := x() dsx := &AssignStmt{ Lhs: tmpExprs, Op: DEFINE, @@ -1939,7 +1939,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // step3: - // a,b = .tmp1, .tmp2 + // a,b = .decompose1, .decompose2 // assign stmt expression // the right hand side will be converted to call expr for named/unnamed conversion, // we make a copy of tmpExprs to prevent dsx.Lhs in the previous statement changing by the side effect @@ -1962,7 +1962,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { n.Op = dsx.Op n.Rhs = dsx.Rhs - // insert a assignment statement a,b = .tmp1,.tmp2 AFTER the current statement in the last.Body. + // insert a assignment statement a,b = .decompose1,.decompose2 AFTER the current statement in the last.Body. body = append(body[:index+1], append(Body{asx}, body[index+1:]...)...) last.SetBody(body) } // end of the decomposition From 7db8fa9c28863b7429565d129be55e53f0e28918 Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:37:25 -0500 Subject: [PATCH 11/12] chores: better panic message Co-authored-by: Morgan --- gnovm/pkg/gnolang/values.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/values.go b/gnovm/pkg/gnolang/values.go index 105c9e9fe40..5da7c15bb05 100644 --- a/gnovm/pkg/gnolang/values.go +++ b/gnovm/pkg/gnolang/values.go @@ -604,7 +604,7 @@ func (fv *FuncValue) GetBodyFromSource(store Store) []Stmt { func (fv *FuncValue) UpdateBodyFromSource() { if fv.Source == nil { panic(fmt.Sprintf( - "Source is missing for FuncValue %s", + "Source is missing for FuncValue %q", fv.Name)) } fv.body = fv.Source.GetBody() From bb958e79e7e30164d6b67ac8a3475784b23b7d2f Mon Sep 17 00:00:00 2001 From: piux2 <90544084+piux2@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:59:44 -0700 Subject: [PATCH 12/12] chores: more comments --- gnovm/pkg/gnolang/preprocess.go | 13 ++++++++----- .../decompose/decompose_unnamed2d_filetest.gno | 5 +++-- .../decompose/decompose_unnamed4_filetest.gno | 1 + .../decompose/decompose_unnamed4b_filetest.gno | 1 + .../decompose/decompose_unnamed4c_filetest.gno | 1 + 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 312f6e8d69c..b9a61d0fa03 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -436,7 +436,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { _, ok := last.GetLocalIndex(ln) if !ok { // initial declaration to be re-defined. - last.Define(ln, anyValue(nil)) + last.Predefine(false, ln) } else { // do not redeclare. } @@ -1941,9 +1941,11 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // a,b = .decompose1, .decompose2 // assign stmt expression - // the right hand side will be converted to call expr for named/unnamed conversion, - // we make a copy of tmpExprs to prevent dsx.Lhs in the previous statement changing by the side effect - // when asx.Rhs is converted to const call expr during the preprocess of the next statement + // The right-hand side will be converted to a call expression for named/unnamed conversion. + // tmpExprs is a []Expr; we make a copy of tmpExprs to prevent dsx.Lhs in the previous statement (dsx) from being changed by side effects. + // If we don't copy tmpExprs, when asx.Rhs is converted to a const call expression during the preprocessing of the AssignStmt asx, + // dsx.Lhs will change from []NameExpr to []CallExpr. + // This side effect would cause a panic when the machine executes the dsx statement, as it expects Lhs to be []NameExpr. asx := &AssignStmt{ Lhs: n.Lhs, @@ -3258,7 +3260,7 @@ func predefineNow2(store Store, last BlockNode, d Decl, m map[Name]struct{}) (De } else { panic("should not happen") } - + // The body may get altered during preprocessing later. if !dt.TryDefineMethod(&FuncValue{ Type: ft, IsMethod: true, @@ -3486,6 +3488,7 @@ func tryPredefine(store Store, last BlockNode, d Decl) (un Name) { pkg := skipFile(last).(*PackageNode) // define a FuncValue w/ above type as d.Name. // fill in later during *FuncDecl:BLOCK. + // The body may get altered during preprocessing later. fv := &FuncValue{ Type: ft, IsMethod: false, diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno index 32f8f8a5137..4905b3d58de 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed2d_filetest.gno @@ -18,9 +18,10 @@ func y() (nat, []int) { } func main() { - // if else, for block + // else-if, for block + if false { - if true { + } else if true { u1, n2 = x() println(u1) println(n2) diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno index add1f0e32dc..06617a90ba6 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4_filetest.gno @@ -2,6 +2,7 @@ package main type nat []int +// package block var n1, u2 = x() func x() (nat, []int) { diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno index cff9c0c042a..e84fdf99567 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4b_filetest.gno @@ -2,6 +2,7 @@ package main type nat []int +// package block var n1, n2 nat = x() func x() (nat, []int) { diff --git a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno index f7f376b9c9a..863649f3705 100644 --- a/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno +++ b/gnovm/tests/files/assign_unnamed_type/decompose/decompose_unnamed4c_filetest.gno @@ -2,6 +2,7 @@ package main type nat []int +// package block var u1, u2 []int = x() func x() (nat, []int) {