github.com/goplus/gogen@v1.16.0/package_test.go (about)

     1  /*
     2   Copyright 2021 The GoPlus Authors (goplus.org)
     3   Licensed under the Apache License, Version 2.0 (the "License");
     4   you may not use this file except in compliance with the License.
     5   You may obtain a copy of the License at
     6       http://www.apache.org/licenses/LICENSE-2.0
     7   Unless required by applicable law or agreed to in writing, software
     8   distributed under the License is distributed on an "AS IS" BASIS,
     9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10   See the License for the specific language governing permissions and
    11   limitations under the License.
    12  */
    13  
    14  package gogen_test
    15  
    16  import (
    17  	"bytes"
    18  	"go/ast"
    19  	"go/constant"
    20  	"go/parser"
    21  	"go/token"
    22  	"go/types"
    23  	"log"
    24  	"os"
    25  	"syscall"
    26  	"testing"
    27  	"unsafe"
    28  
    29  	"github.com/goplus/gogen"
    30  	"github.com/goplus/gogen/packages"
    31  	"golang.org/x/tools/go/gcexportdata"
    32  )
    33  
    34  var (
    35  	gblFset   *token.FileSet
    36  	gblImp    types.Importer
    37  	handleErr func(err error)
    38  )
    39  
    40  func init() {
    41  	gogen.SetDebug(gogen.DbgFlagAll)
    42  	gblFset = token.NewFileSet()
    43  	gblImp = packages.NewImporter(gblFset)
    44  }
    45  
    46  func ctxRef(pkg *gogen.Package, name string) gogen.Ref {
    47  	_, o := pkg.CB().Scope().LookupParent(name, token.NoPos)
    48  	return o
    49  }
    50  
    51  type eventRecorder struct{}
    52  
    53  func (p eventRecorder) Member(id ast.Node, obj types.Object) {}
    54  func (p eventRecorder) Call(fn ast.Node, obj types.Object)   {}
    55  
    56  func newMainPackage(
    57  	implicitCast ...func(pkg *gogen.Package, V, T types.Type, pv *gogen.Element) bool) *gogen.Package {
    58  	return newPackage("main", implicitCast...)
    59  }
    60  
    61  func newPackage(
    62  	name string, implicitCast ...func(pkg *gogen.Package, V, T types.Type, pv *gogen.Element) bool) *gogen.Package {
    63  	conf := &gogen.Config{
    64  		Fset:            gblFset,
    65  		Importer:        gblImp,
    66  		Recorder:        eventRecorder{},
    67  		NodeInterpreter: nodeInterp{},
    68  		DbgPositioner:   nodeInterp{},
    69  	}
    70  	if len(implicitCast) > 0 {
    71  		conf.CanImplicitCast = implicitCast[0]
    72  	}
    73  	if handleErr != nil {
    74  		conf.HandleErr = handleErr
    75  		handleErr = nil
    76  	}
    77  	return gogen.NewPackage("", name, conf)
    78  }
    79  
    80  func domTest(t *testing.T, pkg *gogen.Package, expected string) {
    81  	domTestEx(t, pkg, expected, "")
    82  }
    83  
    84  func domTestEx(t *testing.T, pkg *gogen.Package, expected string, fname string) {
    85  	var b bytes.Buffer
    86  	t.Helper()
    87  	err := gogen.WriteTo(&b, pkg, fname)
    88  	if err != nil {
    89  		t.Fatal("gogen.WriteTo failed:", err)
    90  	}
    91  	result := b.String()
    92  	if result != expected {
    93  		t.Fatalf("\nResult:\n%s\nExpected:\n%s\n", result, expected)
    94  	}
    95  	log.Printf("====================== %s End =========================\n", t.Name())
    96  }
    97  
    98  type importer struct {
    99  	packages map[string]*types.Package
   100  	imp      types.Importer
   101  }
   102  
   103  func (i *importer) Import(path string) (*types.Package, error) {
   104  	if pkg, ok := i.packages[path]; ok {
   105  		return pkg, nil
   106  	}
   107  	return i.imp.Import(path)
   108  }
   109  
   110  type goxTest struct {
   111  	fset *token.FileSet
   112  	imp  *importer
   113  }
   114  
   115  func newGoxTest() *goxTest {
   116  	fset := token.NewFileSet()
   117  	return &goxTest{
   118  		fset: fset,
   119  		imp: &importer{
   120  			packages: make(map[string]*types.Package),
   121  			imp:      packages.NewImporter(fset),
   122  		},
   123  	}
   124  }
   125  
   126  func (p *goxTest) LoadGoPackage(pkgPath string, filename string, src string) (*types.Package, error) {
   127  	if src == "" {
   128  		return p.imp.imp.Import(pkgPath)
   129  	}
   130  	f, err := parser.ParseFile(p.fset, filename, src, 0)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  	conf := types.Config{Importer: p.imp}
   135  	pkg, err := conf.Check(pkgPath, p.fset, []*ast.File{f}, nil)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	p.imp.packages[pkgPath] = pkg
   140  	return pkg, nil
   141  }
   142  
   143  func (p *goxTest) NewPackage(pkgPath string, name string) *gogen.Package {
   144  	conf := &gogen.Config{
   145  		Fset:            p.fset,
   146  		Importer:        p.imp,
   147  		NodeInterpreter: nodeInterp{},
   148  		DbgPositioner:   nodeInterp{},
   149  	}
   150  	return gogen.NewPackage(pkgPath, name, conf)
   151  }
   152  
   153  type goxVar = types.Var
   154  
   155  // ----------------------------------------------------------------------------
   156  
   157  func TestRedupPkgIssue796(t *testing.T) {
   158  	pkg := newMainPackage()
   159  	builtin := pkg.Import("github.com/goplus/gogen/internal/builtin")
   160  	builtin.EnsureImported()
   161  	context := pkg.Import("context")
   162  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   163  		Val(context.Ref("WithTimeout")).
   164  		Val(context.Ref("Background")).Call(0).
   165  		Val(pkg.Import("time").Ref("Minute")).Call(2).EndStmt().
   166  		End()
   167  	domTest(t, pkg, `package main
   168  
   169  import (
   170  	"context"
   171  	"time"
   172  )
   173  
   174  func main() {
   175  	context.WithTimeout(context.Background(), time.Minute)
   176  }
   177  `)
   178  }
   179  
   180  func TestBTIMethod(t *testing.T) {
   181  	pkg := newMainPackage()
   182  	fmt := pkg.Import("fmt")
   183  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   184  		NewVar(types.NewChan(0, types.Typ[types.Int]), "a").
   185  		NewVar(types.NewSlice(types.Typ[types.Int]), "b").
   186  		NewVar(types.NewSlice(types.Typ[types.String]), "c").
   187  		NewVar(types.NewMap(types.Typ[types.String], types.Typ[types.Int]), "d").
   188  		NewVar(types.Typ[types.Int64], "e").
   189  		Val(fmt.Ref("Println")).VarVal("a").MemberVal("Len").Call(0).Call(1).EndStmt().
   190  		Val(fmt.Ref("Println")).VarVal("b").MemberVal("Len").Call(0).Call(1).EndStmt().
   191  		Val(fmt.Ref("Println")).VarVal("c").MemberVal("Len").Call(0).Call(1).EndStmt().
   192  		Val(fmt.Ref("Println")).VarVal("d").MemberVal("Len").Call(0).Call(1).EndStmt().
   193  		Val(fmt.Ref("Println")).VarVal("c").MemberVal("Join").Val(",").Call(1).Call(1).EndStmt().
   194  		Val(fmt.Ref("Println")).Val("Hi").MemberVal("Len").Call(0).Call(1).EndStmt().
   195  		Val(fmt.Ref("Println")).Val("100").MemberVal("Int").Call(0).Call(1).EndStmt().
   196  		Val(fmt.Ref("Println")).Val("100").MemberVal("Uint64").Call(0).Call(1).EndStmt().
   197  		Val(fmt.Ref("Println")).Val(100).MemberVal("String").Call(0).Call(1).EndStmt().
   198  		Val(fmt.Ref("Println")).Val(1.34).MemberVal("String").Call(0).Call(1).EndStmt().
   199  		Val(fmt.Ref("Println")).VarVal("e").Debug(
   200  		func(cb *gogen.CodeBuilder) {
   201  			cb.Member("string", gogen.MemberFlagAutoProperty)
   202  		}).Call(1).EndStmt().
   203  		End()
   204  	domTest(t, pkg, `package main
   205  
   206  import (
   207  	"fmt"
   208  	"strconv"
   209  	"strings"
   210  )
   211  
   212  func main() {
   213  	var a chan int
   214  	var b []int
   215  	var c []string
   216  	var d map[string]int
   217  	var e int64
   218  	fmt.Println(len(a))
   219  	fmt.Println(len(b))
   220  	fmt.Println(len(c))
   221  	fmt.Println(len(d))
   222  	fmt.Println(strings.Join(c, ","))
   223  	fmt.Println(len("Hi"))
   224  	fmt.Println(strconv.Atoi("100"))
   225  	fmt.Println(strconv.ParseUint("100", 10, 64))
   226  	fmt.Println(strconv.Itoa(100))
   227  	fmt.Println(strconv.FormatFloat(1.34, 'g', -1, 64))
   228  	fmt.Println(strconv.FormatInt(e, 10))
   229  }
   230  `)
   231  }
   232  
   233  func TestTypedBTIMethod(t *testing.T) {
   234  	pkg := newMainPackage()
   235  	fmt := pkg.Import("fmt")
   236  	tyInt := pkg.NewType("MyInt").InitType(pkg, types.Typ[types.Int])
   237  	tyInt64 := pkg.NewType("MyInt64").InitType(pkg, types.Typ[types.Int64])
   238  	tyUint64 := pkg.NewType("MyUint64").InitType(pkg, types.Typ[types.Uint64])
   239  	tyFloat64 := pkg.NewType("MyFloat64").InitType(pkg, types.Typ[types.Float64])
   240  	tyString := pkg.NewType("MyString").InitType(pkg, types.Typ[types.String])
   241  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   242  		NewVar(tyInt, "a").
   243  		NewVar(tyInt64, "b").
   244  		NewVar(tyUint64, "c").
   245  		NewVar(tyFloat64, "d").
   246  		NewVar(tyString, "e").
   247  		Val(fmt.Ref("Println")).VarVal("a").MemberVal("String").Call(0).Call(1).EndStmt().
   248  		Val(fmt.Ref("Println")).VarVal("b").MemberVal("String").Call(0).Call(1).EndStmt().
   249  		Val(fmt.Ref("Println")).VarVal("c").MemberVal("String").Call(0).Call(1).EndStmt().
   250  		Val(fmt.Ref("Println")).VarVal("d").MemberVal("String").Call(0).Call(1).EndStmt().
   251  		Val(fmt.Ref("Println")).VarVal("e").MemberVal("ToUpper").Call(0).Call(1).EndStmt().
   252  		End()
   253  	domTest(t, pkg, `package main
   254  
   255  import (
   256  	"fmt"
   257  	"strconv"
   258  	"strings"
   259  )
   260  
   261  type MyInt int
   262  type MyInt64 int64
   263  type MyUint64 uint64
   264  type MyFloat64 float64
   265  type MyString string
   266  
   267  func main() {
   268  	var a MyInt
   269  	var b MyInt64
   270  	var c MyUint64
   271  	var d MyFloat64
   272  	var e MyString
   273  	fmt.Println(strconv.Itoa(int(a)))
   274  	fmt.Println(strconv.FormatInt(int64(b), 10))
   275  	fmt.Println(strconv.FormatUint(uint64(c), 10))
   276  	fmt.Println(strconv.FormatFloat(float64(d), 'g', -1, 64))
   277  	fmt.Println(strings.ToUpper(string(e)))
   278  }
   279  `)
   280  }
   281  
   282  func TestPrintlnPrintln(t *testing.T) {
   283  	pkg := newMainPackage()
   284  	fmt := pkg.Import("fmt")
   285  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   286  		Val(fmt.Ref("Println")).Val(fmt.Ref("Println")).Call(0).Call(1).EndStmt().
   287  		End()
   288  	domTest(t, pkg, `package main
   289  
   290  import "fmt"
   291  
   292  func main() {
   293  	fmt.Println(fmt.Println())
   294  }
   295  `)
   296  }
   297  
   298  func TestImportGopPkg(t *testing.T) {
   299  	pkg := newMainPackage()
   300  	foo := pkg.Import("github.com/goplus/gogen/internal/foo")
   301  	foo.EnsureImported()
   302  	nodeSet := foo.Ref("NodeSet")
   303  	if nodeSet == nil {
   304  		t.Fatal("TestImportGopPkg: NodeSet not found")
   305  	}
   306  	typ := nodeSet.(*types.TypeName).Type().(*types.Named)
   307  	for i, n := 0, typ.NumMethods(); i < n; i++ {
   308  		m := typ.Method(i)
   309  		if m.Name() == "Attr" {
   310  			funcs, ok := gogen.CheckOverloadMethod(m.Type().(*types.Signature))
   311  			if !ok || len(funcs) != 2 {
   312  				t.Fatal("CheckOverloadMethod failed:", funcs, ok)
   313  			}
   314  			return
   315  		}
   316  	}
   317  	t.Fatal("TestImportGopPkg: NodeSet.Attr not found")
   318  }
   319  
   320  func TestGoTypesPkg(t *testing.T) {
   321  	const src = `package foo
   322  
   323  type mytype = byte
   324  
   325  func bar(v mytype) rune {
   326  	return 0
   327  }
   328  `
   329  	fset := token.NewFileSet()
   330  	f, err := parser.ParseFile(fset, "foo.go", src, 0)
   331  	if err != nil {
   332  		t.Fatal("parser.ParseFile:", err)
   333  	}
   334  
   335  	packages := make(map[string]*types.Package)
   336  	imp := gcexportdata.NewImporter(fset, packages)
   337  	conf := types.Config{Importer: imp}
   338  	pkg, err := conf.Check("foo", fset, []*ast.File{f}, nil)
   339  	if err != nil {
   340  		t.Fatal("conf.Check:", err)
   341  	}
   342  	bar := pkg.Scope().Lookup("bar")
   343  	if bar.String() != "func foo.bar(v byte) rune" {
   344  		t.Fatal("bar.Type:", bar)
   345  	}
   346  }
   347  
   348  func TestMethods(t *testing.T) {
   349  	const src = `package foo
   350  
   351  type foo struct {}
   352  func (a foo) A() {}
   353  func (p *foo) Bar() {}
   354  `
   355  	fset := token.NewFileSet()
   356  	f, err := parser.ParseFile(fset, "foo.go", src, 0)
   357  	if err != nil {
   358  		t.Fatal("parser.ParseFile:", err)
   359  	}
   360  
   361  	packages := make(map[string]*types.Package)
   362  	imp := gcexportdata.NewImporter(fset, packages)
   363  	conf := types.Config{Importer: imp}
   364  	pkg, err := conf.Check("foo", fset, []*ast.File{f}, nil)
   365  	if err != nil {
   366  		t.Fatal("conf.Check:", err)
   367  	}
   368  	foo, ok := pkg.Scope().Lookup("foo").Type().(*types.Named)
   369  	if !ok {
   370  		t.Fatal("foo not found")
   371  	}
   372  	if foo.NumMethods() != 2 {
   373  		t.Fatal("foo.NumMethods:", foo.NumMethods())
   374  	}
   375  	if foo0 := foo.Method(0).String(); foo0 != "func (foo.foo).A()" {
   376  		t.Fatal("foo.0 =", foo0)
   377  	}
   378  	if foo1 := foo.Method(1).String(); foo1 != "func (*foo.foo).Bar()" {
   379  		t.Fatal("foo.1 =", foo1)
   380  	}
   381  }
   382  
   383  // ----------------------------------------------------------------------------
   384  
   385  func comment(txt string) *ast.CommentGroup {
   386  	return &ast.CommentGroup{List: []*ast.Comment{{Text: txt}}}
   387  }
   388  
   389  func TestBasic(t *testing.T) {
   390  	pkg := newMainPackage()
   391  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
   392  	if pkg.Ref("main") == nil {
   393  		t.Fatal("main not found")
   394  	}
   395  	domTest(t, pkg, `package main
   396  
   397  func main() {
   398  }
   399  `)
   400  }
   401  
   402  func TestTestingFile(t *testing.T) {
   403  	pkg := newMainPackage()
   404  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
   405  	_, err := pkg.SetCurFile("test", false)
   406  	if err != syscall.ENOENT {
   407  		t.Fatal("pkg.SetCurFile failed:", err)
   408  	}
   409  	old, err := pkg.SetCurFile("test", true)
   410  	if err != nil {
   411  		t.Fatal("pkg.SetCurFile failed:", err)
   412  	}
   413  	pkg.NewFunc(nil, "foo", nil, nil, false).BodyStart(pkg).End()
   414  	domTestEx(t, pkg, `package main
   415  
   416  func foo() {
   417  }
   418  `, "test")
   419  	if pkg.CurFile().Name() != "test" {
   420  		t.Fatal("TestTestingFile: curfile =", pkg.CurFile().Name())
   421  	}
   422  	err = gogen.WriteFile("_gop_autogen_test.go", pkg, "test")
   423  	pkg.RestoreCurFile(old)
   424  	if err != nil {
   425  		t.Fatal("gogen.WriteFile failed:", err)
   426  	}
   427  	os.Remove("_gop_autogen_test.go")
   428  	err = gogen.WriteTo(nil, pkg, "unknown")
   429  	if err != syscall.ENOENT {
   430  		t.Fatal("gogen.WriteTo failed:", err)
   431  	}
   432  	if gogen.ASTFile(pkg, "unknown") != nil {
   433  		t.Fatal("gogen.ASTFile: not nil")
   434  	}
   435  	if gogen.CommentedASTFile(pkg, "unknown") != nil {
   436  		t.Fatal("gogen.CommentedASTFile: not nil")
   437  	}
   438  	err = gogen.WriteFile("?.go", pkg, "unknown")
   439  	if err != syscall.ENOENT {
   440  		t.Fatal("gogen.WriteFile failed:", err)
   441  	}
   442  	pkg.ForEachFile(func(fname string, file *gogen.File) {
   443  		if fname != "" && fname != "test" {
   444  			t.Fatal("pkg.ForEachFile unexpected file:", fname)
   445  		}
   446  	})
   447  }
   448  
   449  func TestMake(t *testing.T) {
   450  	pkg := newMainPackage()
   451  	tySlice := types.NewSlice(types.Typ[types.Int])
   452  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   453  		NewVarStart(tySlice, "a").Val(pkg.Builtin().Ref("make")).
   454  		/**/ Typ(tySlice).Val(0).Val(2).Call(3).EndInit(1).
   455  		End()
   456  	domTest(t, pkg, `package main
   457  
   458  func main() {
   459  	var a []int = make([]int, 0, 2)
   460  }
   461  `)
   462  }
   463  
   464  func TestNew(t *testing.T) {
   465  	pkg := newMainPackage()
   466  	tyInt := types.Typ[types.Int]
   467  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   468  		NewVarStart(types.NewPointer(tyInt), "a").Val(pkg.Builtin().Ref("new")).
   469  		Val(ctxRef(pkg, "int")).Call(1).EndInit(1).
   470  		End()
   471  	domTest(t, pkg, `package main
   472  
   473  func main() {
   474  	var a *int = new(int)
   475  }
   476  `)
   477  }
   478  
   479  func TestTypeConv(t *testing.T) { // TypeCast
   480  	pkg := newMainPackage()
   481  	tyInt := types.Typ[types.Uint32]
   482  	tyPInt := types.NewPointer(tyInt)
   483  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   484  		NewVarStart(tyInt, "a").Typ(tyInt).Val(0).Call(1).EndInit(1).
   485  		NewVarStart(tyPInt, "b").Typ(tyPInt).Val(nil).Call(1).EndInit(1).
   486  		End()
   487  	domTest(t, pkg, `package main
   488  
   489  func main() {
   490  	var a uint32 = uint32(0)
   491  	var b *uint32 = (*uint32)(nil)
   492  }
   493  `)
   494  }
   495  
   496  func TestTypeConvBool(t *testing.T) { // TypeCast
   497  	pkg := newMainPackage()
   498  	tyBool := types.Typ[types.Bool]
   499  	tyInt := types.Typ[types.Uint32]
   500  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   501  		NewVarStart(tyBool, "a").Val(false).EndInit(1).
   502  		NewVarStart(tyInt, "b").Typ(tyInt).VarVal("a").Call(1).EndInit(1).
   503  		End()
   504  	domTest(t, pkg, `package main
   505  
   506  func main() {
   507  	var a bool = false
   508  	var b uint32 = func() uint32 {
   509  		if a {
   510  			return 1
   511  		} else {
   512  			return 0
   513  		}
   514  	}()
   515  }
   516  `)
   517  }
   518  
   519  func TestIncDec(t *testing.T) {
   520  	pkg := newMainPackage()
   521  	tyInt := types.Typ[types.Uint]
   522  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   523  		SetComments(comment("\n// new var a"), false).
   524  		NewVar(tyInt, "a").
   525  		SetComments(comment("\n// inc a"), true).
   526  		VarRef(ctxRef(pkg, "a")).IncDec(token.INC).EndStmt().
   527  		VarRef(ctxRef(pkg, "a")).IncDec(token.DEC).EndStmt().
   528  		End()
   529  	cb := pkg.CB()
   530  	if c, _ := cb.BackupComments(); c != nil || cb.Comments() != nil {
   531  		t.Fatal("comment is not nil")
   532  	}
   533  	domTest(t, pkg, `package main
   534  
   535  func main() {
   536  // new var a
   537  	var a uint
   538  // inc a
   539  	a++
   540  	a--
   541  }
   542  `)
   543  }
   544  
   545  func TestSend(t *testing.T) {
   546  	pkg := newMainPackage()
   547  	tyChan := types.NewChan(types.SendRecv, types.Typ[types.Uint])
   548  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   549  		NewVar(tyChan, "a").
   550  		VarVal("a").Val(1).Send().
   551  		End()
   552  	domTest(t, pkg, `package main
   553  
   554  func main() {
   555  	var a chan uint
   556  	a <- 1
   557  }
   558  `)
   559  }
   560  
   561  func TestRecv(t *testing.T) {
   562  	pkg := newMainPackage()
   563  	tyChan := types.NewChan(types.SendRecv, types.Typ[types.Uint])
   564  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   565  		NewVar(tyChan, "a").
   566  		NewVarStart(types.Typ[types.Uint], "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1).
   567  		DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true, nil).EndInit(1).
   568  		End()
   569  	domTest(t, pkg, `package main
   570  
   571  func main() {
   572  	var a chan uint
   573  	var b uint = <-a
   574  	c, ok := <-a
   575  }
   576  `)
   577  }
   578  
   579  func TestRecv2(t *testing.T) {
   580  	pkg := newMainPackage()
   581  	tyChan := types.NewChan(types.SendRecv, types.Typ[types.Uint])
   582  	typ := pkg.NewType("T").InitType(pkg, tyChan)
   583  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   584  		NewVar(typ, "a").
   585  		NewVarStart(types.Typ[types.Uint], "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1).
   586  		DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true).EndInit(1).
   587  		End()
   588  	domTest(t, pkg, `package main
   589  
   590  type T chan uint
   591  
   592  func main() {
   593  	var a T
   594  	var b uint = <-a
   595  	c, ok := <-a
   596  }
   597  `)
   598  }
   599  
   600  func TestRecv3(t *testing.T) {
   601  	pkg := newMainPackage()
   602  	tyUint := pkg.NewType("Uint").InitType(pkg, types.Typ[types.Uint])
   603  	tyChan := types.NewChan(types.SendRecv, tyUint)
   604  	typ := pkg.NewType("T").InitType(pkg, tyChan)
   605  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   606  		NewVar(typ, "a").
   607  		NewVarStart(tyUint, "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1).
   608  		DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true).EndInit(1).
   609  		End()
   610  	domTest(t, pkg, `package main
   611  
   612  type Uint uint
   613  type T chan Uint
   614  
   615  func main() {
   616  	var a T
   617  	var b Uint = <-a
   618  	c, ok := <-a
   619  }
   620  `)
   621  }
   622  
   623  func TestZeroLit(t *testing.T) {
   624  	pkg := newMainPackage()
   625  	tyMap := types.NewMap(types.Typ[types.String], types.Typ[types.Int])
   626  	ret := pkg.NewAutoParam("ret")
   627  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   628  		NewVarStart(tyMap, "a").
   629  		/**/ NewClosure(nil, gogen.NewTuple(ret), false).BodyStart(pkg).
   630  		/******/ VarRef(ctxRef(pkg, "ret")).ZeroLit(ret.Type()).Assign(1).
   631  		/******/ Val(ctxRef(pkg, "ret")).Val("Hi").IndexRef(1).Val(1).Assign(1).
   632  		/******/ Return(0).
   633  		/**/ End().Call(0).EndInit(1).
   634  		End()
   635  	domTest(t, pkg, `package main
   636  
   637  func main() {
   638  	var a map[string]int = func() (ret map[string]int) {
   639  		ret = map[string]int{}
   640  		ret["Hi"] = 1
   641  		return
   642  	}()
   643  }
   644  `)
   645  }
   646  
   647  func TestZeroLitAllTypes(t *testing.T) {
   648  	pkg := newMainPackage()
   649  	tyString := types.Typ[types.String]
   650  	tyBool := types.Typ[types.Bool]
   651  	tyUP := types.Typ[types.UnsafePointer]
   652  	tyMap := types.NewMap(tyString, types.Typ[types.Int])
   653  	tySlice := types.NewSlice(types.Typ[types.Int])
   654  	tyArray := gogen.NewArray(types.Typ[types.Int], 10)
   655  	tyPointer := gogen.NewPointer(types.Typ[types.Int])
   656  	tyChan := types.NewChan(types.SendRecv, types.Typ[types.Int])
   657  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   658  		NewVarStart(tyMap, "a").ZeroLit(tyMap).EndInit(1).
   659  		NewVarStart(tySlice, "b").ZeroLit(tySlice).EndInit(1).
   660  		NewVarStart(tyPointer, "c").ZeroLit(tyPointer).EndInit(1).
   661  		NewVarStart(tyChan, "d").ZeroLit(tyChan).EndInit(1).
   662  		NewVarStart(tyBool, "e").ZeroLit(tyBool).EndInit(1).
   663  		NewVarStart(tyString, "f").ZeroLit(tyString).EndInit(1).
   664  		NewVarStart(tyUP, "g").ZeroLit(tyUP).EndInit(1).
   665  		NewVarStart(gogen.TyEmptyInterface, "h").ZeroLit(gogen.TyEmptyInterface).EndInit(1).
   666  		NewVarStart(tyArray, "i").ZeroLit(tyArray).EndInit(1).
   667  		End()
   668  	domTest(t, pkg, `package main
   669  
   670  import "unsafe"
   671  
   672  func main() {
   673  	var a map[string]int = nil
   674  	var b []int = nil
   675  	var c *int = nil
   676  	var d chan int = nil
   677  	var e bool = false
   678  	var f string = ""
   679  	var g unsafe.Pointer = nil
   680  	var h interface{} = nil
   681  	var i [10]int = [10]int{}
   682  }
   683  `)
   684  }
   685  
   686  func TestTypeDeclInFunc(t *testing.T) {
   687  	pkg := newMainPackage()
   688  	fields := []*types.Var{
   689  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
   690  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
   691  	}
   692  	typ := types.NewStruct(fields, nil)
   693  	cb := pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
   694  	foo := cb.NewType("foo").InitType(pkg, typ)
   695  	cb.AliasType("bar", typ)
   696  	a := cb.AliasType("a", foo)
   697  	cb.AliasType("b", a)
   698  	cb.End()
   699  	domTest(t, pkg, `package main
   700  
   701  func main() {
   702  	type foo struct {
   703  		x int
   704  		y string
   705  	}
   706  	type bar = struct {
   707  		x int
   708  		y string
   709  	}
   710  	type a = foo
   711  	type b = a
   712  }
   713  `)
   714  }
   715  
   716  func TestTypeDoc(t *testing.T) {
   717  	pkg := newMainPackage()
   718  	typ := types.NewStruct(nil, nil)
   719  	def := pkg.NewTypeDefs().SetComments(nil)
   720  	def.NewType("foo").SetComments(pkg, comment("\n//go:notinheap")).InitType(pkg, typ)
   721  	def.Complete()
   722  	domTest(t, pkg, `package main
   723  
   724  //go:notinheap
   725  type foo struct {
   726  }
   727  `)
   728  }
   729  
   730  func TestDeleteType(t *testing.T) {
   731  	pkg := newMainPackage()
   732  	typ := types.NewStruct(nil, nil)
   733  	def := pkg.NewTypeDefs()
   734  	decl := def.NewType("foo")
   735  	if decl.State() != gogen.TyStateUninited {
   736  		t.Fatal("TypeDecl.State failed")
   737  	}
   738  	decl.InitType(pkg, typ)
   739  	if decl.State() != gogen.TyStateInited {
   740  		t.Fatal("TypeDecl.State failed")
   741  	}
   742  	decl.Delete()
   743  	if decl.State() != gogen.TyStateDeleted {
   744  		t.Fatal("TypeDecl.State failed")
   745  	}
   746  	def.NewType("t").InitType(def.Pkg(), gogen.TyByte)
   747  	def.NewType("bar").Delete()
   748  	def.Complete()
   749  	domTest(t, pkg, `package main
   750  
   751  type t byte
   752  `)
   753  }
   754  
   755  func TestTypeDecl(t *testing.T) {
   756  	pkg := newMainPackage()
   757  	fields := []*types.Var{
   758  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
   759  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
   760  	}
   761  	typ := types.NewStruct(fields, nil)
   762  	foo := pkg.NewType("foo").InitType(pkg, typ)
   763  	pkg.AliasType("bar", typ)
   764  	a := pkg.AliasType("a", foo)
   765  	pkg.AliasType("b", a)
   766  	domTest(t, pkg, `package main
   767  
   768  type foo struct {
   769  	x int
   770  	y string
   771  }
   772  type bar = struct {
   773  	x int
   774  	y string
   775  }
   776  type a = foo
   777  type b = a
   778  `)
   779  }
   780  
   781  func TestTypeCycleDef(t *testing.T) {
   782  	pkg := newMainPackage()
   783  	foo := pkg.NewType("foo")
   784  	a := pkg.AliasType("a", foo.Type())
   785  	b := pkg.AliasType("b", a)
   786  	fields := []*types.Var{
   787  		types.NewField(token.NoPos, pkg.Types, "p", types.NewPointer(b), false),
   788  	}
   789  	foo.InitType(pkg, types.NewStruct(fields, nil))
   790  	domTest(t, pkg, `package main
   791  
   792  type foo struct {
   793  	p *b
   794  }
   795  type a = foo
   796  type b = a
   797  `)
   798  }
   799  
   800  func TestTypeMethods(t *testing.T) {
   801  	pkg := newMainPackage()
   802  	fields := []*types.Var{
   803  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
   804  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
   805  	}
   806  	typ := types.NewStruct(fields, nil)
   807  	foo := pkg.NewType("foo").InitType(pkg, typ)
   808  	recv := pkg.NewParam(token.NoPos, "a", foo)
   809  	precv := pkg.NewParam(token.NoPos, "p", types.NewPointer(foo))
   810  	pkg.NewFunc(recv, "Bar", nil, nil, false).SetComments(pkg, comment("\n// abc")).BodyStart(pkg).End()
   811  	pkg.NewFunc(precv, "Print", nil, nil, false).BodyStart(pkg).End()
   812  	if foo.NumMethods() != 2 {
   813  		t.Fatal("foo.NumMethods != 2")
   814  	}
   815  	domTest(t, pkg, `package main
   816  
   817  type foo struct {
   818  	x int
   819  	y string
   820  }
   821  
   822  // abc
   823  func (a foo) Bar() {
   824  }
   825  func (p *foo) Print() {
   826  }
   827  `)
   828  }
   829  
   830  func TestAssignInterface(t *testing.T) {
   831  	pkg := newMainPackage()
   832  	foo := pkg.NewType("foo").InitType(pkg, types.Typ[types.Int])
   833  	recv := pkg.NewParam(token.NoPos, "a", foo)
   834  	ret := pkg.NewParam(token.NoPos, "ret", types.Typ[types.String])
   835  	pkg.NewFunc(recv, "Error", nil, types.NewTuple(ret), false).BodyStart(pkg).
   836  		Return(0).
   837  		End()
   838  	pkg.CB().NewVarStart(gogen.TyError, "err").
   839  		Typ(foo).ZeroLit(foo).Call(1).
   840  		EndInit(1)
   841  	domTest(t, pkg, `package main
   842  
   843  type foo int
   844  
   845  func (a foo) Error() (ret string) {
   846  	return
   847  }
   848  
   849  var err error = foo(0)
   850  `)
   851  }
   852  
   853  func TestAssignUserInterface(t *testing.T) {
   854  	pkg := newMainPackage()
   855  	methods := []*types.Func{
   856  		types.NewFunc(token.NoPos, pkg.Types, "Bar", types.NewSignatureType(nil, nil, nil, nil, nil, false)),
   857  	}
   858  	tyInterf := types.NewInterfaceType(methods, nil).Complete()
   859  	typStruc := types.NewStruct(nil, nil)
   860  	foo := pkg.NewType("foo").InitType(pkg, tyInterf)
   861  	bar := pkg.NewType("bar").InitType(pkg, typStruc)
   862  	pbar := types.NewPointer(bar)
   863  	recv := pkg.NewParam(token.NoPos, "p", pbar)
   864  	vfoo := types.NewTuple(pkg.NewParam(token.NoPos, "v", types.NewSlice(foo)))
   865  	pkg.NewFunc(recv, "Bar", nil, nil, false).BodyStart(pkg).End()
   866  	pkg.NewFunc(nil, "f", vfoo, nil, true).BodyStart(pkg).End()
   867  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   868  		NewVar(pbar, "v").
   869  		VarVal("f").
   870  		VarVal("v").VarVal("v").Call(2).EndStmt().
   871  		End()
   872  	domTest(t, pkg, `package main
   873  
   874  type foo interface {
   875  	Bar()
   876  }
   877  type bar struct {
   878  }
   879  
   880  func (p *bar) Bar() {
   881  }
   882  func f(v ...foo) {
   883  }
   884  func main() {
   885  	var v *bar
   886  	f(v, v)
   887  }
   888  `)
   889  }
   890  
   891  func TestTypeAssert(t *testing.T) {
   892  	pkg := newMainPackage()
   893  	params := types.NewTuple(pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface))
   894  	pkg.NewFunc(nil, "foo", params, nil, false).BodyStart(pkg, source("{}", 1, 5)).
   895  		DefineVarStart(0, "x").VarVal("v").TypeAssert(types.Typ[types.Int], false).EndInit(1).
   896  		DefineVarStart(0, "y", "ok").VarVal("v").TypeAssert(types.Typ[types.String], true).EndInit(1).
   897  		End()
   898  	domTest(t, pkg, `package main
   899  
   900  func foo(v interface{}) {
   901  	x := v.(int)
   902  	y, ok := v.(string)
   903  }
   904  `)
   905  }
   906  
   907  func newFuncDecl(pkg *gogen.Package, name string, params, results *types.Tuple) *gogen.Func {
   908  	sig := types.NewSignatureType(nil, nil, nil, params, results, false)
   909  	return pkg.NewFuncDecl(token.NoPos, name, sig)
   910  }
   911  
   912  func TestTypeSwitch(t *testing.T) {
   913  	pkg := newMainPackage()
   914  	p := pkg.NewParam(token.NoPos, "p", types.NewPointer(gogen.TyEmptyInterface))
   915  	v := pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface)
   916  	newFuncDecl(pkg, "bar", types.NewTuple(p), nil)
   917  	newFuncDecl(pkg, "foo", types.NewTuple(v), nil).BodyStart(pkg).
   918  		/**/ TypeSwitch("t").Val(v).TypeAssertThen().
   919  		/****/ TypeCase().Typ(types.Typ[types.Int]).Typ(types.Typ[types.String]).Then().
   920  		/******/ Val(ctxRef(pkg, "bar")).VarRef(ctxRef(pkg, "t")).UnaryOp(token.AND).Call(1).EndStmt().
   921  		/****/ End().
   922  		/**/ TypeCase().Typ(types.Typ[types.Bool]).Then().
   923  		/******/ NewVarStart(types.Typ[types.Bool], "x").Val(ctxRef(pkg, "t")).EndInit(1).
   924  		/****/ End().
   925  		/****/ TypeDefaultThen().
   926  		/******/ Val(ctxRef(pkg, "bar")).VarRef(ctxRef(pkg, "t")).UnaryOp(token.AND).Call(1).EndStmt().
   927  		/****/ End().
   928  		/**/ End().
   929  		End()
   930  	domTest(t, pkg, `package main
   931  
   932  func bar(p *interface{})
   933  func foo(v interface{}) {
   934  	switch t := v.(type) {
   935  	case int, string:
   936  		bar(&t)
   937  	case bool:
   938  		var x bool = t
   939  	default:
   940  		bar(&t)
   941  	}
   942  }
   943  `)
   944  }
   945  
   946  func TestTypeSwitch2(t *testing.T) {
   947  	pkg := newMainPackage()
   948  	p := pkg.NewParam(token.NoPos, "p", types.NewPointer(gogen.TyEmptyInterface))
   949  	v := pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface)
   950  	pkg.NewFunc(nil, "bar", types.NewTuple(p), nil, false).BodyStart(pkg).End()
   951  	pkg.NewFunc(nil, "foo", types.NewTuple(v), nil, false).BodyStart(pkg).
   952  		/**/ TypeSwitch("").Val(ctxRef(pkg, "bar")).Val(nil).Call(1).EndStmt().Val(v).TypeAssertThen().
   953  		/****/ TypeCase().Typ(types.Typ[types.Int]).Then().
   954  		/******/ Val(ctxRef(pkg, "bar")).VarRef(ctxRef(pkg, "v")).UnaryOp(token.AND).Call(1).EndStmt().
   955  		/****/ End().
   956  		/**/ End().
   957  		End()
   958  	domTest(t, pkg, `package main
   959  
   960  func bar(p *interface{}) {
   961  }
   962  func foo(v interface{}) {
   963  	switch bar(nil); v.(type) {
   964  	case int:
   965  		bar(&v)
   966  	}
   967  }
   968  `)
   969  }
   970  
   971  func TestSelect(t *testing.T) {
   972  	pkg := newMainPackage()
   973  	tyXchg := types.NewChan(types.SendRecv, types.Typ[types.Int])
   974  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
   975  		NewVar(tyXchg, "xchg").
   976  		/**/ Select().
   977  		/****/ CommCase().DefineVarStart(0, "x").Val(ctxRef(pkg, "xchg")).UnaryOp(token.ARROW).EndInit(1).Then().
   978  		/******/ NewVarStart(types.Typ[types.Int], "t").Val(ctxRef(pkg, "x")).EndInit(1).
   979  		/****/ End().
   980  		/****/ CommCase().Val(ctxRef(pkg, "xchg")).Val(1).Send().Then().
   981  		/******/ DefineVarStart(0, "x").Val(1).EndInit(1).
   982  		/****/ End().
   983  		/****/ CommDefaultThen().
   984  		/******/ DefineVarStart(0, "x").Val("Hi").EndInit(1).
   985  		/****/ End().
   986  		/**/ End().
   987  		End()
   988  	domTest(t, pkg, `package main
   989  
   990  func main() {
   991  	var xchg chan int
   992  	select {
   993  	case x := <-xchg:
   994  		var t int = x
   995  	case xchg <- 1:
   996  		x := 1
   997  	default:
   998  		x := "Hi"
   999  	}
  1000  }
  1001  `)
  1002  }
  1003  
  1004  func TestStructLit(t *testing.T) {
  1005  	pkg := newMainPackage()
  1006  	fields := []*types.Var{
  1007  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  1008  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  1009  	}
  1010  	typ := types.NewStruct(fields, nil)
  1011  	pkg.CB().NewVarStart(nil, "a").
  1012  		StructLit(typ, 0, false).EndInit(1)
  1013  	pkg.CB().NewVarStart(nil, "b").
  1014  		Val(123).Val("Hi").
  1015  		StructLit(typ, 2, false).EndInit(1)
  1016  	pkg.CB().NewVarStart(nil, "c").
  1017  		Val(1).Val("abc").
  1018  		StructLit(typ, 2, true).EndInit(1)
  1019  	domTest(t, pkg, `package main
  1020  
  1021  var a = struct {
  1022  	x int
  1023  	y string
  1024  }{}
  1025  var b = struct {
  1026  	x int
  1027  	y string
  1028  }{123, "Hi"}
  1029  var c = struct {
  1030  	x int
  1031  	y string
  1032  }{y: "abc"}
  1033  `)
  1034  }
  1035  
  1036  func TestNamedStructLit(t *testing.T) {
  1037  	pkg := newMainPackage()
  1038  	fields := []*types.Var{
  1039  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  1040  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  1041  	}
  1042  	typU := types.NewStruct(fields, nil)
  1043  	typ := pkg.NewType("foo").InitType(pkg, typU)
  1044  	bar := pkg.AliasType("bar", typ)
  1045  	pkg.CB().NewVarStart(typ, "a").
  1046  		StructLit(typ, 0, false).EndInit(1)
  1047  	pkg.CB().NewVarStart(types.NewPointer(bar), "b").
  1048  		Val(123).Val("Hi").
  1049  		StructLit(bar, 2, false).
  1050  		UnaryOp(token.AND).
  1051  		EndInit(1)
  1052  	pkg.CB().NewVarStart(bar, "c").
  1053  		Val(1).Val("abc").
  1054  		StructLit(typ, 2, true).EndInit(1)
  1055  	domTest(t, pkg, `package main
  1056  
  1057  type foo struct {
  1058  	x int
  1059  	y string
  1060  }
  1061  type bar = foo
  1062  
  1063  var a foo = foo{}
  1064  var b *bar = &bar{123, "Hi"}
  1065  var c bar = foo{y: "abc"}
  1066  `)
  1067  }
  1068  
  1069  func TestMapLit(t *testing.T) {
  1070  	pkg := newMainPackage()
  1071  	pkg.CB().NewVarStart(nil, "a").
  1072  		Val("a").Val(1).Val("b").Val(2).MapLit(nil, 4).EndInit(1)
  1073  	pkg.CB().NewVarStart(nil, "b").
  1074  		Val("a").Val(1).Val("b").Val(1.2).MapLit(nil, 4).EndInit(1)
  1075  	pkg.CB().NewVarStart(nil, "c").
  1076  		MapLit(nil, 0).EndInit(1)
  1077  	pkg.CB().NewVarStart(nil, "d").
  1078  		Val(1).Val(true).
  1079  		MapLit(types.NewMap(types.Typ[types.Int], types.Typ[types.Bool]), 2).EndInit(1)
  1080  	domTest(t, pkg, `package main
  1081  
  1082  var a = map[string]int{"a": 1, "b": 2}
  1083  var b = map[string]float64{"a": 1, "b": 1.2}
  1084  var c = map[string]interface{}{}
  1085  var d = map[int]bool{1: true}
  1086  `)
  1087  }
  1088  
  1089  func TestNamedMapLit(t *testing.T) {
  1090  	pkg := newMainPackage()
  1091  	foo := pkg.NewType("foo").InitType(pkg, types.NewMap(types.Typ[types.Int], types.Typ[types.Bool]))
  1092  	bar := pkg.AliasType("bar", foo)
  1093  	pkg.CB().NewVarStart(foo, "a").
  1094  		Val(1).Val(true).
  1095  		MapLit(foo, 2).EndInit(1)
  1096  	pkg.CB().NewVarStart(bar, "b").
  1097  		Val(1).Val(true).
  1098  		MapLit(bar, 2).EndInit(1)
  1099  	domTest(t, pkg, `package main
  1100  
  1101  type foo map[int]bool
  1102  type bar = foo
  1103  
  1104  var a foo = foo{1: true}
  1105  var b bar = bar{1: true}
  1106  `)
  1107  }
  1108  
  1109  func TestSliceLit(t *testing.T) {
  1110  	pkg := newMainPackage()
  1111  	pkg.CB().NewVarStart(nil, "a").
  1112  		Val("a").Val("b").SliceLit(nil, 2).EndInit(1)
  1113  	pkg.CB().NewVarStart(nil, "b").
  1114  		Val(1).Val(1.2).Val(3).SliceLit(nil, 3).EndInit(1)
  1115  	pkg.CB().NewVarStart(nil, "c").
  1116  		SliceLit(nil, 0).EndInit(1)
  1117  	pkg.CB().NewVarStart(nil, "d").
  1118  		Val(1).
  1119  		SliceLit(types.NewSlice(types.Typ[types.Int]), 1).EndInit(1)
  1120  	domTest(t, pkg, `package main
  1121  
  1122  var a = []string{"a", "b"}
  1123  var b = []float64{1, 1.2, 3}
  1124  var c = []interface{}{}
  1125  var d = []int{1}
  1126  `)
  1127  }
  1128  
  1129  func TestNamedSliceLit(t *testing.T) {
  1130  	pkg := newMainPackage()
  1131  	foo := pkg.NewType("foo").InitType(pkg, types.NewSlice(types.Typ[types.Int]))
  1132  	bar := pkg.AliasType("bar", foo)
  1133  	pkg.CB().NewVarStart(foo, "a").
  1134  		Val(1).
  1135  		SliceLit(foo, 1).EndInit(1)
  1136  	pkg.CB().NewVarStart(bar, "b").
  1137  		Val(1).
  1138  		SliceLit(bar, 1).EndInit(1)
  1139  	domTest(t, pkg, `package main
  1140  
  1141  type foo []int
  1142  type bar = foo
  1143  
  1144  var a foo = foo{1}
  1145  var b bar = bar{1}
  1146  `)
  1147  }
  1148  
  1149  func TestKeyValModeLit(t *testing.T) {
  1150  	pkg := newMainPackage()
  1151  	pkg.CB().NewVarStart(nil, "a").
  1152  		None().Val(1).Val(3).Val(3.4).None().Val(5).
  1153  		ArrayLit(types.NewArray(types.Typ[types.Float64], -1), 6, true).EndInit(1)
  1154  	pkg.CB().NewVarStart(nil, "b").
  1155  		Val(2).Val(1.2).None().Val(3).Val(6).Val(4.5).
  1156  		SliceLit(types.NewSlice(types.Typ[types.Float64]), 6, true).EndInit(1)
  1157  	domTest(t, pkg, `package main
  1158  
  1159  var a = [...]float64{1, 3: 3.4, 5}
  1160  var b = []float64{2: 1.2, 3, 6: 4.5}
  1161  `)
  1162  }
  1163  
  1164  func TestNamedArrayLit(t *testing.T) {
  1165  	pkg := newMainPackage()
  1166  	foo := pkg.NewType("foo").InitType(pkg, types.NewArray(types.Typ[types.String], 2))
  1167  	bar := pkg.AliasType("bar", foo)
  1168  	pkg.CB().NewVarStart(foo, "a").
  1169  		Val("a").Val("b").ArrayLit(foo, 2).EndInit(1)
  1170  	pkg.CB().NewVarStart(bar, "b").
  1171  		Val("a").Val("b").ArrayLit(bar, 2).EndInit(1)
  1172  	domTest(t, pkg, `package main
  1173  
  1174  type foo [2]string
  1175  type bar = foo
  1176  
  1177  var a foo = foo{"a", "b"}
  1178  var b bar = bar{"a", "b"}
  1179  `)
  1180  }
  1181  
  1182  func TestArrayLit(t *testing.T) {
  1183  	pkg := newMainPackage()
  1184  	pkg.CB().NewVarStart(nil, "a").
  1185  		Val("a").Val("b").ArrayLit(types.NewArray(types.Typ[types.String], 2), 2).EndInit(1)
  1186  	pkg.CB().NewVarStart(nil, "b").
  1187  		Val(1).Val(1.2).Val(3).ArrayLit(types.NewArray(types.Typ[types.Float64], -1), 3).EndInit(1)
  1188  	pkg.CB().NewVarStart(nil, "c").
  1189  		ArrayLit(types.NewArray(gogen.TyEmptyInterface, 10), 0).EndInit(1)
  1190  	domTest(t, pkg, `package main
  1191  
  1192  var a = [2]string{"a", "b"}
  1193  var b = [...]float64{1, 1.2, 3}
  1194  var c = [10]interface{}{}
  1195  `)
  1196  }
  1197  
  1198  func TestBlockStmt(t *testing.T) {
  1199  	pkg := newMainPackage()
  1200  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1201  		Block().
  1202  		/**/ NewVar(types.Typ[types.String], "x", "y").
  1203  		End().
  1204  		Block().
  1205  		/**/ DefineVarStart(token.NoPos, "x", "y").Val(1).Val(4.0).EndInit(2).
  1206  		End().
  1207  		VBlock().
  1208  		/**/ DefineVarStart(token.NoPos, "x", "y").Val(10).Val(100).EndInit(2).
  1209  		/**/ Debug(func(cb *gogen.CodeBuilder) {
  1210  			if !cb.InVBlock() {
  1211  				t.Fatal("InVBlock: false?")
  1212  			}
  1213  		}).
  1214  		End().
  1215  		Debug(func(cb *gogen.CodeBuilder) {
  1216  			if cb.InVBlock() {
  1217  				t.Fatal("InVBlock: true?")
  1218  			}
  1219  		}).
  1220  		End()
  1221  	domTest(t, pkg, `package main
  1222  
  1223  func main() {
  1224  	{
  1225  		var x, y string
  1226  	}
  1227  	{
  1228  		x, y := 1, 4.0
  1229  	}
  1230  	x, y := 10, 100
  1231  }
  1232  `)
  1233  	safeRun(t, func() {
  1234  		pkg.CB().Then()
  1235  	})
  1236  	safeRun(t, func() {
  1237  		pkg.CB().Val(1).Then()
  1238  	})
  1239  	safeRun(t, func() {
  1240  		pkg.CB().Else()
  1241  	})
  1242  	safeRun(t, func() {
  1243  		pkg.CB().TypeAssertThen()
  1244  	})
  1245  	safeRun(t, func() {
  1246  		pkg.CB().Case()
  1247  	})
  1248  	safeRun(t, func() {
  1249  		pkg.CB().Fallthrough()
  1250  	})
  1251  	safeRun(t, func() {
  1252  		pkg.CB().Post()
  1253  	})
  1254  	safeRun(t, func() {
  1255  		pkg.CB().RangeAssignThen(0)
  1256  	})
  1257  	safeRun(t, func() {
  1258  		pkg.CB().TypeCase()
  1259  	})
  1260  	safeRun(t, func() {
  1261  		pkg.CB().CommCase()
  1262  	})
  1263  	safeRun(t, func() {
  1264  		pkg.CB().Val(2).Val(3).EndStmt()
  1265  	})
  1266  }
  1267  
  1268  func safeRun(t *testing.T, doSth func()) {
  1269  	defer func() {
  1270  		if e := recover(); e == nil {
  1271  			t.Fatal("no error?")
  1272  		}
  1273  	}()
  1274  	doSth()
  1275  }
  1276  
  1277  func TestConst(t *testing.T) {
  1278  	pkg := newMainPackage()
  1279  	tv := pkg.ConstStart().Val(1).Val(2).BinaryOp(token.ADD).EndConst()
  1280  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(3)) {
  1281  		t.Fatal("TestConst: != 3, it is", tv.CVal)
  1282  	}
  1283  	tv = pkg.ConstStart().Val("1").Val("2").BinaryOp(token.ADD).EndConst()
  1284  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeString("12")) {
  1285  		t.Fatal("TestConst: != 12, it is", tv.CVal)
  1286  	}
  1287  }
  1288  
  1289  func TestConstLenCap(t *testing.T) {
  1290  	pkg := newMainPackage()
  1291  	typ := types.NewArray(types.Typ[types.Int], 10)
  1292  	typAP := types.NewPointer(typ)
  1293  	pkg.Types.Scope().Insert(types.NewVar(token.NoPos, pkg.Types, "array", typ))
  1294  	pkg.Types.Scope().Insert(types.NewVar(token.NoPos, pkg.Types, "parray", typAP))
  1295  	tv := pkg.ConstStart().Val(pkg.Builtin().Ref("len")).Val(pkg.Ref("array")).Call(1).EndConst()
  1296  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(10)) {
  1297  		t.Fatal("TestConst: != 10, it is", tv.CVal)
  1298  	}
  1299  	tv = pkg.ConstStart().Val(pkg.Builtin().Ref("len")).Val(pkg.Ref("parray")).Call(1).EndConst()
  1300  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(10)) {
  1301  		t.Fatal("TestConst: != 10, it is", tv.CVal)
  1302  	}
  1303  	tv = pkg.ConstStart().Val(pkg.Builtin().Ref("len")).Val("Hi").Call(1).EndConst()
  1304  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(2)) {
  1305  		t.Fatal("TestConst: != 2, it is", tv.CVal)
  1306  	}
  1307  	tv = pkg.ConstStart().Val(pkg.Builtin().Ref("cap")).Val(pkg.Ref("array")).Call(1).EndConst()
  1308  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(10)) {
  1309  		t.Fatal("TestConst: != 10, it is", tv.CVal)
  1310  	}
  1311  	tv = pkg.ConstStart().Val(pkg.Builtin().Ref("cap")).Val(pkg.Ref("parray")).Call(1).EndConst()
  1312  	if constant.Compare(tv.CVal, token.NEQ, constant.MakeInt64(10)) {
  1313  		t.Fatal("TestConst: != 10, it is", tv.CVal)
  1314  	}
  1315  }
  1316  
  1317  func TestConstDecl(t *testing.T) {
  1318  	pkg := newMainPackage()
  1319  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
  1320  	pkg.NewConstDefs(pkg.CB().Scope()).SetComments(nil).New(func(cb *gogen.CodeBuilder) int {
  1321  		cb.Val(1).Val(2).BinaryOp(token.ADD)
  1322  		return 1
  1323  	}, 0, token.NoPos, nil, "n")
  1324  	pkg.CB().NewConstStart(types.Typ[types.String], "x").
  1325  		Val("1").Val("2").BinaryOp(token.ADD).EndInit(1)
  1326  	pkg.CB().NewConstStart(types.Typ[types.String], "y").
  1327  		Val("Hello").EndInit(1).
  1328  		End()
  1329  	domTest(t, pkg, `package main
  1330  
  1331  func main() {
  1332  	const n = 1 + 2
  1333  	const x string = "1" + "2"
  1334  	const y string = "Hello"
  1335  }
  1336  `)
  1337  }
  1338  
  1339  func TestConstDecl2(t *testing.T) {
  1340  	pkg := newMainPackage()
  1341  	pkg.NewConstDefs(pkg.Types.Scope()).
  1342  		New(func(cb *gogen.CodeBuilder) int {
  1343  			cb.Val(ctxRef(pkg, "iota"))
  1344  			return 1
  1345  		}, 0, token.NoPos, nil, "a").
  1346  		Next(1, token.NoPos, "_").
  1347  		Next(2, token.NoPos, "_").
  1348  		Next(3, token.NoPos, "b").
  1349  		New(func(cb *gogen.CodeBuilder) int {
  1350  			cb.Val(ctxRef(pkg, "iota"))
  1351  			return 1
  1352  		}, 4, token.NoPos, nil, "c")
  1353  	o := pkg.Types.Scope().Lookup("b")
  1354  	if v, ok := constant.Int64Val(o.(*types.Const).Val()); !ok || v != 3 {
  1355  		t.Fatal("TestConstDecl2 failed: b =", v)
  1356  	}
  1357  	o2 := pkg.Types.Scope().Lookup("c")
  1358  	if v, ok := constant.Int64Val(o2.(*types.Const).Val()); !ok || v != 4 {
  1359  		t.Fatal("TestConstDecl2 failed: c =", v)
  1360  	}
  1361  	domTest(t, pkg, `package main
  1362  
  1363  const (
  1364  	a = iota
  1365  	_
  1366  	_
  1367  	b
  1368  	c = iota
  1369  )
  1370  `)
  1371  }
  1372  
  1373  func TestConstDecl3(t *testing.T) {
  1374  	pkg := newMainPackage()
  1375  	pkg.NewConstDefs(pkg.Types.Scope()).
  1376  		New(func(cb *gogen.CodeBuilder) int {
  1377  			cb.Val(1).Val(ctxRef(pkg, "iota")).BinaryOp(token.SHL)
  1378  			return 1
  1379  		}, 0, token.NoPos, types.Typ[types.Uint16], "a").
  1380  		Next(1, token.NoPos, "_").
  1381  		Next(2, token.NoPos, "_").
  1382  		Next(3, token.NoPos, "b")
  1383  	o := pkg.Types.Scope().Lookup("b")
  1384  	if v, ok := constant.Int64Val(o.(*types.Const).Val()); !ok || v != 8 {
  1385  		t.Fatal("TestConstDecl3 failed:", v)
  1386  	}
  1387  	domTest(t, pkg, `package main
  1388  
  1389  const (
  1390  	a uint16 = 1 << iota
  1391  	_
  1392  	_
  1393  	b
  1394  )
  1395  `)
  1396  }
  1397  
  1398  func TestDeleteVarDecl(t *testing.T) {
  1399  	pkg := newMainPackage()
  1400  	pkg.SetRedeclarable(true)
  1401  	scope := pkg.CB().Scope()
  1402  	defs := pkg.NewVarDefs(scope).SetComments(nil)
  1403  	decl := defs.New(token.NoPos, types.Typ[types.Int], "a", "b")
  1404  	defs.New(token.NoPos, types.Typ[types.String], "c")
  1405  	defs.New(token.NoPos, types.Typ[types.String], "s")
  1406  	if decl.Inited() {
  1407  		t.Fatal("TestDeleteVarDecl: inited?")
  1408  	}
  1409  	defs.Delete("b")
  1410  	defs.Delete("c")
  1411  	defs.NewAndInit(func(cb *gogen.CodeBuilder) int {
  1412  		cb.Val(10)
  1413  		return 1
  1414  	}, token.NoPos, types.Typ[types.Int], "b")
  1415  	if err := defs.Delete("b"); err != syscall.EACCES {
  1416  		t.Fatal("defs.Delete b failed:", err)
  1417  	}
  1418  	if err := defs.Delete("unknown"); err != syscall.ENOENT {
  1419  		t.Fatal("defs.Delete unknown failed:", err)
  1420  	}
  1421  	domTest(t, pkg, `package main
  1422  
  1423  var (
  1424  	a int
  1425  	s string
  1426  	b int = 10
  1427  )
  1428  `)
  1429  }
  1430  
  1431  func TestVarDecl(t *testing.T) {
  1432  	pkg := newMainPackage()
  1433  	scope := pkg.CB().Scope()
  1434  	decl := pkg.NewVarDefs(scope).NewAndInit(func(cb *gogen.CodeBuilder) int {
  1435  		cb.Val(1).Val(2).BinaryOp(token.ADD).
  1436  			Val("1").Val("2").BinaryOp(token.ADD)
  1437  		return 2
  1438  	}, token.NoPos, nil, "n", "s")
  1439  	pkg.CB().NewVarStart(types.Typ[types.String], "x").
  1440  		Val("Hello, ").Val("Go+").BinaryOp(token.ADD).
  1441  		EndInit(1)
  1442  	if decl.New(token.NoPos, types.Typ[types.String], "y").Ref("y") == nil {
  1443  		t.Fatal("TestVarDecl failed: var y not found")
  1444  	}
  1445  	pkg.NewVarDefs(scope) // no variables, ignore
  1446  	domTest(t, pkg, `package main
  1447  
  1448  var (
  1449  	n, s = 1 + 2, "1" + "2"
  1450  	y    string
  1451  )
  1452  var x string = "Hello, " + "Go+"
  1453  `)
  1454  }
  1455  
  1456  func TestVarDeclNoBody(t *testing.T) {
  1457  	pkg := newMainPackage()
  1458  	pkg.NewVarEx(pkg.Types.Scope(), token.NoPos, types.Typ[types.String], "x")
  1459  	domTest(t, pkg, `package main
  1460  
  1461  var x string
  1462  `)
  1463  }
  1464  
  1465  func TestVarDeclInFunc(t *testing.T) {
  1466  	pkg := newMainPackage()
  1467  	fmt := pkg.Import("fmt")
  1468  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1469  		NewVar(types.Typ[types.String], "x", "y").
  1470  		NewVarStart(nil, "a", "_").Val(1).Val(2).BinaryOp(token.ADD).Val("Hi").EndInit(2).
  1471  		NewVarStart(nil, "n", "_").Val(fmt.Ref("Println")).Val(2).Call(1).EndInit(1).
  1472  		End()
  1473  	domTest(t, pkg, `package main
  1474  
  1475  import "fmt"
  1476  
  1477  func main() {
  1478  	var x, y string
  1479  	var a, _ = 1 + 2, "Hi"
  1480  	var n, _ = fmt.Println(2)
  1481  }
  1482  `)
  1483  }
  1484  
  1485  func TestDefineVar(t *testing.T) {
  1486  	pkg := newMainPackage()
  1487  	fmt := pkg.Import("fmt")
  1488  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1489  		NewVar(types.Typ[types.Int], "n").
  1490  		DefineVarStart(0, "n", "err").Val(fmt.Ref("Println")).Val(2).Call(1).EndInit(1).
  1491  		End()
  1492  	domTest(t, pkg, `package main
  1493  
  1494  import "fmt"
  1495  
  1496  func main() {
  1497  	var n int
  1498  	n, err := fmt.Println(2)
  1499  }
  1500  `)
  1501  }
  1502  
  1503  func TestFuncDoc(t *testing.T) {
  1504  	pkg := newMainPackage()
  1505  	fn := pkg.NewFunc(nil, "main", nil, nil, false).SetComments(pkg, comment("\n//go:noinline"))
  1506  	fn.BodyStart(pkg).End()
  1507  	if fn.Comments() == nil {
  1508  		t.Fatal("TestFuncDoc failed: no doc?")
  1509  	}
  1510  	domTest(t, pkg, `package main
  1511  
  1512  //go:noinline
  1513  func main() {
  1514  }
  1515  `)
  1516  }
  1517  
  1518  func TestFuncDoc2(t *testing.T) {
  1519  	pkg := newMainPackage()
  1520  	fn := pkg.NewFunc(nil, "main", nil, nil, false).SetComments(pkg, comment("\n/*\n doc\n*/"))
  1521  	fn.BodyStart(pkg).End()
  1522  	if fn.Comments() == nil {
  1523  		t.Fatal("TestFuncDoc2 failed: no doc?")
  1524  	}
  1525  	domTest(t, pkg, `package main
  1526  
  1527  /*
  1528   doc
  1529  */
  1530  func main() {
  1531  }
  1532  `)
  1533  }
  1534  
  1535  func TestFuncBasic(t *testing.T) {
  1536  	pkg := newMainPackage()
  1537  	v := pkg.NewParam(token.NoPos, "v", gogen.TyByte)
  1538  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v), nil, false).BodyStart(pkg).End().Pkg().
  1539  		NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1540  	domTest(t, pkg, `package main
  1541  
  1542  func foo(v byte) {
  1543  }
  1544  func main() {
  1545  }
  1546  `)
  1547  }
  1548  
  1549  func TestFuncVariadic(t *testing.T) {
  1550  	pkg := newMainPackage()
  1551  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(gogen.TyByte))
  1552  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v), nil, true).BodyStart(pkg).End()
  1553  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1554  	domTest(t, pkg, `package main
  1555  
  1556  func foo(v ...byte) {
  1557  }
  1558  func main() {
  1559  }
  1560  `)
  1561  }
  1562  
  1563  func TestInitFunc(t *testing.T) {
  1564  	pkg := newMainPackage()
  1565  	pkg.NewFunc(nil, "init", nil, nil, false).BodyStart(pkg).End()
  1566  	pkg.NewFunc(nil, "init", nil, nil, false).BodyStart(pkg).End()
  1567  	domTest(t, pkg, `package main
  1568  
  1569  func init() {
  1570  }
  1571  func init() {
  1572  }
  1573  `)
  1574  }
  1575  
  1576  func TestFuncAsParam(t *testing.T) {
  1577  	pkg := newMainPackage()
  1578  	v := pkg.NewParam(token.NoPos, "v", types.NewSignatureType(nil, nil, nil, nil, nil, false))
  1579  	x := pkg.NewParam(token.NoPos, "x", types.NewPointer(types.Typ[types.Bool]))
  1580  	y := pkg.NewParam(token.NoPos, "y", types.NewChan(types.SendOnly, types.Typ[types.Bool]))
  1581  	z := pkg.NewParam(token.NoPos, "z", types.Typ[types.UnsafePointer])
  1582  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v, x, y, z), nil, false).BodyStart(pkg).End()
  1583  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1584  	domTest(t, pkg, `package main
  1585  
  1586  import "unsafe"
  1587  
  1588  func foo(v func(), x *bool, y chan<- bool, z unsafe.Pointer) {
  1589  }
  1590  func main() {
  1591  }
  1592  `)
  1593  }
  1594  
  1595  func TestNamedFuncAsParam(t *testing.T) {
  1596  	pkg := newMainPackage()
  1597  	typ := pkg.NewType("foo").InitType(pkg, types.NewSignatureType(nil, nil, nil, nil, nil, false))
  1598  	v := pkg.NewParam(token.NoPos, "v", typ)
  1599  	pkg.NewFunc(nil, "bar", gogen.NewTuple(v), nil, false).BodyStart(pkg).
  1600  		VarVal("v").Call(0).EndStmt().
  1601  		End()
  1602  	domTest(t, pkg, `package main
  1603  
  1604  type foo func()
  1605  
  1606  func bar(v foo) {
  1607  	v()
  1608  }
  1609  `)
  1610  }
  1611  
  1612  func TestDefOverloadFunc(t *testing.T) {
  1613  	pkg := newMainPackage()
  1614  	pkg.NewFunc(nil, "bar__0", nil, nil, false).BodyStart(pkg).
  1615  		End()
  1616  	domTest(t, pkg, `package main
  1617  
  1618  func bar__0() {
  1619  }
  1620  `)
  1621  }
  1622  
  1623  func TestDefTemplateMethod(t *testing.T) {
  1624  	pkg := newMainPackage()
  1625  	pkg.NewFunc(nil, "Gopt_bar", nil, nil, false).BodyStart(pkg).
  1626  		End()
  1627  	domTest(t, pkg, `package main
  1628  
  1629  func Gopt_bar() {
  1630  }
  1631  `)
  1632  }
  1633  
  1634  func TestBuiltinFunc(t *testing.T) {
  1635  	var a, n *goxVar
  1636  	pkg := newMainPackage()
  1637  	builtin := pkg.Builtin()
  1638  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(types.Typ[types.Int]))
  1639  	array := pkg.NewParam(token.NoPos, "array", types.NewArray(types.Typ[types.Int], 10))
  1640  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v, array), nil, false).BodyStart(pkg).
  1641  		NewAutoVar(token.NoPos, "a", &a).NewAutoVar(token.NoPos, "n", &n).
  1642  		VarRef(a).
  1643  		/**/ Val(builtin.Ref("append")).Val(v).Val(1).Val(2).Call(3).
  1644  		/**/ Assign(1).EndStmt().
  1645  		VarRef(n).Val(builtin.Ref("len")).Val(a).Call(1).Assign(1).EndStmt().
  1646  		VarRef(n).Val(builtin.Ref("cap")).Val(array).Call(1).Assign(1).EndStmt().
  1647  		End()
  1648  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1649  	domTest(t, pkg, `package main
  1650  
  1651  func foo(v []int, array [10]int) {
  1652  	var a []int
  1653  	var n int
  1654  	a = append(v, 1, 2)
  1655  	n = len(a)
  1656  	n = cap(array)
  1657  }
  1658  func main() {
  1659  }
  1660  `)
  1661  }
  1662  
  1663  func TestComplex(t *testing.T) {
  1664  	pkg := newMainPackage()
  1665  	pkg.NewConstStart(pkg.Types.Scope(), token.NoPos, nil, "a").
  1666  		Val(ctxRef(pkg, "complex")).Val(1).Val(2).Call(2).
  1667  		EndInit(1)
  1668  	pkg.NewConstStart(pkg.Types.Scope(), token.NoPos, nil, "b").
  1669  		Val(ctxRef(pkg, "real")).VarVal("a").Call(1).
  1670  		EndInit(1)
  1671  	pkg.NewConstStart(pkg.Types.Scope(), token.NoPos, nil, "c").
  1672  		Val(ctxRef(pkg, "imag")).VarVal("a").Call(1).
  1673  		EndInit(1)
  1674  	domTest(t, pkg, `package main
  1675  
  1676  const a = complex(1, 2)
  1677  const b = real(a)
  1678  const c = imag(a)
  1679  `)
  1680  }
  1681  
  1682  func TestClose(t *testing.T) {
  1683  	pkg := newMainPackage()
  1684  	tyChan := types.NewChan(types.SendOnly, types.Typ[types.Int])
  1685  	pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "c", tyChan)), nil, false).BodyStart(pkg).
  1686  		Val(ctxRef(pkg, "close")).VarVal("c").Call(1).EndStmt().
  1687  		End()
  1688  	domTest(t, pkg, `package main
  1689  
  1690  func foo(c chan<- int) {
  1691  	close(c)
  1692  }
  1693  `)
  1694  }
  1695  
  1696  func TestAppend(t *testing.T) {
  1697  	pkg := newMainPackage()
  1698  	builtin := pkg.Builtin()
  1699  	tySlice := types.NewSlice(types.Typ[types.Int])
  1700  	pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "a", tySlice)), nil, false).BodyStart(pkg).
  1701  		NewVar(tySlice, "b").VarRef(ctxRef(pkg, "b")).Val(builtin.Ref("append")).
  1702  		VarVal("b").VarVal("a").Call(2, true).Assign(1).EndStmt().
  1703  		End()
  1704  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1705  	domTest(t, pkg, `package main
  1706  
  1707  func foo(a []int) {
  1708  	var b []int
  1709  	b = append(b, a...)
  1710  }
  1711  func main() {
  1712  }
  1713  `)
  1714  }
  1715  
  1716  func TestAppend2(t *testing.T) {
  1717  	pkg := newMainPackage()
  1718  	builtin := pkg.Builtin()
  1719  	tySlice := pkg.NewType("T").InitType(pkg, types.NewSlice(types.Typ[types.Int]))
  1720  	pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "a", tySlice)), nil, false).BodyStart(pkg).
  1721  		NewVar(tySlice, "b").VarRef(ctxRef(pkg, "b")).Val(builtin.Ref("append")).
  1722  		VarVal("b").VarVal("a").Call(2, true).Assign(1).EndStmt().
  1723  		End()
  1724  	domTest(t, pkg, `package main
  1725  
  1726  type T []int
  1727  
  1728  func foo(a T) {
  1729  	var b T
  1730  	b = append(b, a...)
  1731  }
  1732  `)
  1733  }
  1734  
  1735  func TestAppendString(t *testing.T) {
  1736  	pkg := newMainPackage()
  1737  	builtin := pkg.Builtin()
  1738  	tySlice := types.NewSlice(types.Typ[types.Byte])
  1739  	pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "a", tySlice)), nil, false).BodyStart(pkg).
  1740  		VarRef(ctxRef(pkg, "a")).Val(builtin.Ref("append")).
  1741  		VarVal("a").Val("Hi").Call(2, true).Assign(1).EndStmt().
  1742  		End()
  1743  	domTest(t, pkg, `package main
  1744  
  1745  func foo(a []uint8) {
  1746  	a = append(a, "Hi"...)
  1747  }
  1748  `)
  1749  }
  1750  
  1751  func TestCopyString(t *testing.T) {
  1752  	pkg := newMainPackage()
  1753  	builtin := pkg.Builtin()
  1754  	tySlice := types.NewSlice(types.Typ[types.Byte])
  1755  	pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "a", tySlice)), nil, false).BodyStart(pkg).
  1756  		NewVarStart(types.Typ[types.Int], "n").Val(builtin.Ref("copy")).
  1757  		VarVal("a").Val("Hi").Call(2).EndInit(1).
  1758  		End()
  1759  	domTest(t, pkg, `package main
  1760  
  1761  func foo(a []uint8) {
  1762  	var n int = copy(a, "Hi")
  1763  }
  1764  `)
  1765  }
  1766  
  1767  func TestUnsafeFunc(t *testing.T) {
  1768  	pkg := newMainPackage()
  1769  	fields := []*types.Var{
  1770  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  1771  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  1772  	}
  1773  	typ := types.NewStruct(fields, nil)
  1774  	tyT := pkg.NewType("T").InitType(pkg, typ)
  1775  	tyUintptr := types.Typ[types.Uintptr]
  1776  	builtin := pkg.Builtin()
  1777  	unsafe := gogen.PkgRef{types.Unsafe}
  1778  	pkg.NewFunc(nil, "test", nil, nil, false).BodyStart(pkg).
  1779  		NewVar(tyT, "a").NewVar(tyUintptr, "r").
  1780  		VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Sizeof")).VarVal("a").Call(1).Assign(1).EndStmt().
  1781  		VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Alignof")).VarVal("a").Call(1).Assign(1).EndStmt().
  1782  		VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Offsetof")).VarVal("a").MemberVal("y").Call(1).Assign(1).EndStmt().
  1783  		Val(builtin.Ref("println")).VarRef(ctxRef(pkg, "r")).Call(1).EndStmt().
  1784  		End()
  1785  	domTest(t, pkg, `package main
  1786  
  1787  import "unsafe"
  1788  
  1789  type T struct {
  1790  	x int
  1791  	y string
  1792  }
  1793  
  1794  func test() {
  1795  	var a T
  1796  	var r uintptr
  1797  	r = unsafe.Sizeof(a)
  1798  	r = unsafe.Alignof(a)
  1799  	r = unsafe.Offsetof(a.y)
  1800  	println(r)
  1801  }
  1802  `)
  1803  }
  1804  
  1805  func TestUnsafeFunc2(t *testing.T) {
  1806  	pkg := newMainPackage()
  1807  	builtin := pkg.Builtin()
  1808  	unsafe := pkg.Unsafe()
  1809  	tyUP := types.Typ[types.UnsafePointer]
  1810  	tyInt := types.Typ[types.Int]
  1811  	pkg.NewFunc(nil, "test17", nil, nil, false).BodyStart(pkg).
  1812  		NewVar(tyUP, "a").NewVar(tyUP, "r").
  1813  		NewVarStart(nil, "ar").
  1814  		Val(1).Val(2).Val(3).ArrayLit(types.NewArray(tyInt, 3), 3).EndInit(1).
  1815  		NewVar(types.NewSlice(tyInt), "r2").
  1816  		VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Add")).VarVal("a").Val(10).Call(2).Assign(1).EndStmt().
  1817  		VarRef(ctxRef(pkg, "r2")).Val(unsafe.Ref("Slice")).Val(ctxRef(pkg, "ar")).Val(0).Index(1, false).UnaryOp(token.AND).Val(3).Call(2).Assign(1).EndStmt().
  1818  		Val(builtin.Ref("println")).VarRef(ctxRef(pkg, "r")).VarRef(ctxRef(pkg, "r2")).Call(2).EndStmt().
  1819  		End()
  1820  	domTest(t, pkg, `package main
  1821  
  1822  import "unsafe"
  1823  
  1824  func test17() {
  1825  	var a unsafe.Pointer
  1826  	var r unsafe.Pointer
  1827  	var ar = [3]int{1, 2, 3}
  1828  	var r2 []int
  1829  	r = unsafe.Add(a, 10)
  1830  	r2 = unsafe.Slice(&ar[0], 3)
  1831  	println(r, r2)
  1832  }
  1833  `)
  1834  }
  1835  
  1836  func TestUnsafeConst(t *testing.T) {
  1837  	pkg := newMainPackage()
  1838  	unsafe_ := pkg.Unsafe()
  1839  	fieldsM := []*types.Var{
  1840  		types.NewField(token.NoPos, pkg.Types, "m", types.Typ[types.Int], false),
  1841  		types.NewField(token.NoPos, pkg.Types, "n", types.Typ[types.String], false),
  1842  	}
  1843  	typM := types.NewStruct(fieldsM, nil)
  1844  	tyM := pkg.NewType("M").InitType(pkg, typM)
  1845  	fieldsT := []*types.Var{
  1846  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  1847  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  1848  		types.NewField(token.NoPos, pkg.Types, "", tyM, true),
  1849  	}
  1850  	typT := types.NewStruct(fieldsT, nil)
  1851  	tyT := pkg.NewType("T").InitType(pkg, typT)
  1852  	pkg.CB().NewVar(tyT, "t")
  1853  	pkg.CB().NewConstStart(nil, "c1").
  1854  		Val(unsafe_.Ref("Sizeof")).Val(100).Call(1).EndInit(1)
  1855  	pkg.CB().NewConstStart(nil, "c2").
  1856  		Val(unsafe_.Ref("Sizeof")).Val(ctxRef(pkg, "t")).Call(1).EndInit(1)
  1857  	pkg.CB().NewConstStart(nil, "c3").
  1858  		Val(unsafe_.Ref("Alignof")).Val("hello").Call(1).EndInit(1)
  1859  	pkg.CB().NewConstStart(nil, "c4").
  1860  		Val(unsafe_.Ref("Alignof")).Val(ctxRef(pkg, "t")).Call(1).EndInit(1)
  1861  	pkg.CB().NewConstStart(nil, "c5").
  1862  		Val(unsafe_.Ref("Offsetof")).Val(ctxRef(pkg, "t")).MemberVal("y").Call(1).EndInit(1)
  1863  	pkg.CB().NewConstStart(nil, "c6").
  1864  		Val(unsafe_.Ref("Offsetof")).Val(ctxRef(pkg, "t")).MemberVal("n").Call(1).EndInit(1)
  1865  
  1866  	domTest(t, pkg, `package main
  1867  
  1868  import "unsafe"
  1869  
  1870  type M struct {
  1871  	m int
  1872  	n string
  1873  }
  1874  type T struct {
  1875  	x int
  1876  	y string
  1877  	M
  1878  }
  1879  
  1880  var t T
  1881  
  1882  const c1 = unsafe.Sizeof(100)
  1883  const c2 = unsafe.Sizeof(t)
  1884  const c3 = unsafe.Alignof("hello")
  1885  const c4 = unsafe.Alignof(t)
  1886  const c5 = unsafe.Offsetof(t.y)
  1887  const c6 = unsafe.Offsetof(t.n)
  1888  `)
  1889  	c1 := pkg.CB().Val(unsafe_.Ref("Sizeof")).Val(ctxRef(pkg, "t")).Call(1).Get(-1)
  1890  	if v, ok := constant.Int64Val(c1.CVal); !ok || uintptr(v) != (unsafe.Sizeof(int(0))*2+unsafe.Sizeof("")*2) {
  1891  		t.Fatalf("unsafe.Sizeof(t) %v", c1.CVal)
  1892  	}
  1893  	c2 := pkg.CB().Val(unsafe_.Ref("Alignof")).Val(ctxRef(pkg, "t")).Call(1).Get(-1)
  1894  	if v, ok := constant.Int64Val(c2.CVal); !ok || uintptr(v) != unsafe.Alignof("") {
  1895  		t.Fatalf("unsafe.Alignof(t) %v", c2.CVal)
  1896  	}
  1897  	c3 := pkg.CB().Val(unsafe_.Ref("Offsetof")).Val(ctxRef(pkg, "t")).MemberVal("y").Call(1).Get(-1)
  1898  	if v, ok := constant.Int64Val(c3.CVal); !ok || uintptr(v) != unsafe.Sizeof(int(0)) {
  1899  		t.Fatalf("unsafe.Offsetof(t.y) %v", c3.CVal)
  1900  	}
  1901  	c4 := pkg.CB().Val(unsafe_.Ref("Offsetof")).Val(ctxRef(pkg, "t")).MemberVal("n").Call(1).Get(-1)
  1902  	if v, ok := constant.Int64Val(c4.CVal); !ok || uintptr(v) != (unsafe.Sizeof(int(0))*2+unsafe.Sizeof("")) {
  1903  		t.Fatalf("unsafe.Offsetof(t.n) %v", c4.CVal)
  1904  	}
  1905  }
  1906  
  1907  func TestEmptyInterface(t *testing.T) {
  1908  	pkg := newMainPackage()
  1909  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(gogen.TyEmptyInterface))
  1910  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v), nil, true).BodyStart(pkg).End()
  1911  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1912  	domTest(t, pkg, `package main
  1913  
  1914  func foo(v ...interface{}) {
  1915  }
  1916  func main() {
  1917  }
  1918  `)
  1919  }
  1920  
  1921  func TestInterfaceMethods(t *testing.T) {
  1922  	pkg := newMainPackage()
  1923  	methods := []*types.Func{
  1924  		types.NewFunc(token.NoPos, pkg.Types, "Bar", types.NewSignatureType(nil, nil, nil, nil, nil, false)),
  1925  	}
  1926  	tyInterf := types.NewInterfaceType(methods, nil).Complete()
  1927  	bar := pkg.NewType("bar").InitType(pkg, tyInterf)
  1928  	b := pkg.NewParam(token.NoPos, "b", bar)
  1929  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(tyInterf))
  1930  	pkg.NewFunc(nil, "foo", gogen.NewTuple(b, v), nil, true).BodyStart(pkg).
  1931  		Val(b).MemberVal("Bar").Call(0).EndStmt().
  1932  		Val(v).Val(0).Index(1, false).MemberVal("Bar").Call(0).EndStmt().
  1933  		End()
  1934  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1935  	domTest(t, pkg, `package main
  1936  
  1937  type bar interface {
  1938  	Bar()
  1939  }
  1940  
  1941  func foo(b bar, v ...interface {
  1942  	Bar()
  1943  }) {
  1944  	b.Bar()
  1945  	v[0].Bar()
  1946  }
  1947  func main() {
  1948  }
  1949  `)
  1950  }
  1951  
  1952  func TestFuncCall(t *testing.T) {
  1953  	pkg := newMainPackage()
  1954  	fmt := pkg.Import("fmt")
  1955  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  1956  		Val(fmt.Ref("Println")).Val("Hello").Call(1, false).EndStmt().
  1957  		End()
  1958  	domTest(t, pkg, `package main
  1959  
  1960  import "fmt"
  1961  
  1962  func main() {
  1963  	fmt.Println("Hello")
  1964  }
  1965  `)
  1966  }
  1967  
  1968  func TestFuncCallEllipsis(t *testing.T) {
  1969  	pkg := newMainPackage()
  1970  	fmt := pkg.Import("fmt")
  1971  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(types.NewInterfaceType(nil, nil).Complete()))
  1972  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v), nil, true).BodyStart(pkg).
  1973  		Val(fmt.Ref("Println")).Val(v).Call(1, true).EndStmt().
  1974  		End()
  1975  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  1976  	domTest(t, pkg, `package main
  1977  
  1978  import "fmt"
  1979  
  1980  func foo(v ...interface{}) {
  1981  	fmt.Println(v...)
  1982  }
  1983  func main() {
  1984  }
  1985  `)
  1986  }
  1987  
  1988  func TestDelayedLoadUnused(t *testing.T) {
  1989  	pkg := newMainPackage()
  1990  	println := gogen.NewOverloadFunc(token.NoPos, pkg.Types, "println", pkg.Import("fmt").Ref("Println"))
  1991  	pkg.Types.Scope().Insert(println)
  1992  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  1993  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  1994  	n := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  1995  	err := pkg.NewParam(token.NoPos, "", types.Universe.Lookup("error").Type())
  1996  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  1997  		End()
  1998  	domTest(t, pkg, `package main
  1999  
  2000  func foo(format string, args ...interface{}) (int, error) {
  2001  }
  2002  `)
  2003  }
  2004  
  2005  func TestDelayedLoadUsed(t *testing.T) {
  2006  	pkg := newMainPackage()
  2007  	printf := gogen.NewOverloadFunc(token.NoPos, pkg.Types, "printf", pkg.Import("fmt").Ref("Printf"))
  2008  	pkg.Types.Scope().Insert(printf)
  2009  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  2010  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  2011  	n := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  2012  	err := pkg.NewParam(token.NoPos, "", types.Universe.Lookup("error").Type())
  2013  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  2014  		Val(printf).Val(format).Val(args).Call(2, true).Return(1).
  2015  		End()
  2016  	domTest(t, pkg, `package main
  2017  
  2018  import "fmt"
  2019  
  2020  func foo(format string, args ...interface{}) (int, error) {
  2021  	return fmt.Printf(format, args...)
  2022  }
  2023  `)
  2024  }
  2025  
  2026  func TestIf(t *testing.T) {
  2027  	pkg := newMainPackage()
  2028  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2029  		/**/ If().DefineVarStart(0, "x").Val(3).EndInit(1).
  2030  		/******/ Val(ctxRef(pkg, "x")).Val(1).BinaryOp(token.GTR).Then().
  2031  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val("OK!").Call(1).EndStmt().
  2032  		/**/ End().
  2033  		End()
  2034  	domTest(t, pkg, `package main
  2035  
  2036  import "fmt"
  2037  
  2038  func main() {
  2039  	if x := 3; x > 1 {
  2040  		fmt.Println("OK!")
  2041  	}
  2042  }
  2043  `)
  2044  }
  2045  
  2046  func TestIfElse(t *testing.T) {
  2047  	pkg := newMainPackage()
  2048  	fmt := pkg.Import("fmt")
  2049  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2050  		/**/ If().DefineVarStart(0, "x").Val(3).EndInit(1).
  2051  		/******/ Val(ctxRef(pkg, "x")).Val(1).BinaryOp(token.GTR).Then().
  2052  		/******/ Val(fmt.Ref("Println")).Val("OK!").Call(1).EndStmt().
  2053  		/**/ Else().If().Val(ctxRef(pkg, "x")).Val(0).BinaryOp(token.GTR).Then().
  2054  		/******/ Val(fmt.Ref("Println")).Val("Hi").Call(1).EndStmt().
  2055  		/****/ Else().
  2056  		/******/ Val(fmt.Ref("Println")).Val("Error!").Call(1).EndStmt().
  2057  		/****/ End().
  2058  		/**/ End().
  2059  		End()
  2060  	domTest(t, pkg, `package main
  2061  
  2062  import "fmt"
  2063  
  2064  func main() {
  2065  	if x := 3; x > 1 {
  2066  		fmt.Println("OK!")
  2067  	} else if x > 0 {
  2068  		fmt.Println("Hi")
  2069  	} else {
  2070  		fmt.Println("Error!")
  2071  	}
  2072  }
  2073  `)
  2074  }
  2075  
  2076  func TestGoto(t *testing.T) {
  2077  	pkg := newMainPackage()
  2078  	cb := pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
  2079  	l := cb.NewLabel(token.NoPos, "retry")
  2080  	cb.Label(l).Goto(l).
  2081  		End()
  2082  	domTest(t, pkg, `package main
  2083  
  2084  func main() {
  2085  retry:
  2086  	goto retry
  2087  }
  2088  `)
  2089  }
  2090  
  2091  func TestMultiLabel(t *testing.T) {
  2092  	pkg := newMainPackage()
  2093  	cb := pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
  2094  	l := cb.NewLabel(token.NoPos, "retry")
  2095  	l2 := cb.NewLabel(token.NoPos, "retry2")
  2096  	cb.Label(l).Label(l2).Goto(l).Goto(l2).
  2097  		End()
  2098  	domTest(t, pkg, `package main
  2099  
  2100  func main() {
  2101  retry:
  2102  	;
  2103  retry2:
  2104  	goto retry
  2105  	goto retry2
  2106  }
  2107  `)
  2108  }
  2109  
  2110  func TestBreakContinue(t *testing.T) { // TODO: check invalid syntax
  2111  	pkg := newMainPackage()
  2112  	cb := pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
  2113  	l := cb.NewLabel(token.NoPos, "retry")
  2114  	cb.Label(l).Break(nil).Continue(nil).
  2115  		Break(l).Continue(l).
  2116  		End()
  2117  	domTest(t, pkg, `package main
  2118  
  2119  func main() {
  2120  retry:
  2121  	break
  2122  	continue
  2123  	break retry
  2124  	continue retry
  2125  }
  2126  `)
  2127  }
  2128  
  2129  func TestGoDefer(t *testing.T) { // TODO: check invalid syntax
  2130  	pkg := newMainPackage()
  2131  	fmt := pkg.Import("fmt")
  2132  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2133  		Val(fmt.Ref("Println")).Val("Hi").Call(1).Go().
  2134  		Val(fmt.Ref("Println")).Val("Go+").Call(1).Defer().
  2135  		End()
  2136  	domTest(t, pkg, `package main
  2137  
  2138  import "fmt"
  2139  
  2140  func main() {
  2141  	go fmt.Println("Hi")
  2142  	defer fmt.Println("Go+")
  2143  }
  2144  `)
  2145  }
  2146  
  2147  func TestSwitch(t *testing.T) {
  2148  	pkg := newMainPackage()
  2149  	fmt := pkg.Import("fmt")
  2150  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2151  		/**/ Switch().DefineVarStart(0, "x").Val(3).EndInit(1).Val(ctxRef(pkg, "x")).Then(). // switch x := 3; x {
  2152  		/**/ Case().Val(1).Val(2).Then(). // case 1, 2:
  2153  		/******/ Val(fmt.Ref("Println")).Val("1 or 2").Call(1).EndStmt().
  2154  		/******/ End().
  2155  		/**/ Case().Val(3).Then(). // case 3:
  2156  		/******/ Val(fmt.Ref("Println")).Val("3").Call(1).EndStmt().
  2157  		/******/ End().
  2158  		/**/ DefaultThen(). // default:
  2159  		/******/ Val(fmt.Ref("Println")).Val("other").Call(1).EndStmt().
  2160  		/******/ End().
  2161  		/**/ End(). // end switch
  2162  		End()
  2163  	domTest(t, pkg, `package main
  2164  
  2165  import "fmt"
  2166  
  2167  func main() {
  2168  	switch x := 3; x {
  2169  	case 1, 2:
  2170  		fmt.Println("1 or 2")
  2171  	case 3:
  2172  		fmt.Println("3")
  2173  	default:
  2174  		fmt.Println("other")
  2175  	}
  2176  }
  2177  `)
  2178  }
  2179  
  2180  func TestSwitchNoTag(t *testing.T) {
  2181  	pkg := newMainPackage()
  2182  	fmt := pkg.Import("fmt")
  2183  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2184  		/**/ DefineVarStart(0, "x").Val(3).EndInit(1).
  2185  		/**/ Switch().None().Then(). // switch {
  2186  		/**/ Case().Val(ctxRef(pkg, "x")).Val(2).BinaryOp(token.EQL).Then(). // case x == 2:
  2187  		/******/ Val(fmt.Ref("Println")).Val("x = 2").Call(1).EndStmt().
  2188  		/******/ Fallthrough().
  2189  		/******/ End().
  2190  		/**/ Case().Val(ctxRef(pkg, "x")).Val(3).BinaryOp(token.LSS).Then(). // case x < 3:
  2191  		/******/ Val(fmt.Ref("Println")).Val("x < 3").Call(1).EndStmt().
  2192  		/******/ End().
  2193  		/**/ DefaultThen(). // default:
  2194  		/******/ Val(fmt.Ref("Println")).Val("other").Call(1).EndStmt().
  2195  		/******/ End().
  2196  		/**/ End(). // end switch
  2197  		End()
  2198  	domTest(t, pkg, `package main
  2199  
  2200  import "fmt"
  2201  
  2202  func main() {
  2203  	x := 3
  2204  	switch {
  2205  	case x == 2:
  2206  		fmt.Println("x = 2")
  2207  		fallthrough
  2208  	case x < 3:
  2209  		fmt.Println("x < 3")
  2210  	default:
  2211  		fmt.Println("other")
  2212  	}
  2213  }
  2214  `)
  2215  }
  2216  
  2217  func TestFor(t *testing.T) {
  2218  	pkg := newMainPackage()
  2219  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2220  		/**/ For().DefineVarStart(0, "i").Val(0).EndInit(1). // for i := 0; i < len("Hello"); i=i+1 {
  2221  		/******/ Val(ctxRef(pkg, "i")).Val(ctxRef(pkg, "len")).Val("Hello").Call(1).BinaryOp(token.LSS).Then().
  2222  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "i")).Call(1).EndStmt().
  2223  		/******/ Post().
  2224  		/******/ VarRef(ctxRef(pkg, "i")).Val(ctxRef(pkg, "i")).Val(1).BinaryOp(token.ADD).Assign(1).EndStmt().
  2225  		/**/ End().
  2226  		End()
  2227  	domTest(t, pkg, `package main
  2228  
  2229  import "fmt"
  2230  
  2231  func main() {
  2232  	for i := 0; i < len("Hello"); i = i + 1 {
  2233  		fmt.Println(i)
  2234  	}
  2235  }
  2236  `)
  2237  }
  2238  
  2239  func TestLoopFor(t *testing.T) {
  2240  	pkg := newMainPackage()
  2241  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2242  		/**/ For().None().Then(). // for {
  2243  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val("Hi").Call(1).EndStmt().
  2244  		/**/ End().
  2245  		End()
  2246  	domTest(t, pkg, `package main
  2247  
  2248  import "fmt"
  2249  
  2250  func main() {
  2251  	for {
  2252  		fmt.Println("Hi")
  2253  	}
  2254  }
  2255  `)
  2256  }
  2257  
  2258  func TestLabeledFor(t *testing.T) {
  2259  	pkg := newMainPackage()
  2260  	cb := pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg)
  2261  	l := cb.NewLabel(token.NoPos, "label")
  2262  	cb.Label(l).
  2263  		/**/ For().DefineVarStart(0, "i").Val(0).EndInit(1). // for i := 0; i < 10; i=i+1 {
  2264  		/******/ Val(ctxRef(pkg, "i")).Val(10).BinaryOp(token.LSS).Then().
  2265  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "i")).Call(1).EndStmt().
  2266  		/******/ Break(l).
  2267  		/******/ Post().
  2268  		/******/ VarRef(ctxRef(pkg, "i")).Val(ctxRef(pkg, "i")).Val(1).BinaryOp(token.ADD).Assign(1).EndStmt().
  2269  		/**/ End().
  2270  		End()
  2271  	domTest(t, pkg, `package main
  2272  
  2273  import "fmt"
  2274  
  2275  func main() {
  2276  label:
  2277  	for i := 0; i < 10; i = i + 1 {
  2278  		fmt.Println(i)
  2279  		break label
  2280  	}
  2281  }
  2282  `)
  2283  }
  2284  
  2285  func TestForRange(t *testing.T) {
  2286  	pkg := newMainPackage()
  2287  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2288  		DefineVarStart(0, "a").Val(1).Val(1.2).Val(3).SliceLit(nil, 3).EndInit(1).
  2289  		/**/ ForRange("i").VarVal("a").RangeAssignThen(token.NoPos).
  2290  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "i")).Call(1).EndStmt().
  2291  		/**/ End().
  2292  		End()
  2293  	domTest(t, pkg, `package main
  2294  
  2295  import "fmt"
  2296  
  2297  func main() {
  2298  	a := []float64{1, 1.2, 3}
  2299  	for i := range a {
  2300  		fmt.Println(i)
  2301  	}
  2302  }
  2303  `)
  2304  }
  2305  
  2306  func TestForRange2(t *testing.T) {
  2307  	pkg := newMainPackage()
  2308  	typ := pkg.NewType("T").InitType(pkg, types.NewSlice(types.Typ[types.Float64]))
  2309  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2310  		DefineVarStart(0, "a").Val(1).Val(1.2).Val(3).SliceLit(typ, 3).EndInit(1).
  2311  		/**/ ForRange("i").VarVal("a").RangeAssignThen(token.NoPos).
  2312  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "i")).Call(1).EndStmt().
  2313  		/**/ End().
  2314  		End()
  2315  	domTest(t, pkg, `package main
  2316  
  2317  import "fmt"
  2318  
  2319  type T []float64
  2320  
  2321  func main() {
  2322  	a := T{1, 1.2, 3}
  2323  	for i := range a {
  2324  		fmt.Println(i)
  2325  	}
  2326  }
  2327  `)
  2328  }
  2329  
  2330  func TestForRange3(t *testing.T) {
  2331  	pkg := newMainPackage()
  2332  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2333  		ForRange().Val("Hi").RangeAssignThen(token.NoPos).End().
  2334  		End()
  2335  	domTest(t, pkg, `package main
  2336  
  2337  func main() {
  2338  	for range "Hi" {
  2339  	}
  2340  }
  2341  `)
  2342  }
  2343  
  2344  func TestForRangeChan(t *testing.T) {
  2345  	pkg := newMainPackage()
  2346  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2347  		NewVar(types.NewChan(types.SendRecv, types.Typ[types.Int]), "a").
  2348  		/**/ ForRange("_", "i").VarVal("a").RangeAssignThen(token.NoPos).
  2349  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "i")).Call(1).EndStmt().
  2350  		/**/ End().
  2351  		End()
  2352  	domTest(t, pkg, `package main
  2353  
  2354  import "fmt"
  2355  
  2356  func main() {
  2357  	var a chan int
  2358  	for i := range a {
  2359  		fmt.Println(i)
  2360  	}
  2361  }
  2362  `)
  2363  }
  2364  
  2365  func TestForRangeKV(t *testing.T) {
  2366  	pkg := newMainPackage()
  2367  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2368  		DefineVarStart(0, "a").Val(1).Val(1.2).Val(3).ArrayLit(types.NewArray(types.Typ[types.Float64], 3), 3).EndInit(1).
  2369  		/**/ ForRange("_", "x").VarVal("a").RangeAssignThen(token.NoPos).
  2370  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "x")).Call(1).EndStmt().
  2371  		/**/ End().
  2372  		End()
  2373  	domTest(t, pkg, `package main
  2374  
  2375  import "fmt"
  2376  
  2377  func main() {
  2378  	a := [3]float64{1, 1.2, 3}
  2379  	for _, x := range a {
  2380  		fmt.Println(x)
  2381  	}
  2382  }
  2383  `)
  2384  }
  2385  
  2386  func TestForRangeArrayPointer(t *testing.T) {
  2387  	pkg := newMainPackage()
  2388  	v := pkg.NewParam(token.NoPos, "a", types.NewPointer(types.NewArray(types.Typ[types.Float64], 3)))
  2389  	pkg.NewFunc(nil, "foo", gogen.NewTuple(v), nil, false).BodyStart(pkg).
  2390  		/**/ ForRange("_", "x").VarVal("a").RangeAssignThen(token.NoPos).
  2391  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "x")).Call(1).EndStmt().
  2392  		/**/ End().
  2393  		End()
  2394  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2395  	domTest(t, pkg, `package main
  2396  
  2397  import "fmt"
  2398  
  2399  func foo(a *[3]float64) {
  2400  	for _, x := range a {
  2401  		fmt.Println(x)
  2402  	}
  2403  }
  2404  func main() {
  2405  }
  2406  `)
  2407  }
  2408  
  2409  func TestForRangeNoAssign(t *testing.T) {
  2410  	pkg := newMainPackage()
  2411  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2412  		DefineVarStart(0, "a").Val(1).Val(1.2).Val(3).SliceLit(nil, 3).EndInit(1).
  2413  		/**/ ForRange().VarVal("a").RangeAssignThen(token.NoPos).
  2414  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val("Hi").Call(1).EndStmt().
  2415  		/**/ End().
  2416  		End()
  2417  	domTest(t, pkg, `package main
  2418  
  2419  import "fmt"
  2420  
  2421  func main() {
  2422  	a := []float64{1, 1.2, 3}
  2423  	for range a {
  2424  		fmt.Println("Hi")
  2425  	}
  2426  }
  2427  `)
  2428  }
  2429  
  2430  func TestForRangeAssignKV(t *testing.T) {
  2431  	pkg := newMainPackage()
  2432  	tyString := types.Typ[types.String]
  2433  	tyInt := types.Typ[types.Int]
  2434  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2435  		NewVar(tyString, "k").NewVar(tyInt, "v").
  2436  		DefineVarStart(0, "a").Val("a").Val(1).Val("b").Val(3).MapLit(nil, 4).EndInit(1).
  2437  		/**/ ForRange().VarRef(ctxRef(pkg, "k")).VarRef(ctxRef(pkg, "v")).VarVal("a").RangeAssignThen(token.NoPos).
  2438  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "k")).VarVal("v").Call(2).EndStmt().
  2439  		/**/ End().
  2440  		End()
  2441  	domTest(t, pkg, `package main
  2442  
  2443  import "fmt"
  2444  
  2445  func main() {
  2446  	var k string
  2447  	var v int
  2448  	a := map[string]int{"a": 1, "b": 3}
  2449  	for k, v = range a {
  2450  		fmt.Println(k, v)
  2451  	}
  2452  }
  2453  `)
  2454  }
  2455  
  2456  func TestForRangeAssign(t *testing.T) {
  2457  	pkg := newMainPackage()
  2458  	tyBool := types.Typ[types.Bool]
  2459  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2460  		NewVar(tyBool, "k").
  2461  		NewVar(types.NewChan(types.SendRecv, tyBool), "a").
  2462  		/**/ ForRange().VarRef(ctxRef(pkg, "k")).VarVal("a").RangeAssignThen(token.NoPos).
  2463  		/******/ Val(pkg.Import("fmt").Ref("Println")).Val(ctxRef(pkg, "k")).Call(1).EndStmt().
  2464  		/**/ End().
  2465  		End()
  2466  	domTest(t, pkg, `package main
  2467  
  2468  import "fmt"
  2469  
  2470  func main() {
  2471  	var k bool
  2472  	var a chan bool
  2473  	for k = range a {
  2474  		fmt.Println(k)
  2475  	}
  2476  }
  2477  `)
  2478  }
  2479  
  2480  func TestReturn(t *testing.T) {
  2481  	pkg := newMainPackage()
  2482  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  2483  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  2484  	n := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  2485  	err := pkg.NewParam(token.NoPos, "", types.Universe.Lookup("error").Type())
  2486  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  2487  		Val(pkg.Import("fmt").Ref("Printf")).Val(format).Val(args).Call(2, true).Return(1).
  2488  		End()
  2489  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2490  	domTest(t, pkg, `package main
  2491  
  2492  import "fmt"
  2493  
  2494  func foo(format string, args ...interface{}) (int, error) {
  2495  	return fmt.Printf(format, args...)
  2496  }
  2497  func main() {
  2498  }
  2499  `)
  2500  }
  2501  
  2502  func TestReturnExpr(t *testing.T) {
  2503  	pkg := newMainPackage()
  2504  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  2505  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  2506  	n := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  2507  	err := pkg.NewParam(token.NoPos, "", types.Universe.Lookup("error").Type())
  2508  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  2509  		Val(0).Val(types.Universe.Lookup("nil")).Return(2).
  2510  		End()
  2511  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2512  	domTest(t, pkg, `package main
  2513  
  2514  func foo(format string, args ...interface{}) (int, error) {
  2515  	return 0, nil
  2516  }
  2517  func main() {
  2518  }
  2519  `)
  2520  }
  2521  
  2522  func TestReturnNamedResults(t *testing.T) {
  2523  	pkg := newMainPackage()
  2524  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  2525  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  2526  	n := pkg.NewParam(token.NoPos, "n", types.Typ[types.Int])
  2527  	err := pkg.NewParam(token.NoPos, "err", types.Universe.Lookup("error").Type())
  2528  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  2529  		VarRef(pkg.CB().Scope().Lookup("n")).VarRef(err).Val(1).Val(nil).Assign(2).
  2530  		Return(0).
  2531  		End()
  2532  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2533  	domTest(t, pkg, `package main
  2534  
  2535  func foo(format string, args ...interface{}) (n int, err error) {
  2536  	n, err = 1, nil
  2537  	return
  2538  }
  2539  func main() {
  2540  }
  2541  `)
  2542  }
  2543  
  2544  func TestImport(t *testing.T) {
  2545  	pkg := newMainPackage()
  2546  	fmt := pkg.Import("fmt")
  2547  
  2548  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(gogen.TyByte))
  2549  	pkg.NewFunc(nil, "fmt", gogen.NewTuple(v), nil, false).BodyStart(pkg).End()
  2550  
  2551  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2552  		Val(fmt.Ref("Println")).Val("Hello").Call(1).EndStmt().
  2553  		End()
  2554  	domTest(t, pkg, `package main
  2555  
  2556  import fmt1 "fmt"
  2557  
  2558  func fmt(v []byte) {
  2559  }
  2560  func main() {
  2561  	fmt1.Println("Hello")
  2562  }
  2563  `)
  2564  }
  2565  
  2566  func TestImportUnused(t *testing.T) {
  2567  	pkg := newMainPackage()
  2568  	pkg.Import("fmt")
  2569  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2570  	domTest(t, pkg, `package main
  2571  
  2572  func main() {
  2573  }
  2574  `)
  2575  }
  2576  
  2577  func TestImportForceUsed(t *testing.T) {
  2578  	pkg := newMainPackage()
  2579  	pkg.ForceImport("fmt")
  2580  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2581  	domTest(t, pkg, `package main
  2582  
  2583  import _ "fmt"
  2584  
  2585  func main() {
  2586  }
  2587  `)
  2588  }
  2589  
  2590  func TestImportForceUsed2(t *testing.T) {
  2591  	pkg := newMainPackage()
  2592  	pkg.Import("fmt").MarkForceUsed(pkg)
  2593  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2594  	domTest(t, pkg, `package main
  2595  
  2596  import _ "fmt"
  2597  
  2598  func main() {
  2599  }
  2600  `)
  2601  }
  2602  
  2603  func TestImportAnyWhere(t *testing.T) {
  2604  	pkg := newMainPackage()
  2605  
  2606  	v := pkg.NewParam(token.NoPos, "v", types.NewSlice(gogen.TyByte))
  2607  	pkg.NewFunc(nil, "fmt", gogen.NewTuple(v), nil, false).BodyStart(pkg).End()
  2608  
  2609  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2610  		Val(pkg.Import("fmt").Ref("Println")).Val("Hello").Call(1).EndStmt().
  2611  		End()
  2612  	domTest(t, pkg, `package main
  2613  
  2614  import fmt1 "fmt"
  2615  
  2616  func fmt(v []byte) {
  2617  }
  2618  func main() {
  2619  	fmt1.Println("Hello")
  2620  }
  2621  `)
  2622  }
  2623  
  2624  func TestImportAndCallMethod(t *testing.T) {
  2625  	var x *goxVar
  2626  	pkg := newMainPackage()
  2627  	strings := pkg.Import("strings")
  2628  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2629  		NewAutoVar(token.NoPos, "x", &x).
  2630  		VarRef(x).Val(strings.Ref("NewReplacer")).Val("?").Val("!").Call(2).
  2631  		/**/ MemberVal("Replace").Val("hello, world???").Call(1).Assign(1).EndStmt().
  2632  		Val(pkg.Builtin().Ref("println")).Val(x).Call(1).EndStmt().
  2633  		End()
  2634  	domTest(t, pkg, `package main
  2635  
  2636  import "strings"
  2637  
  2638  func main() {
  2639  	var x string
  2640  	x = strings.NewReplacer("?", "!").Replace("hello, world???")
  2641  	println(x)
  2642  }
  2643  `)
  2644  }
  2645  
  2646  func TestOverloadFunc(t *testing.T) {
  2647  	var f, g, x, y *goxVar
  2648  	pkg := newMainPackage()
  2649  	builtin := pkg.Builtin()
  2650  	c64 := pkg.NewParam(token.NoPos, "c64", types.Typ[types.Complex64])
  2651  	c128 := pkg.NewParam(token.NoPos, "c128", types.Typ[types.Complex128])
  2652  	pkg.NewFunc(nil, "foo", gogen.NewTuple(c64, c128), nil, false).BodyStart(pkg).
  2653  		NewAutoVar(token.NoPos, "f", &f).NewAutoVar(token.NoPos, "g", &g).
  2654  		NewAutoVar(token.NoPos, "x", &x).NewAutoVar(token.NoPos, "y", &y).
  2655  		VarRef(f).Val(builtin.Ref("imag")).Val(c128).Call(1).Assign(1).EndStmt().
  2656  		VarRef(g).Val(builtin.Ref("real")).Val(c64).Call(1).Assign(1).EndStmt().
  2657  		VarRef(x).Val(builtin.Ref("complex")).Val(0).Val(f).Call(2).Assign(1).EndStmt().
  2658  		VarRef(y).Val(builtin.Ref("complex")).Val(g).Val(1).Call(2).Assign(1).EndStmt().
  2659  		End()
  2660  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2661  	domTest(t, pkg, `package main
  2662  
  2663  func foo(c64 complex64, c128 complex128) {
  2664  	var f float64
  2665  	var g float32
  2666  	var x complex128
  2667  	var y complex64
  2668  	f = imag(c128)
  2669  	g = real(c64)
  2670  	x = complex(0, f)
  2671  	y = complex(g, 1)
  2672  }
  2673  func main() {
  2674  }
  2675  `)
  2676  }
  2677  
  2678  func TestOverloadFunc2(t *testing.T) {
  2679  	pkg := newMainPackage()
  2680  	bar := pkg.Import("github.com/goplus/gogen/internal/overload")
  2681  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2682  		Val(bar.Ref("Put")).Val("1").Call(1).EndStmt().
  2683  		Val(bar.Ref("Put2")).Val(1).Call(1).EndStmt().
  2684  		End()
  2685  	domTest(t, pkg, `package main
  2686  
  2687  import "github.com/goplus/gogen/internal/overload"
  2688  
  2689  func main() {
  2690  	overload.PutString("1")
  2691  	overload.Put2__0(1)
  2692  }
  2693  `)
  2694  }
  2695  
  2696  func TestOverloadMethod(t *testing.T) {
  2697  	pkg := newMainPackage()
  2698  	bar := pkg.Import("github.com/goplus/gogen/internal/overload")
  2699  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2700  		NewVar(bar.Ref("Game").Type(), "g").
  2701  		VarVal("g").MemberVal("Run").Val("Hi").Call(1).EndStmt().
  2702  		VarVal("g").MemberVal("Run2").Val(1).Call(1).EndStmt().
  2703  		// TODO: VarVal("g").MemberVal("Run3").Val("1").Call(1).EndStmt().
  2704  		End()
  2705  	domTest(t, pkg, `package main
  2706  
  2707  import "github.com/goplus/gogen/internal/overload"
  2708  
  2709  func main() {
  2710  	var g overload.Game
  2711  	g.RunString("Hi")
  2712  	g.Run2__0(1)
  2713  }
  2714  `)
  2715  }
  2716  
  2717  func TestOverloadMethod2(t *testing.T) {
  2718  	pkg := newMainPackage()
  2719  	foo := pkg.Import("github.com/goplus/gogen/internal/foo")
  2720  	nodeSet := foo.Ref("NodeSet").Type()
  2721  	v := pkg.NewParam(token.NoPos, "v", nodeSet)
  2722  	pkg.NewFunc(nil, "bar", types.NewTuple(v), nil, false).BodyStart(pkg).
  2723  		DefineVarStart(token.NoPos, "val", "err").Val(v).
  2724  		Debug(func(cb *gogen.CodeBuilder) {
  2725  			if kind, err := cb.Member("attr", gogen.MemberFlagAutoProperty); err == nil {
  2726  				t.Fatal("cb.Member v.attr no error?", kind)
  2727  			}
  2728  			cb.Member("attr", gogen.MemberFlagMethodAlias)
  2729  		}).
  2730  		Val("key").Call(1).EndInit(1).EndStmt().
  2731  		Val(v).
  2732  		Debug(func(cb *gogen.CodeBuilder) {
  2733  			cb.Member("len", gogen.MemberFlagAutoProperty)
  2734  		}).EndStmt().
  2735  		VarRef(v).Val(v).MemberVal("Attr").Val("key").Val("val").Call(2).Assign(1).
  2736  		End()
  2737  	domTest(t, pkg, `package main
  2738  
  2739  import "github.com/goplus/gogen/internal/foo"
  2740  
  2741  func bar(v foo.NodeSet) {
  2742  	val, err := v.Attr__0("key")
  2743  	v.Len__0()
  2744  	v = v.Attr__1("key", "val")
  2745  }
  2746  `)
  2747  }
  2748  
  2749  func TestOverloadInterfaceMethod(t *testing.T) {
  2750  	pkg := newMainPackage()
  2751  	foo := pkg.Import("github.com/goplus/gogen/internal/foo")
  2752  	nodeSet := foo.Ref("NodeSeter").Type()
  2753  	v := pkg.NewParam(token.NoPos, "v", nodeSet)
  2754  	pkg.NewFunc(nil, "bar", types.NewTuple(v), nil, false).BodyStart(pkg).
  2755  		DefineVarStart(token.NoPos, "val", "err").Val(v).
  2756  		Debug(func(cb *gogen.CodeBuilder) {
  2757  			if kind, err := cb.Member("attr", gogen.MemberFlagAutoProperty); err == nil {
  2758  				t.Fatal("cb.Member v.attr no error?", kind)
  2759  			}
  2760  			cb.Member("attr", gogen.MemberFlagMethodAlias)
  2761  		}).
  2762  		Val("key").Call(1).EndInit(1).EndStmt().
  2763  		Val(v).
  2764  		Debug(func(cb *gogen.CodeBuilder) {
  2765  			cb.Member("len", gogen.MemberFlagAutoProperty)
  2766  		}).EndStmt().
  2767  		VarRef(v).Val(v).MemberVal("Attr").Val("key").Val("val").Call(2).Assign(1).
  2768  		End()
  2769  	domTest(t, pkg, `package main
  2770  
  2771  import "github.com/goplus/gogen/internal/foo"
  2772  
  2773  func bar(v foo.NodeSeter) {
  2774  	val, err := v.Attr__0("key")
  2775  	v.Len__0()
  2776  	v = v.Attr__1("key", "val")
  2777  }
  2778  `)
  2779  }
  2780  
  2781  func TestPkgVar(t *testing.T) {
  2782  	pkg := newMainPackage()
  2783  	flag := pkg.Import("flag")
  2784  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2785  		VarRef(flag.Ref("Usage")).Val(nil).Assign(1).
  2786  		End()
  2787  	domTest(t, pkg, `package main
  2788  
  2789  import "flag"
  2790  
  2791  func main() {
  2792  	flag.Usage = nil
  2793  }
  2794  `)
  2795  }
  2796  
  2797  func TestEmbbedMember(t *testing.T) {
  2798  	pkg := newMainPackage()
  2799  	test := pkg.Import("testing")
  2800  	typ := pkg.NewParam(token.NoPos, "t", types.NewPointer(test.Ref("T").Type()))
  2801  	pkg.NewFunc(nil, "foo", types.NewTuple(typ), nil, false).BodyStart(pkg).
  2802  		Val(ctxRef(pkg, "t")).
  2803  		MemberVal("Fatal").
  2804  		Call(0).
  2805  		EndStmt().
  2806  		End()
  2807  	domTest(t, pkg, `package main
  2808  
  2809  import "testing"
  2810  
  2811  func foo(t *testing.T) {
  2812  	t.Fatal()
  2813  }
  2814  `)
  2815  }
  2816  
  2817  func TestMemberAutoProperty(t *testing.T) {
  2818  	pkg := newMainPackage()
  2819  	test := pkg.Import("testing")
  2820  	typ := pkg.NewParam(token.NoPos, "t", types.NewPointer(test.Ref("T").Type()))
  2821  	pkg.NewFunc(nil, "foo", types.NewTuple(typ), nil, false).BodyStart(pkg).
  2822  		Val(ctxRef(pkg, "t")).
  2823  		Debug(func(cb *gogen.CodeBuilder) {
  2824  			if kind, err := cb.Member("fatal", gogen.MemberFlagAutoProperty); err == nil {
  2825  				t.Fatal("cb.Member t.fatal no error?", kind)
  2826  			}
  2827  			cb.Member("name", gogen.MemberFlagAutoProperty)
  2828  		}).
  2829  		EndStmt().
  2830  		End()
  2831  	domTest(t, pkg, `package main
  2832  
  2833  import "testing"
  2834  
  2835  func foo(t *testing.T) {
  2836  	t.Name()
  2837  }
  2838  `)
  2839  }
  2840  
  2841  func TestStructMember(t *testing.T) {
  2842  	pkg := newMainPackage()
  2843  	fields := []*types.Var{
  2844  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  2845  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  2846  	}
  2847  	typ := types.NewStruct(fields, nil)
  2848  	foo := pkg.NewType("foo").InitType(pkg, typ)
  2849  	pkg.CB().NewVarStart(nil, "a").
  2850  		Val(123).Val("Hi").
  2851  		StructLit(typ, 2, false).EndInit(1)
  2852  	pkg.CB().NewVarStart(nil, "b").
  2853  		VarVal("a").
  2854  		Debug(func(cb *gogen.CodeBuilder) {
  2855  			kind, err := cb.Member("unknown", gogen.MemberFlagVal, source("a.unknown", 1, 5))
  2856  			if kind != gogen.MemberInvalid ||
  2857  				err.Error() != "./foo.gop:1:5: a.unknown undefined (type struct{x int; y string} has no field or method unknown)" {
  2858  				t.Fatal("Member unknown:", kind, err)
  2859  			}
  2860  		}).
  2861  		MemberVal("y").EndInit(1)
  2862  	pkg.CB().NewVarStart(nil, "c").
  2863  		Val(123).Val("Hi").
  2864  		StructLit(foo, 2, false).EndInit(1)
  2865  	pkg.CB().NewVarStart(nil, "d").
  2866  		VarVal("c").MemberVal("x").EndInit(1)
  2867  	pkg.CB().NewVarStart(nil, "e").
  2868  		VarVal("a").UnaryOp(token.AND).EndInit(1)
  2869  	pkg.CB().NewVarStart(nil, "f").
  2870  		VarVal("e").MemberVal("x").EndInit(1)
  2871  	pkg.CB().NewVarStart(nil, "g").
  2872  		VarVal("c").UnaryOp(token.AND).EndInit(1)
  2873  	pkg.CB().NewVarStart(nil, "h").
  2874  		VarVal("g").MemberVal("y").EndInit(1)
  2875  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2876  		VarVal("c").MemberRef("x").Val(1).Assign(1).
  2877  		VarVal("a").MemberRef("y").Val("1").Assign(1).
  2878  		End()
  2879  	domTest(t, pkg, `package main
  2880  
  2881  type foo struct {
  2882  	x int
  2883  	y string
  2884  }
  2885  
  2886  var a = struct {
  2887  	x int
  2888  	y string
  2889  }{123, "Hi"}
  2890  var b = a.y
  2891  var c = foo{123, "Hi"}
  2892  var d = c.x
  2893  var e = &a
  2894  var f = e.x
  2895  var g = &c
  2896  var h = g.y
  2897  
  2898  func main() {
  2899  	c.x = 1
  2900  	a.y = "1"
  2901  }
  2902  `)
  2903  }
  2904  
  2905  func TestSlice(t *testing.T) {
  2906  	pkg := newMainPackage()
  2907  
  2908  	tySlice := types.NewSlice(types.Typ[types.Int])
  2909  	tyArray := types.NewArray(types.Typ[types.Int], 10)
  2910  	tyPArray := types.NewPointer(tyArray)
  2911  	tyString := types.Typ[types.String]
  2912  	p := pkg.NewParam(token.NoPos, "p", tyPArray)
  2913  	x := pkg.NewParam(token.NoPos, "x", tySlice)
  2914  	y := pkg.NewParam(token.NoPos, "y", tyString)
  2915  	z := pkg.NewParam(token.NoPos, "z", tyArray)
  2916  	pkg.NewFunc(nil, "foo", gogen.NewTuple(p, x, y, z), nil, false).BodyStart(pkg).
  2917  		NewVarStart(tySlice, "a").Val(x).None().Val(2).Slice(false).EndInit(1).
  2918  		NewVarStart(tySlice, "b").Val(x).None().None().Slice(false).EndInit(1).
  2919  		NewVarStart(tySlice, "c").Val(x).Val(1).Val(3).Val(10).Slice(true).EndInit(1).
  2920  		NewVarStart(tyString, "d").Val(y).Val(1).Val(3).Slice(false).EndInit(1).
  2921  		NewVarStart(tySlice, "e").Val(p).None().Val(5).Slice(false).EndInit(1).
  2922  		NewVarStart(tySlice, "f").Val(z).None().Val(5).Slice(false).EndInit(1).
  2923  		End()
  2924  
  2925  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2926  	domTest(t, pkg, `package main
  2927  
  2928  func foo(p *[10]int, x []int, y string, z [10]int) {
  2929  	var a []int = x[:2]
  2930  	var b []int = x[:]
  2931  	var c []int = x[1:3:10]
  2932  	var d string = y[1:3]
  2933  	var e []int = p[:5]
  2934  	var f []int = z[:5]
  2935  }
  2936  func main() {
  2937  }
  2938  `)
  2939  }
  2940  
  2941  func TestIndex(t *testing.T) {
  2942  	pkg := newMainPackage()
  2943  
  2944  	x := pkg.NewParam(token.NoPos, "x", types.NewSlice(types.Typ[types.Int]))
  2945  	y := pkg.NewParam(token.NoPos, "y", types.NewMap(types.Typ[types.String], types.Typ[types.Int]))
  2946  	ret := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  2947  	pkg.NewFunc(nil, "foo", gogen.NewTuple(x, y), gogen.NewTuple(ret), false).BodyStart(pkg).
  2948  		DefineVarStart(0, "v", "ok").Val(y).Val("a").Index(1, true).EndInit(1).
  2949  		Val(x).Val(0).Index(1, false).Return(1).
  2950  		End()
  2951  
  2952  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2953  	domTest(t, pkg, `package main
  2954  
  2955  func foo(x []int, y map[string]int) int {
  2956  	v, ok := y["a"]
  2957  	return x[0]
  2958  }
  2959  func main() {
  2960  }
  2961  `)
  2962  }
  2963  
  2964  func TestIndexRef(t *testing.T) {
  2965  	pkg := newMainPackage()
  2966  
  2967  	tyArray := types.NewArray(types.Typ[types.Int], 10)
  2968  	x := pkg.NewParam(token.NoPos, "x", tyArray)
  2969  	y := pkg.NewParam(token.NoPos, "y", types.NewPointer(tyArray))
  2970  	z := pkg.NewParam(token.NoPos, "z", types.NewMap(types.Typ[types.String], types.Typ[types.Int]))
  2971  	pkg.NewFunc(nil, "foo", gogen.NewTuple(x, y, z), nil, false).BodyStart(pkg).
  2972  		Val(x).Val(0).IndexRef(1).Val(1).Assign(1).
  2973  		Val(y).Val(1).IndexRef(1).Val(2).Assign(1).
  2974  		Val(z).Val("a").IndexRef(1).Val(3).Assign(1).
  2975  		Val(y).ElemRef().Val(x).Assign(1).
  2976  		VarRef(x).Val(y).Elem().Assign(1).
  2977  		End()
  2978  
  2979  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
  2980  	domTest(t, pkg, `package main
  2981  
  2982  func foo(x [10]int, y *[10]int, z map[string]int) {
  2983  	x[0] = 1
  2984  	y[1] = 2
  2985  	z["a"] = 3
  2986  	*y = x
  2987  	x = *y
  2988  }
  2989  func main() {
  2990  }
  2991  `)
  2992  }
  2993  
  2994  func TestStar(t *testing.T) {
  2995  	pkg := newMainPackage()
  2996  	tyInt := types.Typ[types.Uint32]
  2997  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  2998  		DefineVarStart(0, "a").Typ(tyInt).Star().Val(nil).Call(1).EndInit(1).
  2999  		NewVarStart(tyInt, "b").VarVal("a").Star().EndInit(1).
  3000  		End()
  3001  	domTest(t, pkg, `package main
  3002  
  3003  func main() {
  3004  	a := (*uint32)(nil)
  3005  	var b uint32 = *a
  3006  }
  3007  `)
  3008  }
  3009  
  3010  func TestAssignOp(t *testing.T) {
  3011  	pkg := newMainPackage()
  3012  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3013  		NewVar(types.Typ[types.String], "a", "b").
  3014  		VarRef(ctxRef(pkg, "a")).VarVal("b").AssignOp(token.ADD_ASSIGN).
  3015  		End()
  3016  	domTest(t, pkg, `package main
  3017  
  3018  func main() {
  3019  	var a, b string
  3020  	a += b
  3021  }
  3022  `)
  3023  }
  3024  
  3025  func TestAssign(t *testing.T) {
  3026  	var a, b, c, d, e, f, g *goxVar
  3027  	pkg := newMainPackage()
  3028  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3029  		NewAutoVar(token.NoPos, "a", &a).NewAutoVar(token.NoPos, "b", &b).
  3030  		NewAutoVar(token.NoPos, "c", &c).NewAutoVar(token.NoPos, "d", &d).
  3031  		NewAutoVar(token.NoPos, "e", &e).NewAutoVar(token.NoPos, "f", &f).
  3032  		NewAutoVar(token.NoPos, "g", &g).
  3033  		VarRef(a).VarRef(b).VarRef(d).VarRef(e).VarRef(f).VarRef(g).
  3034  		Val("Hi").Val(3).Val(true).Val('!').Val(1.2).Val(&ast.BasicLit{Kind: token.FLOAT, Value: "12.3"}).
  3035  		Assign(6).EndStmt().
  3036  		VarRef(c).Val(b).Assign(1).EndStmt().
  3037  		End()
  3038  	domTest(t, pkg, `package main
  3039  
  3040  func main() {
  3041  	var a string
  3042  	var b int
  3043  	var c int
  3044  	var d bool
  3045  	var e rune
  3046  	var f float64
  3047  	var g float64
  3048  	a, b, d, e, f, g = "Hi", 3, true, '!', 1.2, 12.3
  3049  	c = b
  3050  }
  3051  `)
  3052  }
  3053  
  3054  func TestAssignFnCall(t *testing.T) {
  3055  	var n, err *goxVar
  3056  	pkg := newMainPackage()
  3057  	fmt := pkg.Import("fmt")
  3058  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3059  		NewAutoVar(token.NoPos, "n", &n).NewAutoVar(token.NoPos, "err", &err).
  3060  		VarRef(n).VarRef(err).
  3061  		Val(fmt.Ref("Println")).Val("Hello").Call(1).
  3062  		Assign(2, 1).EndStmt().
  3063  		End()
  3064  	domTest(t, pkg, `package main
  3065  
  3066  import "fmt"
  3067  
  3068  func main() {
  3069  	var n int
  3070  	var err error
  3071  	n, err = fmt.Println("Hello")
  3072  }
  3073  `)
  3074  }
  3075  
  3076  func TestAssignUnderscore(t *testing.T) {
  3077  	var err *goxVar
  3078  	pkg := newMainPackage()
  3079  	fmt := pkg.Import("fmt")
  3080  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3081  		NewAutoVar(token.NoPos, "err", &err).
  3082  		VarRef(nil).VarRef(err).
  3083  		Val(fmt.Ref("Println")).Val("Hello").Call(1).
  3084  		Assign(2, 1).EndStmt().
  3085  		End()
  3086  	domTest(t, pkg, `package main
  3087  
  3088  import "fmt"
  3089  
  3090  func main() {
  3091  	var err error
  3092  	_, err = fmt.Println("Hello")
  3093  }
  3094  `)
  3095  }
  3096  
  3097  func TestOperator(t *testing.T) {
  3098  	var a, b, c, d *goxVar
  3099  	pkg := newMainPackage()
  3100  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3101  		NewAutoVar(token.NoPos, "a", &a).NewAutoVar(token.NoPos, "b", &b).
  3102  		NewAutoVar(token.NoPos, "c", &c).NewAutoVar(token.NoPos, "d", &d).
  3103  		VarRef(a).Val("Hi").Assign(1).EndStmt().
  3104  		VarRef(b).Val(a).Val("!").BinaryOp(token.ADD).Assign(1).EndStmt().
  3105  		VarRef(c).Val(&ast.BasicLit{Kind: token.INT, Value: "13"}).Assign(1).EndStmt().
  3106  		VarRef(d).Val(c).UnaryOp(token.SUB).Assign(1).EndStmt().
  3107  		End()
  3108  	domTest(t, pkg, `package main
  3109  
  3110  func main() {
  3111  	var a string
  3112  	var b string
  3113  	var c int
  3114  	var d int
  3115  	a = "Hi"
  3116  	b = a + "!"
  3117  	c = 13
  3118  	d = -c
  3119  }
  3120  `)
  3121  }
  3122  
  3123  func TestOperatorComplex(t *testing.T) {
  3124  	var a *goxVar
  3125  	pkg := newMainPackage()
  3126  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3127  		NewAutoVar(token.NoPos, "a", &a).
  3128  		VarRef(a).Val(123.1).Val(&ast.BasicLit{Kind: token.IMAG, Value: "3i"}).BinaryOp(token.SUB).Assign(1).EndStmt().
  3129  		End()
  3130  	domTest(t, pkg, `package main
  3131  
  3132  func main() {
  3133  	var a complex128
  3134  	a = 123.1 - 3i
  3135  }
  3136  `)
  3137  }
  3138  
  3139  func TestBinaryOpUntyped(t *testing.T) {
  3140  	var a *goxVar
  3141  	pkg := newMainPackage()
  3142  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3143  		NewAutoVar(token.NoPos, "a", &a).
  3144  		VarRef(a).Val("Hi").Val("!").BinaryOp(token.ADD).Assign(1).EndStmt().
  3145  		End()
  3146  	domTest(t, pkg, `package main
  3147  
  3148  func main() {
  3149  	var a string
  3150  	a = "Hi" + "!"
  3151  }
  3152  `)
  3153  }
  3154  
  3155  func TestBinaryOpSHL(t *testing.T) {
  3156  	pkg := newMainPackage()
  3157  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3158  		NewVar(types.Typ[types.Int32], "a").
  3159  		NewVar(types.Typ[types.Int], "b").
  3160  		VarVal("b").Val(1).VarVal("a").BinaryOp(token.SHL).BinaryOp(token.AND).EndStmt().
  3161  		End()
  3162  	domTest(t, pkg, `package main
  3163  
  3164  func main() {
  3165  	var a int32
  3166  	var b int
  3167  	b & (1 << a)
  3168  }
  3169  `)
  3170  }
  3171  
  3172  func TestImplicitCast(t *testing.T) {
  3173  	pkg := newMainPackage(func(pkg *gogen.Package, V, T types.Type, pv *gogen.Element) bool {
  3174  		log.Println("ImplicitCast:", V, T)
  3175  		*pv = *pkg.CB().Typ(T).Val(pv).Call(1).InternalStack().Pop()
  3176  		return true
  3177  	})
  3178  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3179  		NewVar(types.Typ[types.Int32], "a").
  3180  		NewVar(types.Typ[types.Int64], "b").
  3181  		VarRef(ctxRef(pkg, "b")).VarVal("a").AssignOp(token.ADD_ASSIGN).
  3182  		End()
  3183  	domTest(t, pkg, `package main
  3184  
  3185  func main() {
  3186  	var a int32
  3187  	var b int64
  3188  	b += int64(a)
  3189  }
  3190  `)
  3191  }
  3192  
  3193  func TestBinaryOpCmpNil(t *testing.T) {
  3194  	pkg := newMainPackage()
  3195  	typ := types.NewSlice(gogen.TyEmptyInterface)
  3196  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3197  		NewVar(typ, "a").
  3198  		NewVarStart(types.Typ[types.Bool], "b").
  3199  		VarVal("a").Val(nil).BinaryOp(token.NEQ).EndInit(1).
  3200  		NewVarStart(types.Typ[types.Bool], "c").
  3201  		Val(nil).VarVal("a").BinaryOp(token.EQL).EndInit(1).
  3202  		End()
  3203  	domTest(t, pkg, `package main
  3204  
  3205  func main() {
  3206  	var a []interface{}
  3207  	var b bool = a != nil
  3208  	var c bool = nil == a
  3209  }
  3210  `)
  3211  }
  3212  
  3213  func TestClosure(t *testing.T) {
  3214  	pkg := newMainPackage()
  3215  	fmt := pkg.Import("fmt")
  3216  	paramV := pkg.NewParam(token.NoPos, "v", types.Typ[types.String]) // v string
  3217  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3218  		NewClosure(gogen.NewTuple(paramV), nil, false).BodyStart(pkg).
  3219  		/**/ Debug(func(cb *gogen.CodeBuilder) {
  3220  			if cb.Func().Ancestor().Name() != "main" {
  3221  				t.Fatal("closure.Ancestor != main")
  3222  			}
  3223  		}).
  3224  		/**/ Val(fmt.Ref("Println")).Val(paramV).Call(1).EndStmt().
  3225  		/**/ End().
  3226  		Val("Hello").Call(1).EndStmt(). // func(v string) { fmt.Println(v) } ("Hello")
  3227  		End()
  3228  	domTest(t, pkg, `package main
  3229  
  3230  import "fmt"
  3231  
  3232  func main() {
  3233  	func(v string) {
  3234  		fmt.Println(v)
  3235  	}("Hello")
  3236  }
  3237  `)
  3238  }
  3239  
  3240  func TestClosureAutoParamRet(t *testing.T) {
  3241  	pkg := newMainPackage()
  3242  	ret := pkg.NewAutoParam("ret")
  3243  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3244  		NewVarStart(types.NewSlice(types.Typ[types.Int]), "a").
  3245  		/**/ NewClosure(nil, gogen.NewTuple(ret), false).BodyStart(pkg).
  3246  		/******/ VarRef(ctxRef(pkg, "ret")).Val(pkg.Builtin().Ref("append")).Val(ctxRef(pkg, "ret")).Val(1).Call(2).Assign(1).
  3247  		/******/ Return(0).
  3248  		/**/ End().Call(0).EndInit(1).
  3249  		End()
  3250  	domTest(t, pkg, `package main
  3251  
  3252  func main() {
  3253  	var a []int = func() (ret []int) {
  3254  		ret = append(ret, 1)
  3255  		return
  3256  	}()
  3257  }
  3258  `)
  3259  }
  3260  
  3261  func TestReturnErr(t *testing.T) {
  3262  	pkg := newMainPackage()
  3263  	tyErr := types.Universe.Lookup("error").Type()
  3264  	format := pkg.NewParam(token.NoPos, "format", types.Typ[types.String])
  3265  	args := pkg.NewParam(token.NoPos, "args", types.NewSlice(gogen.TyEmptyInterface))
  3266  	n := pkg.NewParam(token.NoPos, "", types.Typ[types.Int])
  3267  	err := pkg.NewParam(token.NoPos, "", tyErr)
  3268  	pkg.NewFunc(nil, "foo", gogen.NewTuple(format, args), gogen.NewTuple(n, err), true).BodyStart(pkg).
  3269  		NewVar(tyErr, "_gop_err").
  3270  		Val(ctxRef(pkg, "_gop_err")).ReturnErr(false).
  3271  		End()
  3272  	domTest(t, pkg, `package main
  3273  
  3274  func foo(format string, args ...interface{}) (int, error) {
  3275  	var _gop_err error
  3276  	return 0, _gop_err
  3277  }
  3278  `)
  3279  }
  3280  
  3281  func TestCallInlineClosure(t *testing.T) {
  3282  	pkg := newMainPackage()
  3283  	fmt := pkg.Import("fmt")
  3284  	ret := pkg.NewAutoParam("ret")
  3285  	err := pkg.NewParam(token.NoPos, "", gogen.TyError)
  3286  	sig := gogen.NewSignature(nil, nil, types.NewTuple(ret), false)
  3287  	pkg.NewFunc(nil, "foo", nil, types.NewTuple(err), false).BodyStart(pkg).
  3288  		DefineVarStart(0, "n").
  3289  		CallInlineClosureStart(sig, 0, false).
  3290  		/**/ DefineVarStart(0, "n", "err").Val(fmt.Ref("Println")).Val("Hi").Call(1).EndInit(1).
  3291  		/**/ If().Val(ctxRef(pkg, "err")).CompareNil(token.NEQ).Then().
  3292  		/******/ Val(ctxRef(pkg, "err")).ReturnErr(true).
  3293  		/******/ End().
  3294  		/**/ Val(ctxRef(pkg, "n")).Return(1).
  3295  		/**/ End().
  3296  		EndInit(1).
  3297  		End()
  3298  	domTest(t, pkg, `package main
  3299  
  3300  import "fmt"
  3301  
  3302  func foo() error {
  3303  	var _autoGo_1 int
  3304  	{
  3305  		n, err := fmt.Println("Hi")
  3306  		if err != nil {
  3307  			return err
  3308  		}
  3309  		_autoGo_1 = n
  3310  		goto _autoGo_2
  3311  	_autoGo_2:
  3312  	}
  3313  	n := _autoGo_1
  3314  }
  3315  `)
  3316  }
  3317  
  3318  func TestCallInlineClosureAssign(t *testing.T) {
  3319  	pkg := newMainPackage()
  3320  	fmt := pkg.Import("fmt")
  3321  	ret := pkg.NewAutoParam("ret")
  3322  	sig := types.NewSignatureType(nil, nil, nil, nil, gogen.NewTuple(ret), false)
  3323  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3324  		Val(fmt.Ref("Println")).
  3325  		CallInlineClosureStart(sig, 0, false).
  3326  		/**/ NewVar(types.Universe.Lookup("error").Type(), "err").
  3327  		/**/ VarRef(ret).VarRef(ctxRef(pkg, "err")).Val(fmt.Ref("Println")).Val("Hi").Call(1).Assign(2, 1).
  3328  		/**/ Return(0).
  3329  		/**/ End().
  3330  		Call(1).EndStmt().
  3331  		End()
  3332  	domTest(t, pkg, `package main
  3333  
  3334  import "fmt"
  3335  
  3336  func main() {
  3337  	var _autoGo_1 int
  3338  	{
  3339  		var err error
  3340  		_autoGo_1, err = fmt.Println("Hi")
  3341  		goto _autoGo_2
  3342  	_autoGo_2:
  3343  	}
  3344  	fmt.Println(_autoGo_1)
  3345  }
  3346  `)
  3347  }
  3348  
  3349  func TestCallInlineClosureEllipsis(t *testing.T) {
  3350  	pkg := newMainPackage()
  3351  	fmt := pkg.Import("fmt")
  3352  	x := pkg.NewParam(token.NoPos, "x", types.NewSlice(gogen.TyEmptyInterface))
  3353  	ret := pkg.NewAutoParam("ret")
  3354  	sig := types.NewSignatureType(nil, nil, nil, types.NewTuple(x), types.NewTuple(ret), true)
  3355  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3356  		Val(fmt.Ref("Println")).
  3357  		Val(1).SliceLit(types.NewSlice(gogen.TyEmptyInterface), 1).
  3358  		CallInlineClosureStart(sig, 1, true).
  3359  		/**/ DefineVarStart(0, "n", "err").Val(fmt.Ref("Println")).Val(x).Call(1, true).EndInit(1).
  3360  		/**/ Val(ctxRef(pkg, "n")).Return(1).
  3361  		/**/ End().
  3362  		Call(1).EndStmt().
  3363  		End()
  3364  	domTest(t, pkg, `package main
  3365  
  3366  import "fmt"
  3367  
  3368  func main() {
  3369  	var _autoGo_1 int
  3370  	{
  3371  		var _autoGo_2 []interface{} = []interface{}{1}
  3372  		n, err := fmt.Println(_autoGo_2...)
  3373  		_autoGo_1 = n
  3374  		goto _autoGo_3
  3375  	_autoGo_3:
  3376  	}
  3377  	fmt.Println(_autoGo_1)
  3378  }
  3379  `)
  3380  }
  3381  
  3382  // ----------------------------------------------------------------------------
  3383  
  3384  func TestExample(t *testing.T) {
  3385  	pkg := newMainPackage()
  3386  
  3387  	fmt := pkg.Import("fmt")
  3388  
  3389  	v := pkg.NewParam(token.NoPos, "v", types.Typ[types.String]) // v string
  3390  
  3391  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3392  		DefineVarStart(0, "a", "b").Val("Hi").Val(3).EndInit(2). // a, b := "Hi", 3
  3393  		NewVarStart(nil, "c").VarVal("b").EndInit(1).            // var c = b
  3394  		NewVar(gogen.TyEmptyInterface, "x", "y").                // var x, y interface{}
  3395  		Val(fmt.Ref("Println")).
  3396  		/**/ VarVal("a").VarVal("b").VarVal("c"). // fmt.Println(a, b, c)
  3397  		/**/ Call(3).EndStmt().
  3398  		NewClosure(gogen.NewTuple(v), nil, false).BodyStart(pkg).
  3399  		/**/ Val(fmt.Ref("Println")).Val(v).Call(1).EndStmt(). // fmt.Println(v)
  3400  		/**/ End().
  3401  		Val("Hello").Call(1).EndStmt(). // func(v string) { ... } ("Hello")
  3402  		End()
  3403  	domTest(t, pkg, `package main
  3404  
  3405  import "fmt"
  3406  
  3407  func main() {
  3408  	a, b := "Hi", 3
  3409  	var c = b
  3410  	var x, y interface{}
  3411  	fmt.Println(a, b, c)
  3412  	func(v string) {
  3413  		fmt.Println(v)
  3414  	}("Hello")
  3415  }
  3416  `)
  3417  }
  3418  
  3419  // ----------------------------------------------------------------------------
  3420  
  3421  func TestInterfaceMethodVarCall(t *testing.T) {
  3422  	pkg := newMainPackage()
  3423  	fmt := pkg.Import("fmt")
  3424  	tyInt := types.Typ[types.Int]
  3425  	tyString := types.Typ[types.String]
  3426  	methods := []*types.Func{
  3427  		types.NewFunc(token.NoPos, pkg.Types, "bar", types.NewSignatureType(
  3428  			nil, nil, nil, types.NewTuple(types.NewVar(token.NoPos, nil, "info", tyString)), nil, false)),
  3429  	}
  3430  	tyInterf := types.NewInterfaceType(methods, nil).Complete()
  3431  	foo := pkg.NewType("foo").InitType(pkg, tyInterf)
  3432  	_ = foo
  3433  	tt := pkg.NewType("t").InitType(pkg, tyInt)
  3434  	recv := pkg.NewParam(token.NoPos, "tt", tt)
  3435  	pkg.NewFunc(recv, "bar", types.NewTuple(types.NewVar(token.NoPos, nil, "info", tyString)), nil, false).BodyStart(pkg).
  3436  		Val(fmt.Ref("Println")).Val(recv).Val(pkg.NewParam(token.NoPos, "info", tyString)).Call(2).EndStmt(). // fmt.Println(v)
  3437  		End()
  3438  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3439  		DefineVarStart(0, "v").Val(ctxRef(pkg, "foo")).MemberVal("bar").EndInit(1).
  3440  		NewVarStart(tt, "tt").Val(123).EndInit(1).
  3441  		VarVal("v").Val(ctxRef(pkg, "tt")).Val("hello").Call(2, false).
  3442  		EndStmt().End()
  3443  	domTest(t, pkg, `package main
  3444  
  3445  import "fmt"
  3446  
  3447  type foo interface {
  3448  	bar(info string)
  3449  }
  3450  type t int
  3451  
  3452  func (tt t) bar(info string) {
  3453  	fmt.Println(tt, info)
  3454  }
  3455  func main() {
  3456  	v := (foo).bar
  3457  	var tt t = 123
  3458  	v(tt, "hello")
  3459  }
  3460  `)
  3461  }
  3462  
  3463  func TestTypeNamed(t *testing.T) {
  3464  	pkg := newMainPackage()
  3465  	fields := []*types.Var{
  3466  		types.NewField(token.NoPos, pkg.Types, "x", types.Typ[types.Int], false),
  3467  		types.NewField(token.NoPos, pkg.Types, "y", types.Typ[types.String], false),
  3468  	}
  3469  	typ := types.NewStruct(fields, nil)
  3470  	t1 := pkg.NewType("T").InitType(pkg, typ)
  3471  	recv := pkg.NewParam(token.NoPos, "a", t1)
  3472  	pkg.NewFunc(recv, "Bar", nil, nil, false).BodyStart(pkg).End()
  3473  	t2 := pkg.NewType("T1").InitType(pkg, types.NewNamed(types.NewTypeName(token.NoPos, nil, "T", t1), t1.Underlying(), nil))
  3474  	recv2 := pkg.NewParam(token.NoPos, "a", t2)
  3475  	pkg.NewFunc(recv2, "Foo", nil, nil, false).BodyStart(pkg).End()
  3476  	pkg.CB().NewType("X").InitType(pkg, gogen.TyByte)
  3477  	domTest(t, pkg, `package main
  3478  
  3479  type T struct {
  3480  	x int
  3481  	y string
  3482  }
  3483  
  3484  func (a T) Bar() {
  3485  }
  3486  
  3487  type T1 T
  3488  
  3489  func (a T1) Foo() {
  3490  }
  3491  
  3492  type X byte
  3493  `)
  3494  }
  3495  
  3496  func TestMethodAccess(t *testing.T) {
  3497  	const src = `package foo
  3498  
  3499  type M struct {
  3500  }
  3501  
  3502  func (m *M) setValue() {
  3503  }
  3504  
  3505  func (m *M) SetValue() {
  3506  }
  3507  `
  3508  	gt := newGoxTest()
  3509  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
  3510  	if err != nil {
  3511  		t.Fatal(err)
  3512  	}
  3513  	pkg := gt.NewPackage("", "main")
  3514  	pkgRef := pkg.Import("foo")
  3515  	tyM := pkgRef.Ref("M").Type()
  3516  
  3517  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3518  		NewVar(tyM, "m").VarVal("m").Debug(
  3519  		func(cb *gogen.CodeBuilder) {
  3520  			cb.Member("setValue", gogen.MemberFlagMethodAlias)
  3521  		}).Call(0).EndStmt().
  3522  		End()
  3523  	domTest(t, pkg, `package main
  3524  
  3525  import "foo"
  3526  
  3527  func main() {
  3528  	var m foo.M
  3529  	m.SetValue()
  3530  }
  3531  `)
  3532  }
  3533  
  3534  func TestPackageName(t *testing.T) {
  3535  	const src = `package foo2
  3536  
  3537  type M struct {
  3538  }
  3539  
  3540  func (m *M) SetValue() {
  3541  }
  3542  `
  3543  	gt := newGoxTest()
  3544  	_, err := gt.LoadGoPackage("foo", "foo.go", src)
  3545  	if err != nil {
  3546  		t.Fatal(err)
  3547  	}
  3548  	pkg := gt.NewPackage("", "main")
  3549  	pkgRef := pkg.Import("foo")
  3550  	tyM := pkgRef.Ref("M").Type()
  3551  
  3552  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3553  		NewVar(tyM, "m").VarVal("m").Debug(
  3554  		func(cb *gogen.CodeBuilder) {
  3555  			cb.Member("SetValue", gogen.MemberFlagMethodAlias)
  3556  		}).Call(0).EndStmt().
  3557  		End()
  3558  	domTest(t, pkg, `package main
  3559  
  3560  import "foo"
  3561  
  3562  func main() {
  3563  	var m foo2.M
  3564  	m.SetValue()
  3565  }
  3566  `)
  3567  }
  3568  
  3569  func TestMethodAlias(t *testing.T) {
  3570  	pkg := newMainPackage()
  3571  
  3572  	typ := types.NewStruct(nil, nil)
  3573  	tyM := pkg.NewType("M").InitType(pkg, typ)
  3574  	recv := pkg.NewParam(token.NoPos, "p", types.NewPointer(tyM))
  3575  	pkg.NewFunc(recv, "SetValue", nil, nil, false).BodyStart(pkg).End()
  3576  	pkg.NewFunc(recv, "setValue", nil, nil, false).BodyStart(pkg).End()
  3577  	pkg.NewFunc(recv, "Value", nil, nil, false).BodyStart(pkg).End()
  3578  
  3579  	pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
  3580  		NewVar(tyM, "m").
  3581  		VarVal("m").Debug(
  3582  		func(cb *gogen.CodeBuilder) {
  3583  			cb.Member("setValue", gogen.MemberFlagMethodAlias)
  3584  		}).Call(0).EndStmt().
  3585  		VarVal("m").Debug(
  3586  		func(cb *gogen.CodeBuilder) {
  3587  			cb.Member("SetValue", gogen.MemberFlagMethodAlias)
  3588  		}).Call(0).EndStmt().
  3589  		VarVal("m").Debug(
  3590  		func(cb *gogen.CodeBuilder) {
  3591  			cb.Member("value", gogen.MemberFlagMethodAlias)
  3592  		}).Call(0).EndStmt().
  3593  		End()
  3594  	domTest(t, pkg, `package main
  3595  
  3596  type M struct {
  3597  }
  3598  
  3599  func (p *M) SetValue() {
  3600  }
  3601  func (p *M) setValue() {
  3602  }
  3603  func (p *M) Value() {
  3604  }
  3605  func main() {
  3606  	var m M
  3607  	m.setValue()
  3608  	m.SetValue()
  3609  	m.Value()
  3610  }
  3611  `)
  3612  }
  3613  
  3614  // ----------------------------------------------------------------------------