Repository: goplus/gop
Pull request #1575 (2023-12-12 14:23:09)

cl: compileForPhraseStmt types record define kv


Patch:
diff --git a/cl/stmt.go b/cl/stmt.go
index 149365ab..8bb4a30c 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -384,17 +384,23 @@ func compileForPhraseStmt(ctx *blockCtx, v *ast.ForPhraseStmt) {
 	cb := ctx.cb
 	comments, once := cb.BackupComments()
 	names := make([]string, 1, 2)
+	defineNames := make([]*ast.Ident, 0, 2)
 	if v.Key == nil {
 		names[0] = "_"
 	} else {
 		names[0] = v.Key.Name
+		defineNames = append(defineNames, v.Key)
 	}
 	if v.Value != nil {
 		names = append(names, v.Value.Name)
+		defineNames = append(defineNames, v.Value)
 	}
 	cb.ForRange(names...)
 	compileExpr(ctx, v.X)
 	cb.RangeAssignThen(v.TokPos)
+	if len(defineNames) > 0 {
+		defNames(ctx, defineNames, cb.Scope())
+	}
 	if v.Cond != nil {
 		cb.If()
 		compileExpr(ctx, v.Cond)


Test patch:
diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go
index f69f6ddf..1ce5a7d8 100644
--- a/x/typesutil/info_test.go
+++ b/x/typesutil/info_test.go
@@ -23,6 +23,50 @@ import (
 	"github.com/goplus/mod/gopmod"
 )
 
+func parserMixedSource(fset *token.FileSet, src string, gosrc string) (*typesutil.Info, *types.Info, error) {
+	f, err := parser.ParseEntry(fset, "main.gop", src, parser.Config{
+		Mode: parser.ParseComments,
+	})
+	if err != nil {
+		return nil, nil, err
+	}
+	var gofiles []*goast.File
+	if len(gosrc) > 0 {
+		f, err := goparser.ParseFile(fset, "main.go", gosrc, goparser.ParseComments)
+		if err != nil {
+			return nil, nil, err
+		}
+		gofiles = append(gofiles, f)
+	}
+
+	conf := &types.Config{}
+	conf.Importer = importer.Default()
+	chkOpts := &typesutil.Config{
+		Types: types.NewPackage("main", "main"),
+		Fset:  fset,
+		Mod:   gopmod.Default,
+	}
+	info := &typesutil.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Implicits:  make(map[ast.Node]types.Object),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+		Scopes:     make(map[ast.Node]*types.Scope),
+	}
+	ginfo := &types.Info{
+		Types:      make(map[goast.Expr]types.TypeAndValue),
+		Defs:       make(map[*goast.Ident]types.Object),
+		Uses:       make(map[*goast.Ident]types.Object),
+		Implicits:  make(map[goast.Node]types.Object),
+		Selections: make(map[*goast.SelectorExpr]*types.Selection),
+		Scopes:     make(map[goast.Node]*types.Scope),
+	}
+	check := typesutil.NewChecker(conf, chkOpts, ginfo, info)
+	err = check.Files(gofiles, []*ast.File{f})
+	return info, ginfo, err
+}
+
 func parserSource(fset *token.FileSet, filename string, src interface{}, mode parser.Mode) (*typesutil.Info, error) {
 	f, err := parser.ParseEntry(fset, filename, src, parser.Config{
 		Mode: mode,
@@ -73,6 +117,26 @@ func parserGoSource(fset *token.FileSet, filename string, src interface{}, mode
 	return info, err
 }
 
+func testGopInfo(t *testing.T, src string, gosrc string, expect string) {
+	fset := token.NewFileSet()
+	info, _, err := parserMixedSource(fset, src, gosrc)
+	if err != nil {
+		t.Fatal("parserMixedSource error", err)
+	}
+	var list []string
+	list = append(list, "== types ==")
+	list = append(list, typesList(fset, info.Types, false)...)
+	list = append(list, "== defs ==")
+	list = append(list, defsList(fset, info.Defs, true)...)
+	list = append(list, "== uses ==")
+	list = append(list, usesList(fset, info.Uses)...)
+	result := strings.Join(list, "\n")
+	t.Log(result)
+	if result != expect {
+		t.Fatal("bad expect\n", expect)
+	}
+}
+
 func testInfo(t *testing.T, src interface{}) {
 	fset := token.NewFileSet()
 	info, err := parserSource(fset, "main.gop", src, parser.ParseComments)
@@ -440,3 +504,107 @@ func test() {
 }
 `)
 }
+
+func TestSliceLit(t *testing.T) {
+	testGopInfo(t, `
+a := [100,200]
+println a
+`, ``, `== types ==
+000:  2: 7 | 100                 *ast.BasicLit                  | value   : untyped int = 100 | constant
+001:  2:11 | 200                 *ast.BasicLit                  | value   : untyped int = 200 | constant
+002:  3: 1 | println             *ast.Ident                     | builtin : invalid type | built-in
+003:  3: 1 | println a           *ast.CallExpr                  | value   : (n int, err error) | value
+004:  3: 9 | a                   *ast.Ident                     | var     : []int | variable
+== defs ==
+000:  2: 1 | a                   | var a []int
+001:  2: 1 | main                | func main.main()
+== uses ==
+000:  3: 1 | println             | builtin println
+001:  3: 9 | a                   | var a []int`)
+}
+
+func TestForPhrase1(t *testing.T) {
+	testGopInfo(t, `
+sum := 0
+for x <- [1, 3, 5, 7, 11, 13, 17], x > 3 {
+	sum = sum + x
+}
+println sum
+`, ``, `== types ==
+000:  2: 8 | 0                   *ast.BasicLit                  | value   : untyped int = 0 | constant
+001:  3:11 | 1                   *ast.BasicLit                  | value   : untyped int = 1 | constant
+002:  3:14 | 3                   *ast.BasicLit                  | value   : untyped int = 3 | constant
+003:  3:17 | 5                   *ast.BasicLit                  | value   : untyped int = 5 | constant
+004:  3:20 | 7                   *ast.BasicLit                  | value   : untyped int = 7 | constant
+005:  3:23 | 11                  *ast.BasicLit                  | value   : untyped int = 11 | constant
+006:  3:27 | 13                  *ast.BasicLit                  | value   : untyped int = 13 | constant
+007:  3:31 | 17                  *ast.BasicLit                  | value   : untyped int = 17 | constant
+008:  3:36 | x                   *ast.Ident                     | var     : int | variable
+009:  3:36 | x > 3               *ast.BinaryExpr                | value   : untyped bool | value
+010:  3:40 | 3                   *ast.BasicLit                  | value   : untyped int = 3 | constant
+011:  4: 2 | sum                 *ast.Ident                     | var     : int | variable
+012:  4: 8 | sum                 *ast.Ident                     | var     : int | variable
+013:  4: 8 | sum + x             *ast.BinaryExpr                | value   : int | value
+014:  4:14 | x                   *ast.Ident                     | var     : int | variable
+015:  6: 1 | println             *ast.Ident                     | builtin : invalid type | built-in
+016:  6: 1 | println sum         *ast.CallExpr                  | value   : (n int, err error) | value
+017:  6: 9 | sum                 *ast.Ident                     | var     : int | variable
+== defs ==
+000:  2: 1 | main                | func main.main()
+001:  2: 1 | sum                 | var sum int
+002:  3: 5 | x                   | var x int
+== uses ==
+000:  3:36 | x                   | var x int
+001:  4: 2 | sum                 | var sum int
+002:  4: 8 | sum                 | var sum int
+003:  4:14 | x                   | var x int
+004:  6: 1 | println             | builtin println
+005:  6: 9 | sum                 | var sum int`)
+}
+
+func TestForPhrase2(t *testing.T) {
+	testGopInfo(t, `
+sum := 0
+for i, x <- [1, 3, 5, 7, 11, 13, 17], i%2 == 1 && x > 3 {
+	sum = sum + x
+}
+println sum
+`, ``, `== types ==
+000:  2: 8 | 0                   *ast.BasicLit                  | value   : untyped int = 0 | constant
+001:  3:14 | 1                   *ast.BasicLit                  | value   : untyped int = 1 | constant
+002:  3:17 | 3                   *ast.BasicLit                  | value   : untyped int = 3 | constant
+003:  3:20 | 5                   *ast.BasicLit                  | value   : untyped int = 5 | constant
+004:  3:23 | 7                   *ast.BasicLit                  | value   : untyped int = 7 | constant
+005:  3:26 | 11                  *ast.BasicLit                  | value   : untyped int = 11 | constant
+006:  3:30 | 13                  *ast.BasicLit                  | value   : untyped int = 13 | constant
+007:  3:34 | 17                  *ast.BasicLit                  | value   : untyped int = 17 | constant
+008:  3:39 | i                   *ast.Ident                     | var     : int | variable
+009:  3:39 | i % 2               *ast.BinaryExpr                | value   : int | value
+010:  3:39 | i%2 == 1            *ast.BinaryExpr                | value   : untyped bool | value
+011:  3:39 | i%2 == 1 && x > 3   *ast.BinaryExpr                | value   : untyped bool | value
+012:  3:41 | 2                   *ast.BasicLit                  | value   : untyped int = 2 | constant
+013:  3:46 | 1                   *ast.BasicLit                  | value   : untyped int = 1 | constant
+014:  3:51 | x                   *ast.Ident                     | var     : int | variable
+015:  3:51 | x > 3               *ast.BinaryExpr                | value   : untyped bool | value
+016:  3:55 | 3                   *ast.BasicLit                  | value   : untyped int = 3 | constant
+017:  4: 2 | sum                 *ast.Ident                     | var     : int | variable
+018:  4: 8 | sum                 *ast.Ident                     | var     : int | variable
+019:  4: 8 | sum + x             *ast.BinaryExpr                | value   : int | value
+020:  4:14 | x                   *ast.Ident                     | var     : int | variable
+021:  6: 1 | println             *ast.Ident                     | builtin : invalid type | built-in
+022:  6: 1 | println sum         *ast.CallExpr                  | value   : (n int, err error) | value
+023:  6: 9 | sum                 *ast.Ident                     | var     : int | variable
+== defs ==
+000:  2: 1 | main                | func main.main()
+001:  2: 1 | sum                 | var sum int
+002:  3: 5 | i                   | var i int
+003:  3: 8 | x                   | var x int
+== uses ==
+000:  3:39 | i                   | var i int
+001:  3:51 | x                   | var x int
+002:  4: 2 | sum                 | var sum int
+003:  4: 8 | sum                 | var sum int
+004:  4:14 | x                   | var x int
+005:  6: 1 | println             | builtin println
+006:  6: 9 | sum                 | var sum int`)
+}