From 635b2381fbe5628d207ac550d3e89963d1ec838e Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Thu, 28 Mar 2024 19:35:55 +0900 Subject: [PATCH 01/17] save --- gnovm/pkg/gnolang/gno_test.go | 26 ++-- gnovm/pkg/gnolang/preprocess.go | 9 ++ gnovm/pkg/gnolang/value_decl_dep_graph.go | 139 ++++++++++++++++++++++ 3 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 gnovm/pkg/gnolang/value_decl_dep_graph.go diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index e67d4a7024d..3be288e30f0 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -121,14 +121,26 @@ func TestRunLoopyMain(t *testing.T) { t.Parallel() m := NewMachine("test", nil) - c := `package test + c := ` +package test + func main() { - for i:=0; i<1000; i++ { - if i == -1 { - return - } - } -}` + //println(a) + //println(b) + //println(c) + + b() +} + +//var a, b, c = 1, a + 1, b + 1 + +var b = func(){println(123)} +//var c = a +//var a = "123" + +//var a, b, c = 1, a + d, 3 +//var d = a +` n := MustParseFile("main.go", c) m.RunFiles(n) m.RunMain() diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index dcb1b0856ca..f5645d3e8d8 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -77,9 +77,18 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } } } + // Finally, predefine other decls and // preprocess ValueDecls.. for _, fn := range fset.Files { + decls, err := sortValueDeps(store, fn.Decls) + + if err != nil { + panic(err) + } + + fn.Decls = decls + for i := 0; i < len(fn.Decls); i++ { d := fn.Decls[i] if d.GetAttribute(ATTR_PREDEFINED) == true { diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go new file mode 100644 index 00000000000..220064b04c7 --- /dev/null +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -0,0 +1,139 @@ +package gnolang + +import "slices" + +func sortValueDeps(store Store, decls Decls) (Decls, error) { + graph := &Graph{ + edges: make(map[string][]string), + vertices: make([]string, 0), + } + + for i := 0; i < len(decls); i++ { + d := decls[i] + vd, ok := d.(*ValueDecl) + + if !ok || d.GetAttribute(ATTR_PREDEFINED) == true { + continue + } + + for j := 0; j < len(vd.NameExprs); j++ { + graph.addVertex(string(vd.NameExprs[j].Name)) + } + } + + for i := 0; i < len(decls); i++ { + d := decls[i] + vd, ok := d.(*ValueDecl) + + if !ok || d.GetAttribute(ATTR_PREDEFINED) == true { + continue + } + + for j := 0; j < len(vd.NameExprs); j++ { + addDepFromExpr(graph, string(vd.NameExprs[j].Name), vd.Values[j]) + } + } + + sorted := make(Decls, 0) + + for _, node := range graph.topologicalSort() { + var dd Decl + + for _, decl := range decls { + vd, ok := decl.(*ValueDecl) + + if !ok || vd.GetAttribute(ATTR_PREDEFINED) == true { + continue + } + + for i, nameExpr := range vd.NameExprs { + if string(nameExpr.Name) == node { + dd = &ValueDecl{ + Attributes: vd.Attributes, + NameExprs: []NameExpr{nameExpr}, + Type: vd.Type, + Values: []Expr{vd.Values[i]}, + Const: vd.Const, + } + } + } + } + + if dd == nil { + panic("should not happen") + } + + sorted = append(sorted, dd) + } + + slices.Reverse(sorted) + + return sorted, nil +} + +func addDepFromExpr(dg *Graph, fromNode string, expr Expr) { + switch e := expr.(type) { + case *FuncLitExpr: + for _, stmt := range e.Body { + addDepFromExprStmt(dg, fromNode, stmt) + } + case *CallExpr: + addDepFromExpr(dg, fromNode, e.Func) + + for _, arg := range e.Args { + addDepFromExpr(dg, fromNode, arg) + } + case *NameExpr: + if isUverseName(e.Name) { + break + } + + toNode := string(e.Name) + dg.addEdge(fromNode, toNode) + } +} + +func addDepFromExprStmt(dg *Graph, fromNode string, stmt Stmt) { + switch e := stmt.(type) { + case *ExprStmt: + addDepFromExpr(dg, fromNode, e.X) + } +} + +type Graph struct { + edges map[string][]string + vertices []string +} + +func (g *Graph) addEdge(u, v string) { + g.edges[u] = append(g.edges[u], v) +} + +func (g *Graph) addVertex(v string) { + g.vertices = append(g.vertices, v) +} + +func (g *Graph) topologicalSortUtil(v string, visited map[string]bool, stack *[]string) { + visited[v] = true + + for _, u := range g.edges[v] { + if !visited[u] { + g.topologicalSortUtil(u, visited, stack) + } + } + + *stack = append([]string{v}, *stack...) +} + +func (g *Graph) topologicalSort() []string { + stack := make([]string, 0) + visited := make(map[string]bool) + + for _, v := range g.vertices { + if !visited[v] { + g.topologicalSortUtil(v, visited, &stack) + } + } + + return stack +} From ff8a31a59d69750d9178e09cf9fafe2d2005dc6c Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Fri, 29 Mar 2024 22:03:55 +0900 Subject: [PATCH 02/17] save --- gnovm/pkg/gnolang/gno_test.go | 15 ++++++++------- gnovm/pkg/gnolang/value_decl_dep_graph.go | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 3be288e30f0..38eacea195b 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -125,21 +125,22 @@ func TestRunLoopyMain(t *testing.T) { package test func main() { - //println(a) - //println(b) - //println(c) + println(a) + println(b) + println(c) + println(d) - b() + //b() } //var a, b, c = 1, a + 1, b + 1 -var b = func(){println(123)} +//var b = func(){println(a)} //var c = a //var a = "123" -//var a, b, c = 1, a + d, 3 -//var d = a +var a, b, c = 1, a + d, 3 +var d = a ` n := MustParseFile("main.go", c) m.RunFiles(n) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index 220064b04c7..051aeecbc8a 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -12,7 +12,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { d := decls[i] vd, ok := d.(*ValueDecl) - if !ok || d.GetAttribute(ATTR_PREDEFINED) == true { + if !ok { continue } @@ -25,7 +25,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { d := decls[i] vd, ok := d.(*ValueDecl) - if !ok || d.GetAttribute(ATTR_PREDEFINED) == true { + if !ok { continue } @@ -42,7 +42,8 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { for _, decl := range decls { vd, ok := decl.(*ValueDecl) - if !ok || vd.GetAttribute(ATTR_PREDEFINED) == true { + if !ok { + sorted = append(sorted, decl) continue } From 80c40976f768a3a3bad6704d992baae1b1a32b73 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Fri, 29 Mar 2024 22:18:13 +0900 Subject: [PATCH 03/17] save --- 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 f5645d3e8d8..09c02c314b3 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -82,7 +82,6 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // preprocess ValueDecls.. for _, fn := range fset.Files { decls, err := sortValueDeps(store, fn.Decls) - if err != nil { panic(err) } From 1dc2b9f96b9da29af96717d29defd845d973616b Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 12:49:16 +0900 Subject: [PATCH 04/17] save --- gnovm/pkg/gnolang/preprocess.go | 15 ++++++++------- gnovm/pkg/gnolang/value_decl_dep_graph.go | 8 ++++++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 09c02c314b3..e4a36436915 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -15,9 +15,17 @@ import ( func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // First, initialize all file nodes and connect to package node. for _, fn := range fset.Files { + decls, err := sortValueDeps(store, fn.Decls) + if err != nil { + panic(err) + } + + fn.Decls = decls + SetNodeLocations(pn.PkgPath, string(fn.Name), fn) fn.InitStaticBlock(fn, pn) } + // NOTE: much of what follows is duplicated for a single *FileNode // in the main Preprocess translation function. Keep synced. @@ -81,13 +89,6 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { // Finally, predefine other decls and // preprocess ValueDecls.. for _, fn := range fset.Files { - decls, err := sortValueDeps(store, fn.Decls) - if err != nil { - panic(err) - } - - fn.Decls = decls - for i := 0; i < len(fn.Decls); i++ { d := fn.Decls[i] if d.GetAttribute(ATTR_PREDEFINED) == true { diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index 051aeecbc8a..aaf81cc4ae3 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -8,11 +8,14 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { vertices: make([]string, 0), } + otherDecls := make(Decls, 0) + for i := 0; i < len(decls); i++ { d := decls[i] vd, ok := d.(*ValueDecl) if !ok { + otherDecls = append(otherDecls, d) continue } @@ -43,7 +46,6 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { vd, ok := decl.(*ValueDecl) if !ok { - sorted = append(sorted, decl) continue } @@ -69,7 +71,9 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { slices.Reverse(sorted) - return sorted, nil + otherDecls = append(otherDecls, sorted...) + + return otherDecls, nil } func addDepFromExpr(dg *Graph, fromNode string, expr Expr) { From e26ab68be748d5a5193840bcc6bb468b6997d9e1 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 12:52:51 +0900 Subject: [PATCH 05/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index aaf81cc4ae3..a06b02f6a3c 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -33,7 +33,9 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { } for j := 0; j < len(vd.NameExprs); j++ { - addDepFromExpr(graph, string(vd.NameExprs[j].Name), vd.Values[j]) + if len(vd.Values) > j { + addDepFromExpr(graph, string(vd.NameExprs[j].Name), vd.Values[j]) + } } } @@ -50,7 +52,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { } for i, nameExpr := range vd.NameExprs { - if string(nameExpr.Name) == node { + if len(vd.Values) > i && string(nameExpr.Name) == node { dd = &ValueDecl{ Attributes: vd.Attributes, NameExprs: []NameExpr{nameExpr}, From 1ec97fc82103b4bd6a24a27de3ee31eba51c2029 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 13:11:30 +0900 Subject: [PATCH 06/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index a06b02f6a3c..ded6a7c279c 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -65,7 +65,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { } if dd == nil { - panic("should not happen") + continue } sorted = append(sorted, dd) From 66a682ff3e469e36e60006312a801658bdffd22f Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 13:19:09 +0900 Subject: [PATCH 07/17] save --- gnovm/pkg/gnolang/nodes.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 8f2c5054a8a..3a18f3ea1bb 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1614,7 +1614,7 @@ func (sb *StaticBlock) GetPathForName(store Store, n Name) ValuePath { bp = bp.GetParentNode(store) gen++ if 0xff < gen { - panic("value path depth overflow") + panic("GetPathForName: value path depth overflow") } } } @@ -1641,7 +1641,7 @@ func (sb *StaticBlock) GetIsConst(store Store, n Name) bool { sb = bp.GetStaticBlock() bp = bp.GetParentNode(store) } else { - panic(fmt.Sprintf("name %s not declared", n)) + panic(fmt.Sprintf("GetIsConst: name %s not declared", n)) } } } @@ -1674,7 +1674,7 @@ func (sb *StaticBlock) GetStaticTypeOf(store Store, n Name) Type { tv := Uverse().GetValueAt(store, path) return tv.T } else { - panic(fmt.Sprintf("name %s not declared", n)) + panic(fmt.Sprintf("GetStaticTypeOf: name %s not declared", n)) } } } From a37e8d5c51b1fa58280f2b9958f40c074ba25bf5 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 17:19:14 +0900 Subject: [PATCH 08/17] save --- gnovm/pkg/gnolang/nodes.go | 17 ++++++++++++++ gnovm/pkg/gnolang/preprocess.go | 28 +++++++---------------- gnovm/pkg/gnolang/value_decl_dep_graph.go | 2 +- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 3a18f3ea1bb..9c5bcc34d57 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -158,6 +158,23 @@ type Attributes struct { data map[interface{}]interface{} // not persisted } +func (attr *Attributes) Copy() Attributes { + if attr == nil { + return Attributes{} + } + + data := make(map[interface{}]interface{}) + for k, v := range attr.data { + data[k] = v + } + + return Attributes{ + Line: attr.Line, + Label: attr.Label, + data: data, + } +} + func (attr *Attributes) GetLine() int { return attr.Line } diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index e4a36436915..d2aad215b26 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -13,7 +13,6 @@ import ( // Anything predefined or preprocessed here get skipped during the Preprocess // phase. func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { - // First, initialize all file nodes and connect to package node. for _, fn := range fset.Files { decls, err := sortValueDeps(store, fn.Decls) if err != nil { @@ -21,7 +20,10 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } fn.Decls = decls + } + // First, initialize all file nodes and connect to package node. + for _, fn := range fset.Files { SetNodeLocations(pn.PkgPath, string(fn.Name), fn) fn.InitStaticBlock(fn, pn) } @@ -37,11 +39,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { d := fn.Decls[i] switch d.(type) { case *ImportDecl: - if d.GetAttribute(ATTR_PREDEFINED) == true { - // skip declarations already predefined - // (e.g. through recursion for a - // dependent) - } else { + if d.GetAttribute(ATTR_PREDEFINED) != true { // recursively predefine dependencies. d2, _ := predefineNow(store, fn, d) fn.Decls[i] = d2 @@ -49,17 +47,14 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { } } } + // Predefine all type decls decls. for _, fn := range fset.Files { for i := 0; i < len(fn.Decls); i++ { d := fn.Decls[i] switch d.(type) { case *TypeDecl: - if d.GetAttribute(ATTR_PREDEFINED) == true { - // skip declarations already predefined - // (e.g. through recursion for a - // dependent) - } else { + if d.GetAttribute(ATTR_PREDEFINED) != true { // recursively predefine dependencies. d2, _ := predefineNow(store, fn, d) fn.Decls[i] = d2 @@ -73,11 +68,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { d := fn.Decls[i] switch d.(type) { case *FuncDecl: - if d.GetAttribute(ATTR_PREDEFINED) == true { - // skip declarations already predefined - // (e.g. through recursion for a - // dependent) - } else { + if d.GetAttribute(ATTR_PREDEFINED) != true { // recursively predefine dependencies. d2, _ := predefineNow(store, fn, d) fn.Decls[i] = d2 @@ -91,10 +82,7 @@ func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { for _, fn := range fset.Files { for i := 0; i < len(fn.Decls); i++ { d := fn.Decls[i] - if d.GetAttribute(ATTR_PREDEFINED) == true { - // skip declarations already predefined (e.g. - // through recursion for a dependent) - } else { + if d.GetAttribute(ATTR_PREDEFINED) != true { // recursively predefine dependencies. d2, _ := predefineNow(store, fn, d) fn.Decls[i] = d2 diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index ded6a7c279c..cc0184d9114 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -54,7 +54,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { for i, nameExpr := range vd.NameExprs { if len(vd.Values) > i && string(nameExpr.Name) == node { dd = &ValueDecl{ - Attributes: vd.Attributes, + Attributes: vd.Attributes.Copy(), NameExprs: []NameExpr{nameExpr}, Type: vd.Type, Values: []Expr{vd.Values[i]}, From 1391a93558c4bcfa417182e759008c349af0daa6 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Sat, 30 Mar 2024 17:48:15 +0900 Subject: [PATCH 09/17] save --- gnovm/pkg/gnolang/nodes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index 9c5bcc34d57..5d430a8bcde 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -1658,7 +1658,7 @@ func (sb *StaticBlock) GetIsConst(store Store, n Name) bool { sb = bp.GetStaticBlock() bp = bp.GetParentNode(store) } else { - panic(fmt.Sprintf("GetIsConst: name %s not declared", n)) + panic(fmt.Sprintf("name %s not declared", n)) } } } @@ -1691,7 +1691,7 @@ func (sb *StaticBlock) GetStaticTypeOf(store Store, n Name) Type { tv := Uverse().GetValueAt(store, path) return tv.T } else { - panic(fmt.Sprintf("GetStaticTypeOf: name %s not declared", n)) + panic(fmt.Sprintf("name %s not declared", n)) } } } From 05f7828249f2caaab43286abb56f117eccfb0366 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 1 Apr 2024 09:57:08 +0200 Subject: [PATCH 10/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index cc0184d9114..328e5b53c11 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -52,13 +52,17 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { } for i, nameExpr := range vd.NameExprs { - if len(vd.Values) > i && string(nameExpr.Name) == node { - dd = &ValueDecl{ - Attributes: vd.Attributes.Copy(), - NameExprs: []NameExpr{nameExpr}, - Type: vd.Type, - Values: []Expr{vd.Values[i]}, - Const: vd.Const, + if string(nameExpr.Name) == node { + if len(vd.Values) > i { + dd = &ValueDecl{ + Attributes: vd.Attributes.Copy(), + NameExprs: []NameExpr{nameExpr}, + Type: vd.Type, + Values: []Expr{vd.Values[i]}, + Const: vd.Const, + } + } else { + dd = vd } } } From 81700000cb592ec57bed04e34febcbb9a1151637 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 1 Apr 2024 16:15:50 +0200 Subject: [PATCH 11/17] save --- gnovm/pkg/gnolang/gno_test.go | 27 ++++--------- gnovm/pkg/gnolang/value_decl_dep_graph.go | 48 ++++++++++++++++++++++- gnovm/tests/files/var18.gno | 14 +++++++ gnovm/tests/files/var19.gno | 14 +++++++ gnovm/tests/files/var20.gno | 17 ++++++++ gnovm/tests/files/var21.gno | 15 +++++++ 6 files changed, 114 insertions(+), 21 deletions(-) create mode 100644 gnovm/tests/files/var18.gno create mode 100644 gnovm/tests/files/var19.gno create mode 100644 gnovm/tests/files/var20.gno create mode 100644 gnovm/tests/files/var21.gno diff --git a/gnovm/pkg/gnolang/gno_test.go b/gnovm/pkg/gnolang/gno_test.go index 38eacea195b..e67d4a7024d 100644 --- a/gnovm/pkg/gnolang/gno_test.go +++ b/gnovm/pkg/gnolang/gno_test.go @@ -121,27 +121,14 @@ func TestRunLoopyMain(t *testing.T) { t.Parallel() m := NewMachine("test", nil) - c := ` -package test - + c := `package test func main() { - println(a) - println(b) - println(c) - println(d) - - //b() -} - -//var a, b, c = 1, a + 1, b + 1 - -//var b = func(){println(a)} -//var c = a -//var a = "123" - -var a, b, c = 1, a + d, 3 -var d = a -` + for i:=0; i<1000; i++ { + if i == -1 { + return + } + } +}` n := MustParseFile("main.go", c) m.RunFiles(n) m.RunMain() diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index 328e5b53c11..dc67e44f744 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -1,6 +1,10 @@ package gnolang -import "slices" +import ( + "fmt" + "slices" + "strings" +) func sortValueDeps(store Store, decls Decls) (Decls, error) { graph := &Graph{ @@ -19,6 +23,14 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } + if len(vd.NameExprs) > len(vd.Values) && len(vd.Values) > 0 { + _, ok := vd.Values[0].(*CallExpr) + if ok { + graph.addVertex(vd.NameExprs.String()) + continue + } + } + for j := 0; j < len(vd.NameExprs); j++ { graph.addVertex(string(vd.NameExprs[j].Name)) } @@ -32,6 +44,14 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } + if len(vd.NameExprs) > len(vd.Values) && len(vd.Values) > 0 { + ce, ok := vd.Values[0].(*CallExpr) + if ok { + addDepFromExpr(graph, vd.NameExprs.String(), ce) + continue + } + } + for j := 0; j < len(vd.NameExprs); j++ { if len(vd.Values) > j { addDepFromExpr(graph, string(vd.NameExprs[j].Name), vd.Values[j]) @@ -51,6 +71,30 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } + if strings.Contains(node, ", ") { + names := strings.Split(node, ", ") + + if len(names) != len(vd.NameExprs) { + panic("1should not happen") + } + + equal := true + + for i, name := range names { + if vd.NameExprs[i].String() != name { + equal = false + break + } + } + + if !equal { + panic(fmt.Sprintf("names: %+v != nameExprs: %+v\n", names, vd.NameExprs)) + } + + dd = decl + break + } + for i, nameExpr := range vd.NameExprs { if string(nameExpr.Name) == node { if len(vd.Values) > i { @@ -61,8 +105,10 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { Values: []Expr{vd.Values[i]}, Const: vd.Const, } + break } else { dd = vd + break } } } diff --git a/gnovm/tests/files/var18.gno b/gnovm/tests/files/var18.gno new file mode 100644 index 00000000000..619aedef779 --- /dev/null +++ b/gnovm/tests/files/var18.gno @@ -0,0 +1,14 @@ +package main + +func main() { + println(a) + println(b) +} + +func r2() (int, int) { return 1, 2 } + +var a, b int = r2() + +// Output: +// 1 +// 2 diff --git a/gnovm/tests/files/var19.gno b/gnovm/tests/files/var19.gno new file mode 100644 index 00000000000..f26c230de0d --- /dev/null +++ b/gnovm/tests/files/var19.gno @@ -0,0 +1,14 @@ +package main + +func main() { + println(a) + println(b) + println(c) +} + +var a, b, c = 1, a + 1, b + 1 + +// Output: +// 1 +// 2 +// 3 diff --git a/gnovm/tests/files/var20.gno b/gnovm/tests/files/var20.gno new file mode 100644 index 00000000000..1aec4792fcb --- /dev/null +++ b/gnovm/tests/files/var20.gno @@ -0,0 +1,17 @@ +package main + +func main() { + println(a) + println(b) + println(c) + println(d) +} + +var a, b, c = 1, a + d, 3 +var d = a + +// Output: +// 1 +// 2 +// 3 +// 1 diff --git a/gnovm/tests/files/var21.gno b/gnovm/tests/files/var21.gno new file mode 100644 index 00000000000..7cc6e60beca --- /dev/null +++ b/gnovm/tests/files/var21.gno @@ -0,0 +1,15 @@ +package main + +func main() { + myDep = "123" + myVar() +} + +func hello(s string) {} + +var myVar = func() { hello(myDep) } + +var myDep string + +// Output: +// 123 From f30454e3da8ed4479b0bbd6bbd7c5979ec60772b Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 1 Apr 2024 16:19:06 +0200 Subject: [PATCH 12/17] save --- gnovm/tests/files/var21.gno | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gnovm/tests/files/var21.gno b/gnovm/tests/files/var21.gno index 7cc6e60beca..7ec32e1ebfa 100644 --- a/gnovm/tests/files/var21.gno +++ b/gnovm/tests/files/var21.gno @@ -5,7 +5,9 @@ func main() { myVar() } -func hello(s string) {} +func hello(s string) { + println(s) +} var myVar = func() { hello(myDep) } From 5d177f92af6fee97efc3aac3f04ef5498799e0ed Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 1 Apr 2024 16:34:40 +0200 Subject: [PATCH 13/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 62 ++++++++++++++--------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index dc67e44f744..fb61e2eac35 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -6,7 +6,9 @@ import ( "strings" ) -func sortValueDeps(store Store, decls Decls) (Decls, error) { +// sortValueDeps creates a new topologically sorted +// decl slice ready for processing in order +func sortValueDeps(decls Decls) (Decls, error) { graph := &Graph{ edges: make(map[string][]string), vertices: make([]string, 0), @@ -23,7 +25,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } - if len(vd.NameExprs) > len(vd.Values) && len(vd.Values) > 0 { + if isTuple(vd) { _, ok := vd.Values[0].(*CallExpr) if ok { graph.addVertex(vd.NameExprs.String()) @@ -44,7 +46,7 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } - if len(vd.NameExprs) > len(vd.Values) && len(vd.Values) > 0 { + if isTuple(vd) { ce, ok := vd.Values[0].(*CallExpr) if ok { addDepFromExpr(graph, vd.NameExprs.String(), ce) @@ -71,27 +73,8 @@ func sortValueDeps(store Store, decls Decls) (Decls, error) { continue } - if strings.Contains(node, ", ") { - names := strings.Split(node, ", ") - - if len(names) != len(vd.NameExprs) { - panic("1should not happen") - } - - equal := true - - for i, name := range names { - if vd.NameExprs[i].String() != name { - equal = false - break - } - } - - if !equal { - panic(fmt.Sprintf("names: %+v != nameExprs: %+v\n", names, vd.NameExprs)) - } - - dd = decl + if isCompoundNode(node) { + dd = processCompound(node, vd, decl) break } @@ -194,3 +177,34 @@ func (g *Graph) topologicalSort() []string { return stack } + +func isTuple(vd *ValueDecl) bool { + return len(vd.NameExprs) > len(vd.Values) && len(vd.Values) > 0 +} + +func isCompoundNode(node string) bool { + return strings.Contains(node, ", ") +} + +func processCompound(node string, vd *ValueDecl, decl Decl) Decl { + names := strings.Split(node, ", ") + + if len(names) != len(vd.NameExprs) { + panic("1should not happen") + } + + equal := true + + for i, name := range names { + if vd.NameExprs[i].String() != name { + equal = false + break + } + } + + if !equal { + panic(fmt.Sprintf("names: %+v != nameExprs: %+v\n", names, vd.NameExprs)) + } + + return decl +} From 06ba98db0a66c6876e4c255cdd8a63ddd12a1ce6 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Mon, 1 Apr 2024 16:36:15 +0200 Subject: [PATCH 14/17] save --- gnovm/pkg/gnolang/preprocess.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index d2aad215b26..fc32a9020ea 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -14,7 +14,7 @@ import ( // phase. func PredefineFileSet(store Store, pn *PackageNode, fset *FileSet) { for _, fn := range fset.Files { - decls, err := sortValueDeps(store, fn.Decls) + decls, err := sortValueDeps(fn.Decls) if err != nil { panic(err) } From ff046a4d29f805e054c504752df87a47103034c5 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Tue, 9 Apr 2024 13:39:17 +0200 Subject: [PATCH 15/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index fb61e2eac35..be26872b368 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -137,6 +137,41 @@ func addDepFromExprStmt(dg *Graph, fromNode string, stmt Stmt) { switch e := stmt.(type) { case *ExprStmt: addDepFromExpr(dg, fromNode, e.X) + case *IfStmt: + addDepFromExprStmt(dg, fromNode, e.Init) + addDepFromExpr(dg, fromNode, e.Cond) + + for _, stm := range e.Then.Body { + addDepFromExprStmt(dg, fromNode, stm) + } + for _, stm := range e.Else.Body { + addDepFromExprStmt(dg, fromNode, stm) + } + case *ReturnStmt: + for _, stm := range e.Results { + addDepFromExpr(dg, fromNode, stm) + } + case *AssignStmt: + for _, stm := range e.Rhs { + addDepFromExpr(dg, fromNode, stm) + } + case *SwitchStmt: + addDepFromExpr(dg, fromNode, e.X) + for _, clause := range e.Clauses { + addDepFromExpr(dg, fromNode, clause.bodyStmt.Cond) + for _, s := range clause.bodyStmt.Body { + addDepFromExprStmt(dg, fromNode, s) + } + } + case *ForStmt: + addDepFromExpr(dg, fromNode, e.Cond) + for _, s := range e.bodyStmt.Body { + addDepFromExprStmt(dg, fromNode, s) + } + case *BlockStmt: + for _, s := range e.Block.bodyStmt.Body { + addDepFromExprStmt(dg, fromNode, s) + } } } From 4c9508fd6b986d0f044c8aa4506e6f6948a7698d Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Tue, 9 Apr 2024 13:42:44 +0200 Subject: [PATCH 16/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index be26872b368..2075def22da 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -9,7 +9,7 @@ import ( // sortValueDeps creates a new topologically sorted // decl slice ready for processing in order func sortValueDeps(decls Decls) (Decls, error) { - graph := &Graph{ + graph := &graph{ edges: make(map[string][]string), vertices: make([]string, 0), } @@ -111,7 +111,7 @@ func sortValueDeps(decls Decls) (Decls, error) { return otherDecls, nil } -func addDepFromExpr(dg *Graph, fromNode string, expr Expr) { +func addDepFromExpr(dg *graph, fromNode string, expr Expr) { switch e := expr.(type) { case *FuncLitExpr: for _, stmt := range e.Body { @@ -133,7 +133,7 @@ func addDepFromExpr(dg *Graph, fromNode string, expr Expr) { } } -func addDepFromExprStmt(dg *Graph, fromNode string, stmt Stmt) { +func addDepFromExprStmt(dg *graph, fromNode string, stmt Stmt) { switch e := stmt.(type) { case *ExprStmt: addDepFromExpr(dg, fromNode, e.X) @@ -175,20 +175,20 @@ func addDepFromExprStmt(dg *Graph, fromNode string, stmt Stmt) { } } -type Graph struct { +type graph struct { edges map[string][]string vertices []string } -func (g *Graph) addEdge(u, v string) { +func (g *graph) addEdge(u, v string) { g.edges[u] = append(g.edges[u], v) } -func (g *Graph) addVertex(v string) { +func (g *graph) addVertex(v string) { g.vertices = append(g.vertices, v) } -func (g *Graph) topologicalSortUtil(v string, visited map[string]bool, stack *[]string) { +func (g *graph) topologicalSortUtil(v string, visited map[string]bool, stack *[]string) { visited[v] = true for _, u := range g.edges[v] { @@ -200,7 +200,7 @@ func (g *Graph) topologicalSortUtil(v string, visited map[string]bool, stack *[] *stack = append([]string{v}, *stack...) } -func (g *Graph) topologicalSort() []string { +func (g *graph) topologicalSort() []string { stack := make([]string, 0) visited := make(map[string]bool) From fd9cea4e87e887eaaae358183c229d0c99439f6f Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Tue, 9 Apr 2024 13:43:36 +0200 Subject: [PATCH 17/17] save --- gnovm/pkg/gnolang/value_decl_dep_graph.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnovm/pkg/gnolang/value_decl_dep_graph.go b/gnovm/pkg/gnolang/value_decl_dep_graph.go index 2075def22da..fe130dbf43a 100644 --- a/gnovm/pkg/gnolang/value_decl_dep_graph.go +++ b/gnovm/pkg/gnolang/value_decl_dep_graph.go @@ -225,7 +225,7 @@ func processCompound(node string, vd *ValueDecl, decl Decl) Decl { names := strings.Split(node, ", ") if len(names) != len(vd.NameExprs) { - panic("1should not happen") + panic("should not happen") } equal := true