Repository: goplus/gop
Pull request #1509 (2023-11-01 11:39:57)

refactor: xxxError use Pos instead of Position


Patch:
diff --git a/cl/compile.go b/cl/compile.go
index f1ff311d..1fd3d019 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -251,30 +251,17 @@ func (p *nodeInterp) Position(start token.Pos) token.Position {
 
 func (p *nodeInterp) Caller(node ast.Node) string {
 	if expr, ok := node.(*ast.CallExpr); ok {
-		node = expr.Fun
-		start := node.Pos()
-		pos := p.fset.Position(start)
-		f := p.files[pos.Filename]
-		n := int(node.End() - start)
-		return string(f.Code[pos.Offset : pos.Offset+n])
+		return p.LoadExpr(expr.Fun)
 	}
 	return "the function call"
 }
 
-func (p *nodeInterp) LoadExpr(node ast.Node) (src string, pos token.Position) {
+func (p *nodeInterp) LoadExpr(node ast.Node) string {
 	start := node.Pos()
-	pos = p.fset.Position(start)
+	pos := p.fset.Position(start)
 	f := p.files[pos.Filename]
-	if f == nil { // not found
-		return
-	}
 	n := int(node.End() - start)
-	pos.Filename = relFile(p.workingDir, pos.Filename)
-	if pos.Offset+n < 0 {
-		log.Println("LoadExpr:", node, pos.Filename, pos.Line, pos.Offset, node.Pos(), node.End(), n)
-	}
-	src = string(f.Code[pos.Offset : pos.Offset+n])
-	return
+	return string(f.Code[pos.Offset : pos.Offset+n])
 }
 
 type loader interface {
@@ -374,6 +361,7 @@ func doInitMethods(ld *typeLoader) {
 type pkgCtx struct {
 	*nodeInterp
 	*gmxSettings
+	fset  *token.FileSet
 	cpkgs *cpackages.Importer
 	syms  map[string]loader
 	inits []func()
@@ -394,7 +382,6 @@ type blockCtx struct {
 	*pkgCtx
 	pkg          *gox.Package
 	cb           *gox.CodeBuilder
-	fset         *token.FileSet
 	imports      map[string]pkgImp
 	lookups      []*gox.PkgRef
 	clookups     []*cpackages.PkgRef
@@ -422,27 +409,22 @@ func (bc *blockCtx) findImport(name string) (pi pkgImp, ok bool) {
 	return
 }
 
-func newCodeErrorf(pos *token.Position, format string, args ...interface{}) *gox.CodeError {
-	return &gox.CodeError{Pos: pos, Msg: fmt.Sprintf(format, args...)}
-}
-
-func (p *pkgCtx) newCodeError(start token.Pos, msg string) error {
-	pos := p.Position(start)
-	return &gox.CodeError{Pos: &pos, Msg: msg}
+func (p *pkgCtx) newCodeError(pos token.Pos, msg string) error {
+	return &gox.CodeError{Fset: p.nodeInterp, Pos: pos, Msg: msg}
 }
 
-func (p *pkgCtx) newCodeErrorf(start token.Pos, format string, args ...interface{}) error {
-	pos := p.Position(start)
-	return newCodeErrorf(&pos, format, args...)
+func (p *pkgCtx) newCodeErrorf(pos token.Pos, format string, args ...interface{}) error {
+	return &gox.CodeError{Fset: p.nodeInterp, Pos: pos, Msg: fmt.Sprintf(format, args...)}
 }
 
-func (p *pkgCtx) handleCodeErrorf(pos *token.Position, format string, args ...interface{}) {
-	p.handleErr(newCodeErrorf(pos, format, args...))
+/*
+func (p *pkgCtx) handleError(pos token.Pos, msg string) {
+	p.handleErr(p.newCodeError(pos, msg))
 }
+*/
 
-func (p *pkgCtx) handleErrorf(start token.Pos, format string, args ...interface{}) {
-	pos := p.Position(start)
-	p.handleErr(newCodeErrorf(&pos, format, args...))
+func (p *pkgCtx) handleErrorf(pos token.Pos, format string, args ...interface{}) {
+	p.handleErr(p.newCodeErrorf(pos, format, args...))
 }
 
 func (p *pkgCtx) handleErr(err error) {
@@ -526,6 +508,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		fset: fset, files: files, workingDir: workingDir,
 	}
 	ctx := &pkgCtx{
+		fset: fset,
 		syms: make(map[string]loader), nodeInterp: interp, generics: make(map[string]bool),
 	}
 	confGox := &gox.Config{
@@ -539,6 +522,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		DefaultGoFile:   defaultGoFile,
 		NoSkipConstant:  conf.NoSkipConstant,
 		PkgPathIox:      ioxPkgPath,
+		DbgPositioner:   interp,
 	}
 	if conf.Recorder != nil {
 		confGox.Recorder = &goxRecorder{rec: conf.Recorder}
@@ -573,7 +557,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		fileLine := !conf.NoFileLine
 		fileScope := types.NewScope(p.Types.Scope(), f.Pos(), f.End(), fpath)
 		ctx := &blockCtx{
-			pkg: p, pkgCtx: ctx, cb: p.CB(), fset: p.Fset, targetDir: targetDir, fileScope: fileScope,
+			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir, fileScope: fileScope,
 			fileLine: fileLine, relativePath: conf.RelativePath, isClass: f.IsClass, rec: conf.Recorder,
 			c2goBase: c2goBase(conf.C2goBase), imports: make(map[string]pkgImp), isGopFile: true,
 		}
@@ -588,7 +572,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		f := fromgo.ASTFile(gof, 0)
 		gofiles = append(gofiles, f)
 		ctx := &blockCtx{
-			pkg: p, pkgCtx: ctx, cb: p.CB(), fset: p.Fset, targetDir: targetDir,
+			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir,
 			imports: make(map[string]pkgImp),
 		}
 		preloadFile(p, ctx, fpath, f, false, false)
@@ -903,11 +887,12 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFil
 			case token.TYPE:
 				for _, spec := range d.Specs {
 					t := spec.(*ast.TypeSpec)
-					name := t.Name.Name
+					tName := t.Name
+					name := tName.Name
 					if debugLoad {
 						log.Println("==> Preload type", name)
 					}
-					pos := t.Name.Pos()
+					pos := tName.Pos()
 					ld := getTypeLoader(parent, syms, pos, name)
 					defs := ctx.pkg.NewTypeDefs()
 					if gopFile {
@@ -918,13 +903,13 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFil
 								if debugLoad {
 									log.Println("==> Load > AliasType", name)
 								}
-								defs.AliasType(name, toType(ctx, t.Type), t.Pos())
+								defs.AliasType(name, toType(ctx, t.Type), tName)
 								return
 							}
 							if debugLoad {
 								log.Println("==> Load > NewType", name)
 							}
-							decl := defs.NewType(name, pos)
+							decl := defs.NewType(name, tName)
 							if t.Doc != nil {
 								defs.SetComments(t.Doc)
 							} else if d.Doc != nil {
@@ -936,7 +921,7 @@ func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFil
 								}
 								decl.InitType(ctx.pkg, toType(ctx, t.Type))
 								if rec := ctx.recorder(); rec != nil {
-									rec.Def(t.Name, decl.Type().Obj())
+									rec.Def(tName, decl.Type().Obj())
 								}
 							}
 						}
diff --git a/cl/expr.go b/cl/expr.go
index cd6328ef..f3abf968 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -559,8 +559,8 @@ func compileCallArgs(fn *fnType, fnt types.Type, ctx *blockCtx, v *ast.CallExpr,
 			if e, ok := r.(error); ok {
 				err = e
 			} else {
-				src, pos := ctx.LoadExpr(v)
-				err = newCodeErrorf(&pos, "compile func %v error: %v", src, r)
+				src := ctx.LoadExpr(v)
+				err = ctx.newCodeErrorf(v.Pos(), "compile func %v error: %v", src, r)
 			}
 			ctx.cb.InternalStack().SetLen(n)
 		}
@@ -630,7 +630,7 @@ retry:
 		typ = t.Underlying()
 		goto retry
 	}
-	src, _ := ctx.LoadExpr(toNode)
+	src := ctx.LoadExpr(toNode)
 	err := ctx.newCodeErrorf(lambda.Pos(), "cannot use lambda literal as type %v in %v to %v", ftyp, flag, src)
 	panic(err)
 }
@@ -789,8 +789,8 @@ func compileStructLitInKeyVal(ctx *blockCtx, elts []ast.Expr, t *types.Struct, t
 		if idx >= 0 {
 			ctx.cb.Val(idx)
 		} else {
-			src, pos := ctx.LoadExpr(name)
-			err := newCodeErrorf(&pos, "%s undefined (type %v has no field or method %s)", src, typ, name.Name)
+			src := ctx.LoadExpr(name)
+			err := ctx.newCodeErrorf(name.Pos(), "%s undefined (type %v has no field or method %s)", src, typ, name.Name)
 			panic(err)
 		}
 		switch expr := kv.Value.(type) {
diff --git a/cl/func_type_and_var.go b/cl/func_type_and_var.go
index ef4d1bba..23ee6fdc 100644
--- a/cl/func_type_and_var.go
+++ b/cl/func_type_and_var.go
@@ -62,8 +62,8 @@ func getRecvTypeName(ctx *pkgCtx, recv *ast.FieldList, handleErr bool) (string,
 		return t.Name, true
 	}
 	if handleErr {
-		src, pos := ctx.LoadExpr(typ)
-		ctx.handleCodeErrorf(&pos, "invalid receiver type %v (%v is not a defined type)", src, src)
+		src := ctx.LoadExpr(typ)
+		ctx.handleErrorf(typ.Pos(), "invalid receiver type %v (%v is not a defined type)", src, src)
 	}
 	return "", false
 }
@@ -399,8 +399,8 @@ func toInt64(ctx *blockCtx, e ast.Expr, emsg string) int64 {
 			return v
 		}
 	}
-	src, pos := ctx.LoadExpr(e)
-	panic(newCodeErrorf(&pos, emsg, src))
+	src := ctx.LoadExpr(e)
+	panic(ctx.newCodeErrorf(e.Pos(), emsg, src))
 }
 
 func toInterfaceType(ctx *blockCtx, v *ast.InterfaceType) types.Type {
diff --git a/cl/outline/cl/_walk/walk.go b/cl/outline/cl/_walk/walk.go
deleted file mode 100644
index 3357dd90..00000000
--- a/cl/outline/cl/_walk/walk.go
+++ /dev/null
@@ -1,193 +0,0 @@
-package walk
-
-import (
-	"go/types"
-	"reflect"
-	"strconv"
-
-	"github.com/goplus/gop/ast"
-)
-
-// -----------------------------------------------------------------------------
-
-type Visitor interface {
-}
-
-// -----------------------------------------------------------------------------
-
-type Context struct {
-	pkg *types.Package
-	ctx *types.Scope
-	vi  Visitor
-}
-
-func New(pkg *types.Package, visitor Visitor) *Context {
-	return &Context{pkg: pkg, vi: visitor}
-}
-
-func (p *Context) File(f *ast.File) error {
-	p.ctx = p.pkg.Scope()
-	for _, decl := range f.Decls {
-		if e := p.decl(f, decl); e != nil {
-			return e
-		}
-	}
-	return nil
-}
-
-func (p *Context) decl(f *ast.File, decl ast.Decl) error {
-	switch d := decl.(type) {
-	case *ast.FuncDecl:
-		return p.funcDecl(f, d)
-	case *ast.GenDecl:
-		return p.genDecl(d)
-	default:
-		panic("Unknown ast.decl: " + reflect.TypeOf(decl).String())
-	}
-}
-
-func (p *Context) genDecl(f *ast.GenDecl) error {
-	return nil
-}
-
-func (p *Context) funcDecl(f *ast.File, d *ast.FuncDecl) error {
-	body := p.block(d.Body.List)
-	if f.ShadowEntry == d {
-		return body
-	}
-	flds := Block{
-		"NAME": d.Name.Name,
-	}
-	p.funcType(flds, d.Type)
-	return Block{
-		"type":   "goplus_func",
-		"fields": flds,
-		"inputs": Block{
-			"BODY": Block{
-				"block": body,
-			},
-		},
-	}
-}
-
-func (p *Context) funcType(ret Block, fnt *ast.FuncType) {
-	p.fieldList(ret, "ARG", fnt.Params)
-	p.fieldList(ret, "RET", fnt.Results)
-	// _, variadic := params[n-1].Type.(*ast.Ellipsis)
-}
-
-func (p *Context) fieldList(ret Block, namePrefix string, flds *ast.FieldList) {
-	if flds == nil {
-		return
-	}
-	i := 0
-	for _, param := range flds.List {
-		last := len(param.Names) - 1
-		for j, name := range param.Names {
-			idx := strconv.Itoa(i)
-			i++
-			arg := namePrefix + idx
-			argt := arg + "_TYPE"
-			typ := ""
-			if j == last {
-				typ = p.toType(param.Type)
-			}
-			ret[arg] = name.Name
-			ret[argt] = typ
-		}
-	}
-}
-
-// -----------------------------------------------------------------------------
-
-func (p *Context) block(stmts []ast.Stmt) (ret Block) {
-	var prev Block
-	for _, stmt := range stmts {
-		b := p.stmt(stmt)
-		if prev != nil {
-			prev.setNext(b)
-		} else {
-			ret = b
-		}
-		prev = b
-	}
-	return
-}
-
-func (p *Context) stmt(stmt ast.Stmt) (ret Block) {
-	switch v := stmt.(type) {
-	case *ast.IfStmt:
-		return p.ifStmt(v)
-	case *ast.BlockStmt:
-		return p.block(v.List)
-	}
-	return Block{
-		"type": "goplus_stmt",
-		"inputs": Block{
-			"CODE": p.toCode(stmt),
-		},
-	}
-}
-
-func (p *Context) ifStmt(v *ast.IfStmt) (ret Block) {
-	cond := p.expr(v.Cond)
-	body := p.block(v.Body.List)
-	inputs := Block{
-		"COND": cond,
-		"BODY": body,
-	}
-	if v.Init != nil {
-		inputs["INIT"] = p.stmt(v.Init)
-	}
-	if v.Else != nil {
-		inputs["ELSE"] = p.stmt(v.Else)
-	}
-	return Block{
-		"type":   "goplus_if",
-		"inputs": inputs,
-	}
-}
-
-// -----------------------------------------------------------------------------
-
-func (p *Context) expr(expr ast.Expr) (ret Block) {
-	switch v := expr.(type) {
-	case *ast.BinaryExpr:
-		return p.binaryExpr(v)
-	case *ast.UnaryExpr:
-		return p.unaryExpr(v)
-	}
-	return Block{
-		"type": "goplus_expr",
-		"inputs": Block{
-			"CODE": p.toCode(expr),
-		},
-	}
-}
-
-func (p *Context) unaryExpr(v *ast.UnaryExpr) (ret Block) {
-	return
-}
-
-func (p *Context) binaryExpr(v *ast.BinaryExpr) (ret Block) {
-	return
-}
-
-// -----------------------------------------------------------------------------
-
-func (p *Context) toType(t ast.Expr) string {
-	return p.str(t)
-}
-
-func (p *Context) toCode(v ast.Node) (ret Block) {
-	return Block{
-		"block": Block{
-			"type": "text",
-			"fields": Block{
-				"TEXT": p.str(v),
-			},
-		},
-	}
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/builtin.go b/cl/outline/cl/builtin.go
deleted file mode 100644
index a97ecf34..00000000
--- a/cl/outline/cl/builtin.go
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"go/token"
-	"go/types"
-
-	"github.com/goplus/gox"
-)
-
-// -----------------------------------------------------------------------------
-
-func initMathBig(pkg *gox.Package, conf *gox.Config, big *gox.PkgRef) {
-	big.EnsureImported()
-	conf.UntypedBigInt = big.Ref("UntypedBigint").Type().(*types.Named)
-	conf.UntypedBigRat = big.Ref("UntypedBigrat").Type().(*types.Named)
-	conf.UntypedBigFloat = big.Ref("UntypedBigfloat").Type().(*types.Named)
-}
-
-func initBuiltinFns(builtin *types.Package, scope *types.Scope, pkg *gox.PkgRef, fns []string) {
-	for _, fn := range fns {
-		fnTitle := string(fn[0]-'a'+'A') + fn[1:]
-		scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, fn, pkg.Ref(fnTitle)))
-	}
-}
-
-func initBuiltin(pkg *gox.Package, builtin *types.Package, os, fmt, ng, iox, buil *gox.PkgRef) {
-	scope := builtin.Scope()
-	typs := []string{"bigint", "bigrat", "bigfloat"}
-	for _, typ := range typs {
-		name := string(typ[0]-('a'-'A')) + typ[1:]
-		scope.Insert(types.NewTypeName(token.NoPos, builtin, typ, ng.Ref(name).Type()))
-	}
-	initBuiltinFns(builtin, scope, fmt, []string{
-		"print", "println", "printf", "errorf",
-		"fprint", "fprintln", "fprintf",
-		"sprint", "sprintln", "sprintf",
-	})
-	initBuiltinFns(builtin, scope, os, []string{
-		"open", "create",
-	})
-	initBuiltinFns(builtin, scope, iox, []string{
-		"lines",
-	})
-	scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "blines", iox.Ref("BLines")))
-	scope.Insert(gox.NewOverloadFunc(token.NoPos, builtin, "newRange", buil.Ref("NewRange__0")))
-	scope.Insert(types.NewTypeName(token.NoPos, builtin, "uint128", ng.Ref("Uint128").Type()))
-	scope.Insert(types.NewTypeName(token.NoPos, builtin, "int128", ng.Ref("Int128").Type()))
-	scope.Insert(types.NewTypeName(token.NoPos, builtin, "any", gox.TyEmptyInterface))
-}
-
-func newBuiltinDefault(pkg *gox.Package, conf *gox.Config) *types.Package {
-	builtin := types.NewPackage("", "")
-	fmt := pkg.Import("fmt")
-	os := pkg.Import("os")
-	buil := pkg.Import("github.com/goplus/gop/builtin")
-	ng := pkg.Import("github.com/goplus/gop/builtin/ng")
-	iox := pkg.Import("github.com/goplus/gop/builtin/iox")
-	pkg.Import("strconv")
-	pkg.Import("strings")
-	initMathBig(pkg, conf, ng)
-	initBuiltin(pkg, builtin, os, fmt, ng, iox, buil)
-	gox.InitBuiltin(pkg, builtin, conf)
-	return builtin
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/c.go b/cl/outline/cl/c.go
deleted file mode 100644
index 39b4c989..00000000
--- a/cl/outline/cl/c.go
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"strings"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gox"
-)
-
-const (
-	c2goInvalid = iota
-	c2goStandard
-	c2goUserDef
-)
-
-func checkC2go(pkgPath string) (realPkgPath string, kind int) {
-	if strings.HasPrefix(pkgPath, "C") {
-		if len(pkgPath) == 1 {
-			return "libc", c2goStandard
-		}
-		if pkgPath[1] == '/' {
-			realPkgPath = pkgPath[2:]
-			if strings.IndexByte(realPkgPath, '/') < 0 {
-				kind = c2goStandard
-			} else {
-				kind = c2goUserDef
-			}
-		}
-	}
-	return
-}
-
-func c2goBase(base string) string {
-	if base == "" {
-		base = "github.com/goplus/"
-	} else if !strings.HasSuffix(base, "/") {
-		base += "/"
-	}
-	return base
-}
-
-// -----------------------------------------------------------------------------
-
-func loadC2goPkg(ctx *blockCtx, realPath string, src *ast.BasicLit) *gox.PkgRef {
-	cpkg, err := ctx.cpkgs.Import(realPath)
-	if err != nil {
-		pos := ctx.Position(src.Pos())
-		ctx.handleCodeErrorf(&pos,
-			"%v not found or not a valid C package (c2go.a.pub file not found).\n", realPath)
-		return nil
-	}
-	ctx.clookups = append(ctx.clookups, cpkg)
-	return cpkg.Pkg()
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/classfile.go b/cl/outline/cl/classfile.go
deleted file mode 100644
index 5103312a..00000000
--- a/cl/outline/cl/classfile.go
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	goast "go/ast"
-	"go/constant"
-	"go/types"
-	"path/filepath"
-	"strings"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-)
-
-// -----------------------------------------------------------------------------
-
-type gmxSettings struct {
-	gameClass  string
-	game       gox.Ref
-	sprite     map[string]gox.Ref
-	scheds     []string
-	schedStmts []goast.Stmt // nil or len(scheds) == 2 (delayload)
-	pkgImps    []*gox.PkgRef
-	pkgPaths   []string
-	hasScheds  bool
-	gameIsPtr  bool
-}
-
-func (p *gmxSettings) getScheds(cb *gox.CodeBuilder) []goast.Stmt {
-	if p == nil || !p.hasScheds {
-		return nil
-	}
-	if p.schedStmts == nil {
-		p.schedStmts = make([]goast.Stmt, 2)
-		for i, v := range p.scheds {
-			fn := cb.Val(spxLookup(p.pkgImps, v)).Call(0).InternalStack().Pop().Val
-			p.schedStmts[i] = &goast.ExprStmt{X: fn}
-		}
-		if len(p.scheds) < 2 {
-			p.schedStmts[1] = p.schedStmts[0]
-		}
-	}
-	return p.schedStmts
-}
-
-func newGmx(ctx *pkgCtx, pkg *gox.Package, file string, f *ast.File, conf *Config) *gmxSettings {
-	ext := parser.ClassFileExt(file)
-	gt, ok := conf.LookupClass(ext)
-	if !ok {
-		panic("TODO: class not found")
-	}
-	var name string
-	if f.IsProj {
-		_, name = filepath.Split(file)
-		if idx := strings.Index(name, "."); idx > 0 {
-			name = name[:idx]
-			if name == "main" {
-				name = gt.Class
-			}
-		}
-	}
-	pkgPaths := gt.PkgPaths
-	p := &gmxSettings{gameClass: name, pkgPaths: pkgPaths}
-	p.pkgImps = make([]*gox.PkgRef, len(pkgPaths))
-	for i, pkgPath := range pkgPaths {
-		p.pkgImps[i] = pkg.Import(pkgPath)
-	}
-	spx := p.pkgImps[0]
-	if gt.Class != "" {
-		p.game, p.gameIsPtr = spxRef(spx, gt.Class)
-	}
-	p.sprite = make(map[string]types.Object)
-	for _, v := range gt.Works {
-		obj, _ := spxRef(spx, v.Class)
-		p.sprite[v.Ext] = obj
-	}
-	if x := getStringConst(spx, "Gop_sched"); x != "" {
-		p.scheds, p.hasScheds = strings.SplitN(x, ",", 2), true
-	}
-	return p
-}
-
-func spxLookup(pkgImps []*gox.PkgRef, name string) gox.Ref {
-	for _, pkg := range pkgImps {
-		if o := pkg.TryRef(name); o != nil {
-			return o
-		}
-	}
-	panic("spxLookup: symbol not found - " + name)
-}
-
-func getDefaultClass(file string) string {
-	_, name := filepath.Split(file)
-	if idx := strings.Index(name, "."); idx > 0 {
-		name = name[:idx]
-	}
-	return name
-}
-
-func spxTryRef(spx *gox.PkgRef, typ string) (obj types.Object, isPtr bool) {
-	if strings.HasPrefix(typ, "*") {
-		typ, isPtr = typ[1:], true
-	}
-	obj = spx.Ref(typ)
-	return
-}
-
-func spxRef(spx *gox.PkgRef, typ string) (obj gox.Ref, isPtr bool) {
-	obj, isPtr = spxTryRef(spx, typ)
-	if obj == nil {
-		panic(spx.Path() + "." + typ + " not found")
-	}
-	return
-}
-
-func getStringConst(spx *gox.PkgRef, name string) string {
-	if o := spx.TryRef(name); o != nil {
-		if c, ok := o.(*types.Const); ok {
-			return constant.StringVal(c.Val())
-		}
-	}
-	return ""
-}
-
-func getFields(f *ast.File) (specs []ast.Spec) {
-	for _, decl := range f.Decls {
-		if g, ok := decl.(*ast.GenDecl); ok {
-			if g.Tok == token.VAR {
-				specs, g.Specs = g.Specs, nil
-				return
-			}
-			continue
-		}
-		break
-	}
-	return
-}
-
-func setBodyHandler(ctx *blockCtx) {
-	if ctx.isClass { // in a Go+ class file
-		if scheds := ctx.getScheds(ctx.cb); scheds != nil {
-			ctx.cb.SetBodyHandler(func(body *goast.BlockStmt, kind int) {
-				idx := 0
-				if len(body.List) == 0 {
-					idx = 1
-				}
-				gox.InsertStmtFront(body, scheds[idx])
-			})
-		}
-	}
-}
-
-func gmxMainFunc(p *gox.Package, ctx *pkgCtx) {
-	if o := p.Types.Scope().Lookup(ctx.gameClass); o != nil && hasMethod(o, "MainEntry") {
-		// new(Game).Main()
-		p.NewFunc(nil, "main", nil, nil, false).BodyStart(p).
-			Val(p.Builtin().Ref("new")).Val(o).Call(1).
-			MemberVal("Main").Call(0).EndStmt().
-			End()
-	}
-}
-
-func hasMethod(o types.Object, name string) bool {
-	if obj, ok := o.(*types.TypeName); ok {
-		if t, ok := obj.Type().(*types.Named); ok {
-			for i, n := 0, t.NumMethods(); i < n; i++ {
-				if t.Method(i).Name() == name {
-					return true
-				}
-			}
-		}
-	}
-	return false
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/compile.go b/cl/outline/cl/compile.go
deleted file mode 100644
index 6fd2a2ce..00000000
--- a/cl/outline/cl/compile.go
+++ /dev/null
@@ -1,969 +0,0 @@
-/*
- * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"fmt"
-	"go/types"
-	"log"
-	"os"
-	"reflect"
-	"sort"
-	"strings"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/ast/fromgo"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-	"github.com/goplus/gox/cpackages"
-	"github.com/goplus/mod/modfile"
-	"github.com/qiniu/x/errors"
-)
-
-type dbgFlags int
-
-const (
-	DbgFlagLoad dbgFlags = 1 << iota
-	DbgFlagLookup
-	DbgFlagAll = DbgFlagLoad | DbgFlagLookup
-)
-
-var (
-	enableRecover = true
-)
-
-var (
-	debugLoad   bool
-	debugLookup bool
-)
-
-func SetDisableRecover(disableRecover bool) {
-	enableRecover = !disableRecover
-}
-
-func SetDebug(flags dbgFlags) {
-	debugLoad = (flags & DbgFlagLoad) != 0
-	debugLookup = (flags & DbgFlagLookup) != 0
-}
-
-// -----------------------------------------------------------------------------
-
-type Project = modfile.Project
-
-// Config of loading Go+ packages.
-type Config struct {
-	// Fset provides source position information for syntax trees and types.
-	// If Fset is nil, Load will use a new fileset, but preserve Fset's value.
-	Fset *token.FileSet
-
-	// WorkingDir is the directory in which to run gop compiler.
-	WorkingDir string
-
-	// TargetDir is the directory in which to generate Go files.
-	TargetDir string
-
-	// C2goBase specifies base of standard c2go packages.
-	// Default is github.com/goplus/.
-	C2goBase string
-
-	// LookupPub lookups the c2go package pubfile (named c2go.a.pub).
-	LookupPub func(pkgPath string) (pubfile string, err error)
-
-	// LookupClass lookups a class by specified file extension.
-	LookupClass func(ext string) (c *Project, ok bool)
-
-	// An Importer resolves import paths to Packages.
-	Importer types.Importer
-
-	// NoFileLine = true means not to generate file line comments.
-	NoFileLine bool
-
-	// RelativePath = true means to generate file line comments with relative file path.
-	RelativePath bool
-
-	// NoAutoGenMain = true means not to auto generate main func is no entry.
-	NoAutoGenMain bool
-
-	// NoSkipConstant = true means to disable optimization of skipping constants.
-	NoSkipConstant bool
-}
-
-// -----------------------------------------------------------------------------
-
-type nodeInterp struct {
-	fset       *token.FileSet
-	files      map[string]*ast.File
-	workingDir string
-}
-
-func (p *nodeInterp) Position(start token.Pos) token.Position {
-	pos := p.fset.Position(start)
-	pos.Filename = relFile(p.workingDir, pos.Filename)
-	return pos
-}
-
-func (p *nodeInterp) Caller(node ast.Node) string {
-	if expr, ok := node.(*ast.CallExpr); ok {
-		node = expr.Fun
-		start := node.Pos()
-		pos := p.fset.Position(start)
-		f := p.files[pos.Filename]
-		n := int(node.End() - start)
-		return string(f.Code[pos.Offset : pos.Offset+n])
-	}
-	return "the function call"
-}
-
-func (p *nodeInterp) LoadExpr(node ast.Node) (src string, pos token.Position) {
-	start := node.Pos()
-	pos = p.fset.Position(start)
-	f := p.files[pos.Filename]
-	if f == nil { // not found
-		return
-	}
-	n := int(node.End() - start)
-	pos.Filename = relFile(p.workingDir, pos.Filename)
-	if pos.Offset+n < 0 {
-		log.Println("LoadExpr:", node, pos.Filename, pos.Line, pos.Offset, node.Pos(), node.End(), n)
-	}
-	src = string(f.Code[pos.Offset : pos.Offset+n])
-	return
-}
-
-// -----------------------------------------------------------------------------
-
-type lazyKind int
-
-const (
-	lazyAll lazyKind = iota
-	lazyAliasType
-	lazyInitType
-	lazyVarOrConst
-)
-
-type lazy struct {
-	pos  token.Pos
-	load func()
-	kind lazyKind
-}
-
-func (f *lazy) resolve(kind lazyKind) bool {
-	if load := f.load; load != nil && (kind == lazyAll || f.kind == kind) {
-		f.load = nil
-		load()
-		return true
-	}
-	return false
-}
-
-type lazyobjs map[string]*lazy
-
-func (p lazyobjs) insert(ctx *pkgCtx, name string, o *lazy) {
-	if old, ok := p[name]; ok {
-		npos := ctx.Position(o.pos)
-		ctx.handleCodeErrorf(&npos,
-			"%v redeclared in this block\n\t%v other declaration of %v", name, ctx.Position(old.pos), name)
-		return
-	}
-	p[name] = o
-}
-
-func (p lazyobjs) load(ctx *pkgCtx, name string, kind lazyKind) bool {
-	if enableRecover {
-		defer func() {
-			if e := recover(); e != nil {
-				ctx.handleRecover(e)
-			}
-		}()
-	}
-	if f, ok := p[name]; ok {
-		return f.resolve(kind)
-	}
-	return false
-}
-
-// -----------------------------------------------------------------------------
-
-type pkgCtx struct {
-	*nodeInterp
-	*gmxSettings
-	cpkgs *cpackages.Importer
-	lazys lazyobjs // delay: (1) alias types; (2) init named types; (4) global constants/variables
-	funcs []func() // delay: (3) func prototypes
-	bodys []func() // delay: (5) generate function body
-	errs  errors.List
-
-	// idents []*ast.Ident // toType ident recored
-	inInst int // toType in generic instance
-}
-
-func newCodeErrorf(pos *token.Position, format string, args ...interface{}) *gox.CodeError {
-	return &gox.CodeError{Pos: pos, Msg: fmt.Sprintf(format, args...)}
-}
-
-func (p *pkgCtx) newCodeError(start token.Pos, msg string) error {
-	pos := p.Position(start)
-	return &gox.CodeError{Pos: &pos, Msg: msg}
-}
-
-func (p *pkgCtx) newCodeErrorf(start token.Pos, format string, args ...interface{}) error {
-	pos := p.Position(start)
-	return newCodeErrorf(&pos, format, args...)
-}
-
-func (p *pkgCtx) handleCodeErrorf(pos *token.Position, format string, args ...interface{}) {
-	p.handleErr(newCodeErrorf(pos, format, args...))
-}
-
-func (p *pkgCtx) handleErr(err error) {
-	p.errs = append(p.errs, err)
-}
-
-func (p *pkgCtx) handleRecover(e interface{}) {
-	err, ok := e.(error)
-	if !ok {
-		if msg, ok := e.(string); ok {
-			err = errors.New(msg)
-		} else {
-			panic(e)
-		}
-	}
-	p.handleErr(err)
-}
-
-func (p *pkgCtx) loadNamed(at *gox.Package, t *types.Named) {
-	o := t.Obj()
-	if o.Pkg() == at.Types {
-		p.loadObject(o.Name())
-	}
-}
-
-func (p *pkgCtx) insertObject(name string, pos token.Pos, kind lazyKind, load func()) {
-	if name == "_" {
-		p.bodys = append(p.bodys, load)
-	} else {
-		p.lazys.insert(p, name, &lazy{pos, load, kind})
-	}
-}
-
-func (p *pkgCtx) insertNames(pos token.Pos, names []*ast.Ident, load func()) {
-	lazy := &lazy{pos, load, lazyVarOrConst}
-	for _, ident := range names {
-		name := ident.Name
-		if name == "_" {
-			p.bodys = append(p.bodys, lazy.load)
-		} else {
-			p.lazys.insert(p, name, lazy)
-		}
-	}
-}
-
-func (p *pkgCtx) loadObject(name string) bool {
-	return p.lazys.load(p, name, lazyAll)
-}
-
-type blockCtx struct {
-	*pkgCtx
-	pkg          *gox.Package
-	cb           *gox.CodeBuilder
-	imports      map[string]*gox.PkgRef
-	lookups      []*gox.PkgRef
-	clookups     []*cpackages.PkgRef
-	tlookup      *typeParamLookup
-	c2goBase     string // default is `github.com/goplus/`
-	targetDir    string
-	classRecv    *ast.FieldList // available when gmxSettings != nil
-	isClass      bool
-	fileLine     bool
-	relativePath bool
-}
-
-func (p *blockCtx) ensureLoaded(t *types.Named) {
-	if t.Underlying() == nil {
-		p.loadNamed(p.pkg, t)
-	}
-}
-
-func getUnderlying(ctx *blockCtx, typ types.Type) types.Type {
-	u := typ.Underlying()
-	if u == nil {
-		if t, ok := typ.(*types.Named); ok {
-			ctx.loadNamed(ctx.pkg, t)
-			u = t.Underlying()
-		}
-	}
-	return u
-}
-
-func (p *blockCtx) findImport(name string) (pr *gox.PkgRef, ok bool) {
-	pr, ok = p.imports[name]
-	return
-}
-
-// -----------------------------------------------------------------------------
-
-// Context saves package level states during compiling.
-type Context = pkgCtx
-
-func (p *Context) Complete(pkg *gox.Package, autoGenMain bool) error {
-	for _, genBody := range p.bodys {
-		genBody()
-	}
-	pkgTypes := pkg.Types
-	if autoGenMain && pkgTypes.Name() == "main" {
-		if obj := pkgTypes.Scope().Lookup("main"); obj == nil {
-			old, _ := pkg.SetCurFile(defaultGoFile, false)
-			pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End()
-			pkg.RestoreCurFile(old)
-		}
-	}
-	return p.errs.ToError()
-}
-
-func (p *Context) genOutline() error {
-	for _, f := range p.lazys {
-		f.resolve(lazyAliasType)
-	}
-	for _, f := range p.lazys {
-		f.resolve(lazyInitType)
-	}
-	for _, fnProto := range p.funcs {
-		fnProto()
-	}
-	for _, f := range p.lazys {
-		f.resolve(lazyVarOrConst)
-	}
-	return p.errs.ToError()
-}
-
-// -----------------------------------------------------------------------------
-
-const (
-	defaultGoFile  = ""
-	skippingGoFile = "_skip"
-	testingGoFile  = "_test"
-)
-
-const (
-	ioxPkgPath = "github.com/goplus/gop/builtin/iox"
-)
-
-// NewOutline creates a Go+ package outline.
-func NewOutline(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package, ctx *Context, err error) {
-	workingDir := conf.WorkingDir
-	if workingDir == "" {
-		workingDir, _ = os.Getwd()
-	}
-	targetDir := conf.TargetDir
-	if targetDir == "" {
-		targetDir = workingDir
-	}
-	fset := conf.Fset
-	files := pkg.Files
-	interp := &nodeInterp{
-		fset: fset, files: files, workingDir: workingDir,
-	}
-	ctx = &pkgCtx{
-		nodeInterp: interp,
-		lazys:      make(lazyobjs),
-	}
-	confGox := &gox.Config{
-		Fset:            fset,
-		Importer:        conf.Importer,
-		LoadNamed:       ctx.loadNamed,
-		HandleErr:       ctx.handleErr,
-		NodeInterpreter: interp,
-		NewBuiltin:      newBuiltinDefault,
-		DefaultGoFile:   defaultGoFile,
-		NoSkipConstant:  conf.NoSkipConstant,
-		PkgPathIox:      ioxPkgPath,
-	}
-	if enableRecover {
-		defer func() {
-			if e := recover(); e != nil {
-				ctx.handleRecover(e)
-				err = ctx.errs.ToError()
-			}
-		}()
-	}
-	p = gox.NewPackage(pkgPath, pkg.Name, confGox)
-	for file, gmx := range files {
-		if gmx.IsProj {
-			ctx.gmxSettings = newGmx(ctx, p, file, gmx, conf)
-			break
-		}
-	}
-	if ctx.gmxSettings == nil {
-		for file, gmx := range files {
-			if gmx.IsClass && !gmx.IsNormalGox {
-				ctx.gmxSettings = newGmx(ctx, p, file, gmx, conf)
-				break
-			}
-		}
-	}
-
-	// sort files
-	type File struct {
-		*ast.File
-		path string
-	}
-	sfiles := make([]*File, 0, len(files))
-	for fpath, f := range files {
-		sfiles = append(sfiles, &File{f, fpath})
-	}
-	sort.Slice(sfiles, func(i, j int) bool {
-		return sfiles[i].path < sfiles[j].path
-	})
-
-	// fset = p.Fset // conf.Fset maybe is nil
-	for _, f := range sfiles {
-		fileLine := !conf.NoFileLine
-		ctx := &blockCtx{
-			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir,
-			fileLine: fileLine, relativePath: conf.RelativePath, isClass: f.IsClass,
-			c2goBase: c2goBase(conf.C2goBase), imports: make(map[string]*gox.PkgRef),
-		}
-		preloadGopFile(p, ctx, f.path, f.File, conf)
-	}
-
-	for fpath, gof := range pkg.GoFiles {
-		f := fromgo.ASTFile(gof, 0)
-		ctx := &blockCtx{
-			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir,
-			imports: make(map[string]*gox.PkgRef),
-		}
-		preloadFile(p, ctx, fpath, f, false)
-	}
-	err = ctx.genOutline()
-	return
-}
-
-// NewPackage creates a Go+ package instance.
-func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package, err error) {
-	p, ctx, err := NewOutline(pkgPath, pkg, conf)
-	if err != nil {
-		return
-	}
-	err = ctx.Complete(p, !conf.NoAutoGenMain)
-	return
-}
-
-func getEntrypoint(f *ast.File) string {
-	switch {
-	case f.IsProj:
-		return "MainEntry"
-	case f.IsClass:
-		return "Main"
-	case f.Name.Name != "main":
-		return "init"
-	default:
-		return "main"
-	}
-}
-
-func genGoFile(file string, gopFile bool) string {
-	if gopFile {
-		if strings.HasSuffix(file, "_test.gop") {
-			return testingGoFile
-		}
-		return defaultGoFile
-	}
-	return skippingGoFile
-}
-
-func preloadGopFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, conf *Config) {
-	var parent = ctx.pkgCtx
-	var classType string
-	var baseTypeName string
-	var baseType types.Type
-	var spxClass bool
-	switch {
-	case f.IsProj:
-		classType = parent.gameClass
-		o := parent.game
-		baseTypeName, baseType = o.Name(), o.Type()
-		if parent.gameIsPtr {
-			baseType = types.NewPointer(baseType)
-		}
-	case f.IsClass:
-		classType = getDefaultClass(file)
-		if parent.gmxSettings != nil {
-			ext := parser.ClassFileExt(file)
-			o, ok := parent.sprite[ext]
-			if ok {
-				baseTypeName, baseType, spxClass = o.Name(), o.Type(), true
-			}
-		}
-	}
-	if classType != "" {
-		ctx.classRecv = &ast.FieldList{List: []*ast.Field{{
-			Names: []*ast.Ident{
-				{Name: "this"},
-			},
-			Type: &ast.StarExpr{
-				X: &ast.Ident{Name: classType},
-			},
-		}}}
-		if parent.gmxSettings != nil {
-			ctx.lookups = make([]*gox.PkgRef, len(parent.pkgPaths))
-			for i, pkgPath := range parent.pkgPaths {
-				ctx.lookups[i] = p.Import(pkgPath)
-			}
-		}
-		if debugLoad {
-			log.Println("==> Load > NewType", classType)
-		}
-		pos := f.Pos()
-		specs := getFields(f)
-		decl := p.NewTypeDefs().NewType(classType, pos)
-		parent.insertObject(classType, pos, lazyInitType, func() {
-			if debugLoad {
-				log.Println("==> Load > InitType", classType)
-			}
-			pkg := p.Types
-			var flds []*types.Var
-			var tags []string
-			chk := newCheckRedecl()
-			if len(baseTypeName) != 0 {
-				flds = append(flds, types.NewField(pos, pkg, baseTypeName, baseType, true))
-				tags = append(tags, "")
-				chk.chkRedecl(ctx, baseTypeName, pos)
-			}
-			if spxClass && parent.gmxSettings != nil && parent.gameClass != "" {
-				typ := toType(ctx, &ast.StarExpr{X: &ast.Ident{Name: parent.gameClass}})
-				name := getTypeName(typ)
-				if !chk.chkRedecl(ctx, name, pos) {
-					fld := types.NewField(pos, pkg, name, typ, true)
-					flds = append(flds, fld)
-					tags = append(tags, "")
-				}
-			}
-			for _, v := range specs {
-				spec := v.(*ast.ValueSpec)
-				var embed bool
-				if spec.Names == nil {
-					embed = true
-					v := parseTypeEmbedName(spec.Type)
-					spec.Names = []*ast.Ident{v}
-				}
-				typ := toType(ctx, spec.Type)
-				for _, name := range spec.Names {
-					if chk.chkRedecl(ctx, name.Name, name.Pos()) {
-						continue
-					}
-					flds = append(flds, types.NewField(name.Pos(), pkg, name.Name, typ, embed))
-					tags = append(tags, toFieldTag(spec.Tag))
-				}
-			}
-			decl.InitType(p, types.NewStruct(flds, tags))
-		})
-	}
-	// check class project no MainEntry and auto added
-	if f.IsProj && !conf.NoAutoGenMain && !f.NoEntrypoint() && f.Name.Name == "main" {
-		entry := getEntrypoint(f)
-		var hasEntry bool
-		for _, decl := range f.Decls {
-			switch d := decl.(type) {
-			case *ast.FuncDecl:
-				if d.Name.Name == entry {
-					hasEntry = true
-				}
-			}
-		}
-		if !hasEntry {
-			f.Decls = append(f.Decls, &ast.FuncDecl{
-				Name: ast.NewIdent(entry),
-				Type: &ast.FuncType{Params: &ast.FieldList{}},
-				Body: &ast.BlockStmt{},
-			})
-		}
-	}
-	if d := f.ShadowEntry; d != nil {
-		d.Name.Name = getEntrypoint(f)
-	}
-	preloadFile(p, ctx, file, f, true)
-}
-
-func parseTypeEmbedName(typ ast.Expr) *ast.Ident {
-retry:
-	switch t := typ.(type) {
-	case *ast.Ident:
-		return t
-	case *ast.SelectorExpr:
-		return t.Sel
-	case *ast.StarExpr:
-		typ = t.X
-		goto retry
-	}
-	return nil
-}
-
-func preloadFile(p *gox.Package, ctx *blockCtx, file string, f *ast.File, gopFile bool) {
-	parent := ctx.pkgCtx
-	goFile := genGoFile(file, gopFile)
-	old, _ := p.SetCurFile(goFile, true)
-	defer p.RestoreCurFile(old)
-	for _, decl := range f.Decls {
-		switch d := decl.(type) {
-		case *ast.FuncDecl:
-			dRecv := d.Recv
-			if dRecv == nil {
-				dRecv = ctx.classRecv // maybe in class file (.spx/.gmx)
-			}
-			parent.funcs = append(parent.funcs, func() {
-				old, _ := p.SetCurFile(goFile, true)
-				defer p.RestoreCurFile(old)
-				var recv *types.Var
-				var ok bool
-				if dRecv != nil {
-					if recv, ok = toRecv(ctx, dRecv); !ok {
-						return
-					}
-				}
-				preloadFunc(ctx, recv, d, gopFile)
-			})
-		case *ast.GenDecl:
-			switch d.Tok {
-			case token.IMPORT:
-				for _, item := range d.Specs {
-					loadImport(ctx, item.(*ast.ImportSpec))
-				}
-			case token.TYPE:
-				tdecl := ctx.pkg.NewTypeDefs().SetComments(d.Doc)
-				for _, spec := range d.Specs {
-					t := spec.(*ast.TypeSpec)
-					name, pos := t.Name.Name, t.Pos()
-					if t.Assign != token.NoPos { // alias type
-						parent.insertObject(name, pos, lazyAliasType, func() {
-							if debugLoad {
-								log.Println("==> Load > AliasType", name)
-							}
-							tdecl.AliasType(name, toType(ctx, t.Type), pos)
-						})
-						continue
-					}
-					if debugLoad {
-						log.Println("==> Load > NewType", name)
-					}
-					decl := tdecl.NewType(name, pos).SetComments(p, t.Doc)
-					fnInitType := getInitType(ctx, decl, t, gopFile)
-					parent.insertObject(name, pos, lazyInitType, fnInitType)
-				}
-			case token.CONST:
-				pkg := ctx.pkg
-				cdecl := pkg.NewConstDefs(pkg.Types.Scope())
-				for iotav, spec := range d.Specs {
-					vSpec := spec.(*ast.ValueSpec)
-					if debugLoad {
-						log.Println("==> Preload const", vSpec.Names)
-					}
-					at := cdecl.NewPos()
-					fn := makeF(ctx, cdecl, vSpec)
-					ctx.insertNames(vSpec.Pos(), vSpec.Names, func() {
-						loadConsts(ctx, cdecl, at, fn, vSpec, iotav)
-					})
-				}
-			case token.VAR:
-				pkg := ctx.pkg
-				vdecl := pkg.NewVarDefs(pkg.Types.Scope())
-				for _, spec := range d.Specs {
-					vSpec := spec.(*ast.ValueSpec)
-					if debugLoad {
-						log.Println("==> Preload var", vSpec.Names)
-					}
-					at := vdecl.NewPos()
-					ctx.insertNames(vSpec.Pos(), vSpec.Names, func() {
-						loadVars(ctx, vdecl, at, vSpec)
-					})
-				}
-			default:
-				log.Panicln("TODO - tok:", d.Tok, "spec:", reflect.TypeOf(d.Specs).Elem())
-			}
-		default:
-			log.Panicln("TODO - gopkg.Package.load: unknown decl -", reflect.TypeOf(decl))
-		}
-	}
-	if f.IsProj {
-		parent.bodys = append(parent.bodys, func() {
-			old, _ := p.SetCurFile(goFile, true)
-			defer p.RestoreCurFile(old)
-			gmxMainFunc(p, parent)
-		})
-	}
-}
-
-func getInitType(ctx *blockCtx, decl *gox.TypeDecl, t *ast.TypeSpec, gopFile bool) func() {
-	if gopFile {
-		return func() { // decycle
-			if debugLoad {
-				log.Println("==> Load > InitType", t.Name)
-			}
-			decl.InitType(ctx.pkg, toTypeInited(ctx, t.Type))
-		}
-	}
-	return func() {
-		if debugLoad {
-			log.Println("==> Load > InitType", t.Name)
-		}
-		initType(ctx, decl.Type(), t)
-	}
-}
-
-func preloadFunc(ctx *blockCtx, recv *types.Var, d *ast.FuncDecl, genBody bool) {
-	name := d.Name.Name
-	if debugLoad {
-		if recv == nil {
-			log.Println("==> New func", name)
-		} else {
-			log.Printf("==> New method %v.%s\n", recv.Type(), name)
-		}
-	}
-	if d.Operator {
-		if recv != nil { // binary op
-			if v, ok := binaryGopNames[name]; ok {
-				name = v
-			}
-		} else { // unary op
-			if v, ok := unaryGopNames[name]; ok {
-				name = v
-				at := ctx.pkg.Types
-				arg1 := d.Type.Params.List[0]
-				typ := toType(ctx, arg1.Type)
-				recv = types.NewParam(arg1.Pos(), at, arg1.Names[0].Name, typ)
-				d.Type.Params.List = nil
-			}
-		}
-	}
-	sig := toFuncType(ctx, d.Type, recv, d)
-	fn, err := ctx.pkg.NewFuncWith(d.Name.Pos(), name, sig, func() token.Pos {
-		return d.Recv.List[0].Type.Pos()
-	})
-	if err != nil {
-		ctx.handleErr(err)
-		return
-	}
-	if d.Doc != nil {
-		fn.SetComments(ctx.pkg, d.Doc)
-	}
-	if genBody {
-		if body := d.Body; body != nil {
-			ctx.bodys = append(ctx.bodys, func() { // interface issue: #795
-				loadFuncBody(ctx, fn, body, d)
-			})
-		}
-	}
-}
-
-func loadFuncBody(ctx *blockCtx, fn *gox.Func, body *ast.BlockStmt, src ast.Node) {
-	cb := fn.BodyStart(ctx.pkg)
-	compileStmts(ctx, body.List)
-	cb.End(src)
-}
-
-var binaryGopNames = map[string]string{
-	"+": "Gop_Add",
-	"-": "Gop_Sub",
-	"*": "Gop_Mul",
-	"/": "Gop_Quo",
-	"%": "Gop_Rem",
-
-	"&":  "Gop_And",
-	"|":  "Gop_Or",
-	"^":  "Gop_Xor",
-	"<<": "Gop_Lsh",
-	">>": "Gop_Rsh",
-	"&^": "Gop_AndNot",
-
-	"+=": "Gop_AddAssign",
-	"-=": "Gop_SubAssign",
-	"*=": "Gop_MulAssign",
-	"/=": "Gop_QuoAssign",
-	"%=": "Gop_RemAssign",
-
-	"&=":  "Gop_AndAssign",
-	"|=":  "Gop_OrAssign",
-	"^=":  "Gop_XorAssign",
-	"<<=": "Gop_LshAssign",
-	">>=": "Gop_RshAssign",
-	"&^=": "Gop_AndNotAssign",
-
-	"==": "Gop_EQ",
-	"!=": "Gop_NE",
-	"<=": "Gop_LE",
-	"<":  "Gop_LT",
-	">=": "Gop_GE",
-	">":  "Gop_GT",
-
-	"&&": "Gop_LAnd",
-	"||": "Gop_LOr",
-
-	"<-": "Gop_Send",
-}
-
-var unaryGopNames = map[string]string{
-	"++": "Gop_Inc",
-	"--": "Gop_Dec",
-	"-":  "Gop_Neg",
-	"+":  "Gop_Dup",
-	"^":  "Gop_Not",
-	"!":  "Gop_LNot",
-	"<-": "Gop_Recv",
-}
-
-func simplifyGopPackage(pkgPath string) string {
-	if strings.HasPrefix(pkgPath, "gop/") {
-		return "github.com/goplus/" + pkgPath
-	}
-	return pkgPath
-}
-
-func loadImport(ctx *blockCtx, spec *ast.ImportSpec) {
-	if enableRecover {
-		defer func() {
-			if e := recover(); e != nil {
-				ctx.handleRecover(e)
-			}
-		}()
-	}
-	var pkg *gox.PkgRef
-	var pkgPath = toString(spec.Path)
-	if realPath, kind := checkC2go(pkgPath); kind != c2goInvalid {
-		if kind == c2goStandard {
-			realPath = ctx.c2goBase + realPath
-		}
-		if pkg = loadC2goPkg(ctx, realPath, spec.Path); pkg == nil {
-			return
-		}
-	} else {
-		pkg = ctx.pkg.Import(simplifyGopPackage(pkgPath), spec)
-	}
-	var name string
-	if spec.Name != nil {
-		name = spec.Name.Name
-		if name == "." {
-			ctx.lookups = append(ctx.lookups, pkg)
-			return
-		}
-		if name == "_" {
-			pkg.MarkForceUsed()
-			return
-		}
-	} else {
-		name = pkg.Types.Name()
-	}
-	ctx.imports[name] = pkg
-}
-
-func makeF(ctx *blockCtx, decl *gox.ConstDefs, v *ast.ValueSpec) gox.F {
-	if v.Values != nil {
-		decl.F = func(cb *gox.CodeBuilder) int {
-			for _, val := range v.Values {
-				compileExpr(ctx, val)
-			}
-			return len(v.Values)
-		}
-	}
-	return decl.F
-}
-
-func loadConstSpecs(ctx *blockCtx, decl *gox.ConstDefs, specs []ast.Spec) {
-	for iotav, spec := range specs {
-		vSpec := spec.(*ast.ValueSpec)
-		loadConsts(ctx, decl, decl.NewPos(), makeF(ctx, decl, vSpec), vSpec, iotav)
-	}
-}
-
-func loadConsts(ctx *blockCtx, decl *gox.ConstDefs, at gox.ValueAt, fn gox.F, v *ast.ValueSpec, iotav int) {
-	names := makeNames(v.Names)
-	if v.Values == nil {
-		if debugLoad {
-			log.Println("==> Load const", names)
-		}
-		decl.NextAt(at, fn, iotav, v.Pos(), names...)
-		return
-	}
-	var typ types.Type
-	if v.Type != nil {
-		typ = toType(ctx, v.Type)
-	}
-	if debugLoad {
-		log.Println("==> Load const", names, typ)
-	}
-	decl.NewAt(at, fn, iotav, v.Pos(), typ, names...)
-}
-
-func loadVarSpecs(ctx *blockCtx, decl *gox.VarDefs, specs []ast.Spec) {
-	for _, spec := range specs {
-		loadVars(ctx, decl, decl.NewPos(), spec.(*ast.ValueSpec))
-	}
-}
-
-func loadVars(ctx *blockCtx, decl *gox.VarDefs, at gox.ValueAt, v *ast.ValueSpec) {
-	var typ types.Type
-	if v.Type != nil {
-		typ = toType(ctx, v.Type)
-	}
-	names := makeNames(v.Names)
-	if debugLoad {
-		log.Println("==> Load var", typ, names)
-	}
-	varDecl := decl.NewAt(at, v.Names[0].Pos(), typ, names...)
-	if nv := len(v.Values); nv > 0 {
-		cb := varDecl.InitStart(ctx.pkg)
-		if enableRecover {
-			defer func() {
-				if e := recover(); e != nil {
-					cb.ResetInit()
-					panic(e)
-				}
-			}()
-		}
-		if nv == 1 && len(names) == 2 {
-			compileExpr(ctx, v.Values[0], clCallWithTwoValue)
-		} else {
-			for _, val := range v.Values {
-				switch e := val.(type) {
-				case *ast.LambdaExpr, *ast.LambdaExpr2:
-					if len(v.Values) == 1 {
-						sig := checkLambdaFuncType(ctx, e, typ, clLambaAssign, v.Names[0])
-						compileLambda(ctx, e, sig)
-					} else {
-						panic(ctx.newCodeErrorf(e.Pos(), "lambda unsupport multiple assignment"))
-					}
-				case *ast.SliceLit:
-					compileSliceLit(ctx, e, typ)
-				case *ast.CompositeLit:
-					compileCompositeLit(ctx, e, typ, false)
-				default:
-					compileExpr(ctx, val)
-				}
-			}
-		}
-		cb.EndInit(nv)
-	}
-}
-
-func makeNames(vals []*ast.Ident) []string {
-	names := make([]string, len(vals))
-	for i, v := range vals {
-		names[i] = v.Name
-	}
-	return names
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/expr.go b/cl/outline/cl/expr.go
deleted file mode 100644
index de5d7fd9..00000000
--- a/cl/outline/cl/expr.go
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"bytes"
-	goast "go/ast"
-	gotoken "go/token"
-	"go/types"
-	"log"
-	"math/big"
-	"reflect"
-	"strconv"
-	"strings"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/printer"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-	"github.com/goplus/gox/cpackages"
-)
-
-/*-----------------------------------------------------------------------------
-
-Name context:
-- varVal               (ident)
-- varRef = expr        (identLHS)
-- pkgRef.member        (selectorExpr)
-- pkgRef.member = expr (selectorExprLHS)
-- pkgRef.fn(args)      (callExpr)
-- fn(args)             (callExpr)
-- spx.fn(args)         (callExpr)
-- this.member          (classMember)
-- this.method(args)    (classMember)
-
-Name lookup:
-- local variables
-- $recv members (only in class files)
-- package globals (variables, constants, types, imported packages etc.)
-- $spx package exports (only in class files)
-- $universe package exports (including builtins)
-
-// ---------------------------------------------------------------------------*/
-
-const (
-	clIdentCanAutoCall = 1 << iota
-	clIdentAllowBuiltin
-	clIdentLHS
-	clIdentSelectorExpr // this ident is X of ast.SelectorExpr
-	clIdentGoto
-	clCallWithTwoValue
-	clCommandWithoutArgs
-)
-
-const (
-	objNormal = iota
-	objPkgRef
-	objCPkgRef
-)
-
-const errorPkgPath = "github.com/qiniu/x/errors"
-
-func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (obj *gox.PkgRef, kind int) {
-	fvalue := (flags&clIdentSelectorExpr) != 0 || (flags&clIdentLHS) == 0
-	name := ident.Name
-	if name == "_" {
-		if fvalue {
-			panic(ctx.newCodeError(ident.Pos(), "cannot use _ as value"))
-		}
-		ctx.cb.VarRef(nil)
-		return
-	}
-
-	scope := ctx.pkg.Types.Scope()
-	at, o := ctx.cb.Scope().LookupParent(name, token.NoPos)
-	if o != nil {
-		if at != scope && at != types.Universe { // local object
-			goto find
-		}
-	}
-
-	if ctx.isClass { // in a Go+ class file
-		if fn := ctx.cb.Func(); fn != nil {
-			sig := fn.Ancestor().Type().(*types.Signature)
-			if recv := sig.Recv(); recv != nil {
-				ctx.cb.Val(recv)
-				if compileMember(ctx, ident, name, flags&^clCommandWithoutArgs) == nil { // class member object
-					return
-				}
-				ctx.cb.InternalStack().PopN(1)
-			}
-		}
-	}
-
-	// global object
-	if ctx.loadObject(name) {
-		o, at = scope.Lookup(name), scope
-	}
-	if o != nil && at != types.Universe {
-		goto find
-	}
-
-	// pkgRef object
-	if (flags & clIdentSelectorExpr) != 0 {
-		if name == "C" && len(ctx.clookups) > 0 {
-			return nil, objCPkgRef
-		}
-		if pr, ok := ctx.findImport(name); ok {
-			return pr, objPkgRef
-		}
-	}
-
-	// object from import . "xxx"
-	if compilePkgRef(ctx, nil, ident, flags, objPkgRef) {
-		return
-	}
-
-	// universe object
-	if obj := ctx.pkg.Builtin().TryRef(name); obj != nil {
-		if (flags&clIdentAllowBuiltin) == 0 && isBuiltin(o) && !strings.HasPrefix(o.Name(), "print") {
-			panic(ctx.newCodeErrorf(ident.Pos(), "use of builtin %s not in function call", name))
-		}
-		o = obj
-	} else if o == nil {
-		if (clIdentGoto & flags) != 0 {
-			l := ident.Obj.Data.(*ast.Ident)
-			panic(ctx.newCodeErrorf(l.Pos(), "label %v is not defined", l.Name))
-		}
-		panic(ctx.newCodeErrorf(ident.Pos(), "undefined: %s", name))
-	}
-
-find:
-	if fvalue {
-		ctx.cb.Val(o, ident)
-	} else {
-		ctx.cb.VarRef(o, ident)
-	}
-	return
-}
-
-func isBuiltin(o types.Object) bool {
-	if _, ok := o.(*types.Builtin); ok {
-		return ok
-	}
-	return false
-}
-
-func compileMember(ctx *blockCtx, v ast.Node, name string, flags int) error {
-	var mflag gox.MemberFlag
-	switch {
-	case (flags & clIdentLHS) != 0:
-		mflag = gox.MemberFlagRef
-	case (flags & clCommandWithoutArgs) != 0:
-		mflag = gox.MemberFlagMethodAlias
-	case (flags & clIdentCanAutoCall) != 0:
-		mflag = gox.MemberFlagAutoProperty
-	default:
-		mflag = gox.MemberFlagMethodAlias
-	}
-	_, err := ctx.cb.Member(name, mflag, v)
-	return err
-}
-
-func compileExprLHS(ctx *blockCtx, expr ast.Expr) {
-	switch v := expr.(type) {
-	case *ast.Ident:
-		compileIdent(ctx, v, clIdentLHS)
-	case *ast.IndexExpr:
-		compileIndexExprLHS(ctx, v)
-	case *ast.SelectorExpr:
-		compileSelectorExprLHS(ctx, v)
-	case *ast.StarExpr:
-		compileStarExprLHS(ctx, v)
-	default:
-		log.Panicln("compileExpr failed: unknown -", reflect.TypeOf(v))
-	}
-}
-
-func twoValue(inFlags []int) bool {
-	return inFlags != nil && (inFlags[0]&clCallWithTwoValue) != 0
-}
-
-func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) {
-	switch v := expr.(type) {
-	case *ast.Ident:
-		flags := clIdentCanAutoCall
-		if inFlags != nil {
-			flags |= inFlags[0]
-		}
-		compileIdent(ctx, v, flags)
-	case *ast.BasicLit:
-		compileBasicLit(ctx, v)
-	case *ast.CallExpr:
-		flags := 0
-		if inFlags != nil {
-			flags = inFlags[0]
-		}
-		compileCallExpr(ctx, v, flags)
-	case *ast.SelectorExpr:
-		flags := clIdentCanAutoCall
-		if inFlags != nil {
-			flags |= inFlags[0]
-		}
-		compileSelectorExpr(ctx, v, flags)
-	case *ast.BinaryExpr:
-		compileBinaryExpr(ctx, v)
-	case *ast.UnaryExpr:
-		compileUnaryExpr(ctx, v, twoValue(inFlags))
-	case *ast.FuncLit:
-		compileFuncLit(ctx, v)
-	case *ast.CompositeLit:
-		compileCompositeLit(ctx, v, nil, false)
-	case *ast.SliceLit:
-		compileSliceLit(ctx, v, nil)
-	case *ast.RangeExpr:
-		compileRangeExpr(ctx, v)
-	case *ast.IndexExpr:
-		compileIndexExpr(ctx, v, twoValue(inFlags))
-	case *ast.IndexListExpr:
-		compileIndexListExpr(ctx, v, twoValue(inFlags))
-	case *ast.SliceExpr:
-		compileSliceExpr(ctx, v)
-	case *ast.StarExpr:
-		compileStarExpr(ctx, v)
-	case *ast.ArrayType:
-		ctx.cb.Typ(toArrayType(ctx, v), v)
-	case *ast.MapType:
-		ctx.cb.Typ(toMapType(ctx, v), v)
-	case *ast.StructType:
-		ctx.cb.Typ(toStructType(ctx, v), v)
-	case *ast.ChanType:
-		ctx.cb.Typ(toChanType(ctx, v), v)
-	case *ast.InterfaceType:
-		ctx.cb.Typ(toInterfaceType(ctx, v), v)
-	case *ast.ComprehensionExpr:
-		compileComprehensionExpr(ctx, v, twoValue(inFlags))
-	case *ast.TypeAssertExpr:
-		compileTypeAssertExpr(ctx, v, twoValue(inFlags))
-	case *ast.ParenExpr:
-		compileExpr(ctx, v.X, inFlags...)
-	case *ast.ErrWrapExpr:
-		compileErrWrapExpr(ctx, v, 0)
-	case *ast.FuncType:
-		ctx.cb.Typ(toFuncType(ctx, v, nil, nil), v)
-	case *ast.Ellipsis:
-		panic("compileEllipsis: ast.Ellipsis unexpected")
-	case *ast.KeyValueExpr:
-		panic("compileExpr: ast.KeyValueExpr unexpected")
-	default:
-		log.Panicln("compileExpr failed: unknown -", reflect.TypeOf(v))
-	}
-}
-
-func compileExprOrNone(ctx *blockCtx, expr ast.Expr) {
-	if expr != nil {
-		compileExpr(ctx, expr)
-	} else {
-		ctx.cb.None()
-	}
-}
-
-func compileUnaryExpr(ctx *blockCtx, v *ast.UnaryExpr, twoValue bool) {
-	compileExpr(ctx, v.X)
-	ctx.cb.UnaryOp(gotoken.Token(v.Op), twoValue, v)
-}
-
-func compileBinaryExpr(ctx *blockCtx, v *ast.BinaryExpr) {
-	compileExpr(ctx, v.X)
-	compileExpr(ctx, v.Y)
-	ctx.cb.BinaryOp(gotoken.Token(v.Op), v)
-}
-
-func compileIndexExprLHS(ctx *blockCtx, v *ast.IndexExpr) {
-	compileExpr(ctx, v.X)
-	compileExpr(ctx, v.Index)
-	ctx.cb.IndexRef(1, v)
-}
-
-func compileStarExprLHS(ctx *blockCtx, v *ast.StarExpr) { // *x = ...
-	compileExpr(ctx, v.X)
-	ctx.cb.ElemRef()
-}
-
-func compileStarExpr(ctx *blockCtx, v *ast.StarExpr) { // ... = *x
-	compileExpr(ctx, v.X)
-	ctx.cb.Star()
-}
-
-func compileTypeAssertExpr(ctx *blockCtx, v *ast.TypeAssertExpr, twoValue bool) {
-	compileExpr(ctx, v.X)
-	if v.Type == nil {
-		panic("TODO: x.(type) is only used in type switch")
-	}
-	typ := toType(ctx, v.Type)
-	ctx.cb.TypeAssert(typ, twoValue, v)
-}
-
-func compileIndexExpr(ctx *blockCtx, v *ast.IndexExpr, twoValue bool) { // x[i]
-	compileExpr(ctx, v.X)
-	compileExpr(ctx, v.Index)
-	ctx.cb.Index(1, twoValue, v)
-}
-
-func compileIndexListExpr(ctx *blockCtx, v *ast.IndexListExpr, twoValue bool) { // fn[t1,t2]
-	compileExpr(ctx, v.X)
-	n := len(v.Indices)
-	for i := 0; i < n; i++ {
-		compileExpr(ctx, v.Indices[i])
-	}
-	ctx.cb.Index(n, twoValue, v)
-}
-
-func compileSliceExpr(ctx *blockCtx, v *ast.SliceExpr) { // x[i:j:k]
-	compileExpr(ctx, v.X)
-	compileExprOrNone(ctx, v.Low)
-	compileExprOrNone(ctx, v.High)
-	if v.Slice3 {
-		compileExprOrNone(ctx, v.Max)
-	}
-	ctx.cb.Slice(v.Slice3, v)
-}
-
-func compileSelectorExprLHS(ctx *blockCtx, v *ast.SelectorExpr) {
-	switch x := v.X.(type) {
-	case *ast.Ident:
-		if at, kind := compileIdent(ctx, x, clIdentLHS|clIdentSelectorExpr); kind != objNormal {
-			ctx.cb.VarRef(at.Ref(v.Sel.Name))
-			return
-		}
-	default:
-		compileExpr(ctx, v.X)
-	}
-	ctx.cb.MemberRef(v.Sel.Name, v)
-}
-
-func compileSelectorExpr(ctx *blockCtx, v *ast.SelectorExpr, flags int) {
-	switch x := v.X.(type) {
-	case *ast.Ident:
-		if at, kind := compileIdent(ctx, x, flags|clIdentCanAutoCall|clIdentSelectorExpr); kind != objNormal {
-			if compilePkgRef(ctx, at, v.Sel, flags, kind) {
-				return
-			}
-			if token.IsExported(v.Sel.Name) {
-				panic(ctx.newCodeErrorf(x.Pos(), "undefined: %s.%s", x.Name, v.Sel.Name))
-			}
-			panic(ctx.newCodeErrorf(x.Pos(), "cannot refer to unexported name %s.%s", x.Name, v.Sel.Name))
-		}
-	default:
-		compileExpr(ctx, v.X)
-	}
-	if err := compileMember(ctx, v, v.Sel.Name, flags); err != nil {
-		panic(err)
-	}
-}
-
-func pkgRef(at *gox.PkgRef, name string) (o types.Object, alias bool) {
-	if c := name[0]; c >= 'a' && c <= 'z' {
-		name = string(rune(c)+('A'-'a')) + name[1:]
-		if v := at.TryRef(name); v != nil && gox.IsFunc(v.Type()) {
-			return v, true
-		}
-		return
-	}
-	return at.TryRef(name), false
-}
-
-func lookupPkgRef(ctx *blockCtx, pkg *gox.PkgRef, x *ast.Ident, pkgKind int) (o types.Object, alias bool) {
-	if pkg != nil {
-		return pkgRef(pkg, x.Name)
-	}
-	if pkgKind == objPkgRef {
-		for _, at := range ctx.lookups {
-			if o2, alias2 := pkgRef(at, x.Name); o2 != nil {
-				if o != nil {
-					panic(ctx.newCodeErrorf(
-						x.Pos(), "confliction: %s declared both in \"%s\" and \"%s\"",
-						x.Name, at.Types.Path(), pkg.Types.Path()))
-				}
-				pkg, o, alias = at, o2, alias2
-			}
-		}
-	} else {
-		var cpkg *cpackages.PkgRef
-		for _, at := range ctx.clookups {
-			if o2 := at.Lookup(x.Name); o2 != nil {
-				if o != nil {
-					panic(ctx.newCodeErrorf(
-						x.Pos(), "confliction: %s declared both in \"%s\" and \"%s\"",
-						x.Name, at.Pkg().Types.Path(), cpkg.Pkg().Types.Path()))
-				}
-				cpkg, o = at, o2
-			}
-		}
-	}
-	return
-}
-
-func compilePkgRef(ctx *blockCtx, at *gox.PkgRef, x *ast.Ident, flags, pkgKind int) bool {
-	if v, alias := lookupPkgRef(ctx, at, x, pkgKind); v != nil {
-		cb := ctx.cb
-		if (flags & clIdentLHS) != 0 {
-			cb.VarRef(v, x)
-		} else {
-			autoprop := alias && (flags&clIdentCanAutoCall) != 0
-			if autoprop && !gox.HasAutoProperty(v.Type()) {
-				return false
-			}
-			cb.Val(v, x)
-			if autoprop {
-				cb.Call(0)
-			}
-		}
-		return true
-	}
-	return false
-}
-
-type fnType struct {
-	next     *fnType
-	params   *types.Tuple
-	n1       int
-	variadic bool
-	typetype bool
-	inited   bool
-}
-
-func (p *fnType) arg(i int, ellipsis bool) types.Type {
-	if i < p.n1 {
-		return p.params.At(i).Type()
-	}
-	if p.variadic {
-		t := p.params.At(p.n1).Type()
-		if ellipsis {
-			return t
-		}
-		return t.(*types.Slice).Elem()
-	}
-	return nil
-}
-
-func (p *fnType) init(t *types.Signature) {
-	p.params, p.variadic = t.Params(), t.Variadic()
-	p.n1 = p.params.Len()
-	if p.variadic {
-		p.n1--
-	}
-}
-
-func (p *fnType) initTypeType(t *gox.TypeType) {
-	param := types.NewParam(0, nil, "", t.Type())
-	p.params, p.typetype = types.NewTuple(param), true
-	p.n1 = 1
-}
-
-func (p *fnType) initWith(fnt types.Type, idx, nin int) {
-	if p.inited {
-		return
-	}
-	p.inited = true
-	if t, ok := fnt.(*gox.TypeType); ok {
-		p.initTypeType(t)
-	} else if t := gox.CheckSignatures(fnt, idx, nin); t != nil {
-		p.init(t[0])
-		for i := 1; i < len(t); i++ {
-			fn := &fnType{}
-			fn.inited = true
-			fn.init(t[i])
-			p.next = fn
-			p = p.next
-		}
-	}
-}
-
-func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
-	switch fn := v.Fun.(type) {
-	case *ast.Ident:
-		compileIdent(ctx, fn, clIdentAllowBuiltin|inFlags)
-	case *ast.SelectorExpr:
-		compileSelectorExpr(ctx, fn, 0)
-	case *ast.ErrWrapExpr:
-		if v.IsCommand() {
-			callExpr := *v
-			callExpr.Fun = fn.X
-			ewExpr := *fn
-			ewExpr.X = &callExpr
-			compileErrWrapExpr(ctx, &ewExpr, inFlags)
-			return
-		}
-		compileErrWrapExpr(ctx, fn, 0)
-	default:
-		compileExpr(ctx, fn)
-	}
-	var fnt = ctx.cb.Get(-1).Type
-	var flags gox.InstrFlags
-	var ellipsis = v.Ellipsis != gotoken.NoPos
-	if ellipsis {
-		flags = gox.InstrFlagEllipsis
-	}
-	if (inFlags & clCallWithTwoValue) != 0 {
-		flags |= gox.InstrFlagTwoValue
-	}
-	var fn *fnType = &fnType{}
-	for fn != nil {
-		err := compileCallArgs(fn, fnt, ctx, v, ellipsis, flags)
-		if err == nil {
-			break
-		}
-		if fn.next == nil {
-			panic(err)
-		}
-		fn = fn.next
-	}
-}
-
-func compileCallArgs(fn *fnType, fnt types.Type, ctx *blockCtx, v *ast.CallExpr, ellipsis bool, flags gox.InstrFlags) (err error) {
-	n := ctx.cb.InternalStack().Len()
-	defer func() {
-		if v := recover(); v != nil {
-			err = v.(error)
-			ctx.cb.InternalStack().SetLen(n)
-		}
-	}()
-	for i, arg := range v.Args {
-		switch expr := arg.(type) {
-		case *ast.LambdaExpr:
-			fn.initWith(fnt, i, len(expr.Lhs))
-			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, true), clLambaArgument, v.Fun)
-			compileLambdaExpr(ctx, expr, sig)
-		case *ast.LambdaExpr2:
-			fn.initWith(fnt, i, len(expr.Lhs))
-			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, true), clLambaArgument, v.Fun)
-			compileLambdaExpr2(ctx, expr, sig)
-		case *ast.CompositeLit:
-			fn.initWith(fnt, i, -1)
-			compileCompositeLit(ctx, expr, fn.arg(i, ellipsis), true)
-		case *ast.SliceLit:
-			fn.initWith(fnt, i, -2)
-			t := fn.arg(i, ellipsis)
-			switch t.(type) {
-			case *types.Slice:
-			case *types.Named:
-				if _, ok := getUnderlying(ctx, t).(*types.Slice); !ok {
-					t = nil
-				}
-			default:
-				t = nil
-			}
-			typetype := fn.typetype && t != nil
-			if typetype {
-				ctx.cb.InternalStack().Pop()
-			}
-			compileSliceLit(ctx, expr, t)
-			if typetype {
-				return
-			}
-		default:
-			compileExpr(ctx, arg)
-		}
-	}
-	ctx.cb.CallWith(len(v.Args), flags, v)
-	return
-}
-
-type clLambaFlag string
-
-const (
-	clLambaAssign   clLambaFlag = "assignment"
-	clLambaField    clLambaFlag = "field value"
-	clLambaArgument clLambaFlag = "argument"
-)
-
-// check lambda func type
-func checkLambdaFuncType(ctx *blockCtx, lambda ast.Expr, ftyp types.Type, flag clLambaFlag, toNode ast.Node) *types.Signature {
-	typ := ftyp
-retry:
-	switch t := typ.(type) {
-	case *types.Signature:
-		if l, ok := lambda.(*ast.LambdaExpr); ok {
-			if len(l.Rhs) != t.Results().Len() {
-				break
-			}
-		}
-		return t
-	case *types.Named:
-		typ = t.Underlying()
-		goto retry
-	}
-	src, _ := ctx.LoadExpr(toNode)
-	err := ctx.newCodeErrorf(lambda.Pos(), "cannot use lambda literal as type %v in %v to %v", ftyp, flag, src)
-	panic(err)
-}
-
-func compileLambda(ctx *blockCtx, lambda ast.Expr, sig *types.Signature) {
-	switch expr := lambda.(type) {
-	case *ast.LambdaExpr:
-		compileLambdaExpr(ctx, expr, sig)
-	case *ast.LambdaExpr2:
-		compileLambdaExpr2(ctx, expr, sig)
-	}
-}
-
-func makeLambdaParams(ctx *blockCtx, pos token.Pos, lhs []*ast.Ident, in *types.Tuple) *types.Tuple {
-	pkg := ctx.pkg
-	n := len(lhs)
-	if nin := in.Len(); n != nin {
-		fewOrMany := "few"
-		if n > nin {
-			fewOrMany = "many"
-		}
-		has := make([]string, n)
-		for i, v := range lhs {
-			has[i] = v.Name
-		}
-		panic(ctx.newCodeErrorf(
-			pos, "too %s arguments in lambda expression\n\thave (%s)\n\twant %v", fewOrMany, strings.Join(has, ", "), in))
-	}
-	if n == 0 {
-		return nil
-	}
-	params := make([]*types.Var, n)
-	for i, name := range lhs {
-		params[i] = pkg.NewParam(name.Pos(), name.Name, in.At(i).Type())
-	}
-	return types.NewTuple(params...)
-}
-
-func makeLambdaResults(pkg *gox.Package, out *types.Tuple) *types.Tuple {
-	nout := out.Len()
-	if nout == 0 {
-		return nil
-	}
-	results := make([]*types.Var, nout)
-	for i := 0; i < nout; i++ {
-		results[i] = pkg.NewParam(token.NoPos, "", out.At(i).Type())
-	}
-	return types.NewTuple(results...)
-}
-
-func compileLambdaExpr(ctx *blockCtx, v *ast.LambdaExpr, sig *types.Signature) {
-	pkg := ctx.pkg
-	params := makeLambdaParams(ctx, v.Pos(), v.Lhs, sig.Params())
-	results := makeLambdaResults(pkg, sig.Results())
-	ctx.cb.NewClosure(params, results, false).BodyStart(pkg)
-	for _, v := range v.Rhs {
-		compileExpr(ctx, v)
-	}
-	ctx.cb.Return(len(v.Rhs)).End(v)
-}
-
-func compileLambdaExpr2(ctx *blockCtx, v *ast.LambdaExpr2, sig *types.Signature) {
-	pkg := ctx.pkg
-	params := makeLambdaParams(ctx, v.Pos(), v.Lhs, sig.Params())
-	results := makeLambdaResults(pkg, sig.Results())
-	fn := ctx.cb.NewClosure(params, results, false)
-
-	comments, once := ctx.cb.BackupComments()
-	loadFuncBody(ctx, fn, v.Body, v)
-	ctx.cb.SetComments(comments, once)
-}
-
-func compileFuncLit(ctx *blockCtx, v *ast.FuncLit) {
-	cb := ctx.cb
-	sig := toFuncType(ctx, v.Type, nil, nil)
-	fn := cb.NewClosureWith(sig)
-	if body := v.Body; body != nil {
-		// TODO: delay load closure body
-		// ctx.bodys = append(ctx.bodys, func() {
-		comments, once := cb.BackupComments()
-		loadFuncBody(ctx, fn, body, v)
-		cb.SetComments(comments, once)
-		// })
-	}
-}
-
-func compileBasicLit(ctx *blockCtx, v *ast.BasicLit) {
-	cb := ctx.cb
-	switch v.Kind {
-	case token.RAT:
-		val := v.Value
-		bi, _ := new(big.Int).SetString(val[:len(val)-1], 10) // remove r suffix
-		cb.UntypedBigInt(bi, v)
-	case token.CSTRING:
-		s, err := strconv.Unquote(v.Value)
-		if err != nil {
-			log.Panicln("compileBasicLit:", err)
-		}
-		n := len(s)
-		tyInt8 := types.Typ[types.Int8]
-		typ := types.NewArray(tyInt8, int64(n+1))
-		cb.Typ(types.NewPointer(tyInt8)).Typ(types.Typ[types.UnsafePointer])
-		for i := 0; i < n; i++ {
-			cb.Val(rune(s[i]))
-		}
-		cb.Val(rune(0)).ArrayLit(typ, n+1).UnaryOp(gotoken.AND).Call(1).Call(1)
-	default:
-		cb.Val(&goast.BasicLit{Kind: gotoken.Token(v.Kind), Value: v.Value}, v)
-	}
-}
-
-const (
-	compositeLitVal    = 0
-	compositeLitKeyVal = 1
-)
-
-func checkCompositeLitElts(ctx *blockCtx, elts []ast.Expr, onlyStruct bool) (kind int) {
-	for _, elt := range elts {
-		if _, ok := elt.(*ast.KeyValueExpr); ok {
-			return compositeLitKeyVal
-		}
-	}
-	if len(elts) == 0 && onlyStruct {
-		return compositeLitKeyVal
-	}
-	return compositeLitVal
-}
-
-func compileCompositeLitElts(ctx *blockCtx, elts []ast.Expr, kind int, expected *kvType) {
-	for _, elt := range elts {
-		if kv, ok := elt.(*ast.KeyValueExpr); ok {
-			if key, ok := kv.Key.(*ast.CompositeLit); ok && key.Type == nil {
-				compileCompositeLit(ctx, key, expected.Key(), false)
-			} else {
-				compileExpr(ctx, kv.Key)
-			}
-			if val, ok := kv.Value.(*ast.CompositeLit); ok && val.Type == nil {
-				compileCompositeLit(ctx, val, expected.Elem(), false)
-			} else {
-				compileExpr(ctx, kv.Value)
-			}
-		} else {
-			if kind == compositeLitKeyVal {
-				ctx.cb.None()
-			}
-			if val, ok := elt.(*ast.CompositeLit); ok && val.Type == nil {
-				compileCompositeLit(ctx, val, expected.Elem(), false)
-			} else {
-				compileExpr(ctx, elt)
-			}
-		}
-	}
-}
-
-func compileStructLitInKeyVal(ctx *blockCtx, elts []ast.Expr, t *types.Struct, typ types.Type, src *ast.CompositeLit) {
-	for _, elt := range elts {
-		kv := elt.(*ast.KeyValueExpr)
-		name := kv.Key.(*ast.Ident)
-		idx := lookupField(t, name.Name)
-		if idx >= 0 {
-			ctx.cb.Val(idx)
-		} else {
-			src, pos := ctx.LoadExpr(name)
-			err := newCodeErrorf(&pos, "%s undefined (type %v has no field or method %s)", src, typ, name.Name)
-			panic(err)
-		}
-		switch expr := kv.Value.(type) {
-		case *ast.LambdaExpr, *ast.LambdaExpr2:
-			sig := checkLambdaFuncType(ctx, expr, t.Field(idx).Type(), clLambaField, kv.Key)
-			compileLambda(ctx, expr, sig)
-		default:
-			compileExpr(ctx, kv.Value)
-		}
-	}
-	ctx.cb.StructLit(typ, len(elts)<<1, true, src)
-}
-
-func lookupField(t *types.Struct, name string) int {
-	for i, n := 0, t.NumFields(); i < n; i++ {
-		if fld := t.Field(i); fld.Name() == name {
-			return i
-		}
-	}
-	return -1
-}
-
-type kvType struct {
-	underlying types.Type
-	key, val   types.Type
-	cached     bool
-}
-
-func (p *kvType) required() *kvType {
-	if !p.cached {
-		p.cached = true
-		switch t := p.underlying.(type) {
-		case *types.Slice:
-			p.key, p.val = types.Typ[types.Int], t.Elem()
-		case *types.Array:
-			p.key, p.val = types.Typ[types.Int], t.Elem()
-		case *types.Map:
-			p.key, p.val = t.Key(), t.Elem()
-		}
-	}
-	return p
-}
-
-func (p *kvType) Key() types.Type {
-	return p.required().key
-}
-
-func (p *kvType) Elem() types.Type {
-	return p.required().val
-}
-
-func compileCompositeLit(ctx *blockCtx, v *ast.CompositeLit, expected types.Type, onlyStruct bool) {
-	var hasPtr bool
-	var typ, underlying types.Type
-	var kind = checkCompositeLitElts(ctx, v.Elts, onlyStruct)
-	if v.Type != nil {
-		typ = toType(ctx, v.Type)
-		underlying = getUnderlying(ctx, typ)
-	} else if expected != nil {
-		if t, ok := expected.(*types.Pointer); ok {
-			expected, hasPtr = t.Elem(), true
-		}
-		if onlyStruct {
-			if kind == compositeLitKeyVal {
-				t := getUnderlying(ctx, expected)
-				if _, ok := t.(*types.Struct); ok { // can't omit non-struct type
-					typ, underlying = expected, t
-				}
-			}
-		} else {
-			typ, underlying = expected, getUnderlying(ctx, expected)
-		}
-	}
-	if t, ok := underlying.(*types.Struct); ok && kind == compositeLitKeyVal {
-		compileStructLitInKeyVal(ctx, v.Elts, t, typ, v)
-		if hasPtr {
-			ctx.cb.UnaryOp(gotoken.AND)
-		}
-		return
-	}
-	compileCompositeLitElts(ctx, v.Elts, kind, &kvType{underlying: underlying})
-	n := len(v.Elts)
-	if typ == nil {
-		if kind == compositeLitVal && n > 0 {
-			panic("TODO: mapLit should be in {key: val, ...} form")
-		}
-		ctx.cb.MapLit(nil, n<<1)
-		return
-	}
-	switch underlying.(type) {
-	case *types.Slice:
-		ctx.cb.SliceLitEx(typ, n<<kind, kind == compositeLitKeyVal, v)
-	case *types.Array:
-		ctx.cb.ArrayLitEx(typ, n<<kind, kind == compositeLitKeyVal, v)
-	case *types.Map:
-		ctx.cb.MapLit(typ, n<<1, v)
-	case *types.Struct:
-		ctx.cb.StructLit(typ, n, false, v)
-	default:
-		log.Panicln("compileCompositeLit: unknown type -", reflect.TypeOf(underlying))
-	}
-	if hasPtr {
-		ctx.cb.UnaryOp(gotoken.AND)
-	}
-}
-
-func compileSliceLit(ctx *blockCtx, v *ast.SliceLit, typ types.Type) {
-	n := len(v.Elts)
-	for _, elt := range v.Elts {
-		compileExpr(ctx, elt)
-	}
-	if sliceHasTypeParam(ctx, typ) {
-		ctx.cb.SliceLitEx(nil, n, false, v)
-	} else {
-		ctx.cb.SliceLitEx(typ, n, false, v)
-	}
-}
-
-func compileRangeExpr(ctx *blockCtx, v *ast.RangeExpr) {
-	pkg, cb := ctx.pkg, ctx.cb
-	cb.Val(pkg.Builtin().Ref("newRange"))
-	if v.First == nil {
-		ctx.cb.Val(0, v)
-	} else {
-		compileExpr(ctx, v.First)
-	}
-	compileExpr(ctx, v.Last)
-	if v.Expr3 == nil {
-		ctx.cb.Val(1, v)
-	} else {
-		compileExpr(ctx, v.Expr3)
-	}
-	cb.Call(3)
-}
-
-const (
-	comprehensionInvalid = iota
-	comprehensionList
-	comprehensionMap
-	comprehensionSelect
-)
-
-func comprehensionKind(v *ast.ComprehensionExpr) int {
-	switch v.Tok {
-	case token.LBRACK: // [
-		return comprehensionList
-	case token.LBRACE: // {
-		if _, ok := v.Elt.(*ast.KeyValueExpr); ok {
-			return comprehensionMap
-		}
-		return comprehensionSelect
-	}
-	panic("TODO: invalid comprehensionExpr")
-}
-
-// [expr for k, v <- container, cond]
-// {for k, v <- container, cond}
-// {expr for k, v <- container, cond}
-// {kexpr: vexpr for k, v <- container, cond}
-func compileComprehensionExpr(ctx *blockCtx, v *ast.ComprehensionExpr, twoValue bool) {
-	kind := comprehensionKind(v)
-	pkg, cb := ctx.pkg, ctx.cb
-	var results *types.Tuple
-	var ret *gox.Param
-	if v.Elt == nil {
-		boolean := pkg.NewParam(token.NoPos, "_gop_ok", types.Typ[types.Bool])
-		results = types.NewTuple(boolean)
-	} else {
-		ret = pkg.NewAutoParam("_gop_ret")
-		if kind == comprehensionSelect && twoValue {
-			boolean := pkg.NewParam(token.NoPos, "_gop_ok", types.Typ[types.Bool])
-			results = types.NewTuple(ret, boolean)
-		} else {
-			results = types.NewTuple(ret)
-		}
-	}
-	cb.NewClosure(nil, results, false).BodyStart(pkg)
-	if kind == comprehensionMap {
-		cb.VarRef(ret).ZeroLit(ret.Type()).Assign(1)
-	}
-	end := 0
-	for i := len(v.Fors) - 1; i >= 0; i-- {
-		names := make([]string, 0, 2)
-		forStmt := v.Fors[i]
-		if forStmt.Key != nil {
-			names = append(names, forStmt.Key.Name)
-		} else {
-			names = append(names, "_")
-		}
-		names = append(names, forStmt.Value.Name)
-		cb.ForRange(names...)
-		compileExpr(ctx, forStmt.X)
-		cb.RangeAssignThen(forStmt.TokPos)
-		if forStmt.Cond != nil {
-			cb.If()
-			if forStmt.Init != nil {
-				compileStmt(ctx, forStmt.Init)
-			}
-			compileExpr(ctx, forStmt.Cond)
-			cb.Then()
-			end++
-		}
-		end++
-	}
-	switch kind {
-	case comprehensionList:
-		// _gop_ret = append(_gop_ret, elt)
-		cb.VarRef(ret)
-		cb.Val(pkg.Builtin().Ref("append"))
-		cb.Val(ret)
-		compileExpr(ctx, v.Elt)
-		cb.Call(2).Assign(1)
-	case comprehensionMap:
-		// _gop_ret[key] = val
-		cb.Val(ret)
-		kv := v.Elt.(*ast.KeyValueExpr)
-		compileExpr(ctx, kv.Key)
-		cb.IndexRef(1)
-		compileExpr(ctx, kv.Value)
-		cb.Assign(1)
-	default:
-		if v.Elt == nil {
-			// return true
-			cb.Val(true)
-			cb.Return(1)
-		} else {
-			// return elt, true
-			compileExpr(ctx, v.Elt)
-			n := 1
-			if twoValue {
-				cb.Val(true)
-				n++
-			}
-			cb.Return(n)
-		}
-	}
-	for i := 0; i < end; i++ {
-		cb.End()
-	}
-	cb.Return(0).End().Call(0)
-}
-
-var (
-	tyError = types.Universe.Lookup("error").Type()
-)
-
-func compileErrWrapExpr(ctx *blockCtx, v *ast.ErrWrapExpr, inFlags int) {
-	pkg, cb := ctx.pkg, ctx.cb
-	useClosure := v.Tok == token.NOT || v.Default != nil
-	if !useClosure && (cb.Scope().Parent() == types.Universe) {
-		panic("TODO: can't use expr? in global")
-	}
-
-	compileExpr(ctx, v.X, inFlags)
-	x := cb.InternalStack().Pop()
-	n := 0
-	results, ok := x.Type.(*types.Tuple)
-	if ok {
-		n = results.Len() - 1
-	}
-
-	var ret []*types.Var
-	if n > 0 {
-		i, retName := 0, "_gop_ret"
-		ret = make([]*gox.Param, n)
-		for {
-			ret[i] = pkg.NewAutoParam(retName)
-			i++
-			if i >= n {
-				break
-			}
-			retName = "_gop_ret" + strconv.Itoa(i+1)
-		}
-	}
-	sig := types.NewSignature(nil, nil, types.NewTuple(ret...), false)
-	if useClosure {
-		cb.NewClosureWith(sig).BodyStart(pkg)
-	} else {
-		cb.CallInlineClosureStart(sig, 0, false)
-	}
-
-	cb.NewVar(tyError, "_gop_err")
-	err := cb.Scope().Lookup("_gop_err")
-
-	for _, retVar := range ret {
-		cb.VarRef(retVar)
-	}
-	cb.VarRef(err)
-	cb.InternalStack().Push(x)
-	cb.Assign(n+1, 1)
-
-	cb.If().Val(err).CompareNil(gotoken.NEQ).Then()
-	if v.Default == nil {
-		pos := pkg.Fset.Position(v.Pos())
-		currentFunc := ctx.cb.Func().Ancestor()
-		const newFrameArgs = 5
-
-		currentFuncName := currentFunc.Name()
-		if currentFuncName == "" {
-			currentFuncName = "main"
-		}
-
-		currentFuncName = strings.Join([]string{currentFunc.Pkg().Name(), currentFuncName}, ".")
-
-		cb.
-			VarRef(err).
-			Val(pkg.Import(errorPkgPath).Ref("NewFrame")).
-			Val(err).
-			Val(sprintAst(pkg.Fset, v.X)).
-			Val(pos.Filename).
-			Val(pos.Line).
-			Val(currentFuncName).
-			Call(newFrameArgs).
-			Assign(1)
-	}
-
-	if v.Tok == token.NOT { // expr!
-		cb.Val(pkg.Builtin().Ref("panic")).Val(err).Call(1).EndStmt()
-	} else if v.Default == nil { // expr?
-		cb.Val(err).ReturnErr(true)
-	} else { // expr?:val
-		compileExpr(ctx, v.Default)
-		cb.Return(1)
-	}
-	cb.End().Return(0).End()
-	if useClosure {
-		cb.Call(0)
-	}
-}
-
-func sprintAst(fset *token.FileSet, x ast.Node) string {
-	var buf bytes.Buffer
-	err := printer.Fprint(&buf, fset, x)
-	if err != nil {
-		panic("Unexpected error: " + err.Error())
-	}
-
-	return buf.String()
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/func_type_and_var.go b/cl/outline/cl/func_type_and_var.go
deleted file mode 100644
index 9a412d49..00000000
--- a/cl/outline/cl/func_type_and_var.go
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"go/constant"
-	"go/types"
-	"log"
-	"math/big"
-	"reflect"
-	"strconv"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-)
-
-// -----------------------------------------------------------------------------
-
-func toRecv(ctx *blockCtx, recv *ast.FieldList) (ret *types.Var, ok bool) {
-	v := recv.List[0]
-	var name string
-	if len(v.Names) > 0 {
-		name = v.Names[0].Name
-	}
-	t := toType(ctx, v.Type)
-	if ok = checkRecvType(ctx, t, v.Type); ok {
-		ret = ctx.pkg.NewParam(v.Pos(), name, t)
-	}
-	return
-}
-
-func checkRecvType(ctx *blockCtx, typ types.Type, recv ast.Expr) (ok bool) {
-	t := indirect(typ)
-	if _, ok = t.(*types.Named); !ok {
-		pos := ctx.Position(recv.Pos())
-		ctx.handleCodeErrorf(&pos, "invalid receiver type %v", typ)
-	}
-	return
-}
-
-func indirect(typ types.Type) types.Type {
-	if t, ok := typ.(*types.Pointer); ok {
-		return t.Elem()
-	}
-	return typ
-}
-
-func toResults(ctx *blockCtx, in *ast.FieldList) *types.Tuple {
-	if in == nil {
-		return nil
-	}
-	flds := in.List
-	n := len(flds)
-	args := make([]*types.Var, 0, n)
-	for _, fld := range flds {
-		args = toParam(ctx, fld, args)
-	}
-	return types.NewTuple(args...)
-}
-
-func toParams(ctx *blockCtx, flds []*ast.Field) (typ *types.Tuple, variadic bool) {
-	n := len(flds)
-	if n == 0 {
-		return nil, false
-	}
-	args := make([]*types.Var, 0, n)
-	for _, fld := range flds {
-		args = toParam(ctx, fld, args)
-	}
-	_, ok := flds[n-1].Type.(*ast.Ellipsis)
-	return types.NewTuple(args...), ok
-}
-
-func toParam(ctx *blockCtx, fld *ast.Field, args []*gox.Param) []*gox.Param {
-	typ := toType(ctx, fld.Type)
-	pkg := ctx.pkg
-	if len(fld.Names) == 0 {
-		return append(args, pkg.NewParam(fld.Pos(), "", typ))
-	}
-	for _, name := range fld.Names {
-		args = append(args, pkg.NewParam(name.Pos(), name.Name, typ))
-	}
-	return args
-}
-
-// -----------------------------------------------------------------------------
-
-func toTypeInited(ctx *blockCtx, typ ast.Expr) types.Type {
-	t := toType(ctx, typ)
-	if named, ok := t.(*types.Named); ok {
-		ctx.ensureLoaded(named)
-	}
-	return t
-}
-
-func toType(ctx *blockCtx, typ ast.Expr) types.Type {
-	switch v := typ.(type) {
-	case *ast.Ident:
-		/*
-			ctx.idents = append(ctx.idents, v)
-			defer func() {
-				ctx.idents = ctx.idents[:len(ctx.idents)-1]
-			}()
-		*/
-		typ := toIdentType(ctx, v)
-		/*
-			if ctx.inInst == 0 {
-				if t, ok := typ.(*types.Named); ok {
-					if withTypeParams(ctx, t) {
-						pos := ctx.idents[0].Pos()
-						for _, i := range ctx.idents {
-							if i.Name == v.Name {
-								pos = i.Pos()
-								break
-							}
-						}
-						panic(ctx.newCodeErrorf(pos, "cannot use generic type %v without instantiation", t.Obj().Type()))
-					}
-				}
-			}
-		*/
-		return typ
-	case *ast.StarExpr:
-		elem := toType(ctx, v.X)
-		return types.NewPointer(elem)
-	case *ast.ArrayType:
-		return toArrayType(ctx, v)
-	case *ast.InterfaceType:
-		return toInterfaceType(ctx, v)
-	case *ast.Ellipsis:
-		elem := toType(ctx, v.Elt)
-		return types.NewSlice(elem)
-	case *ast.MapType:
-		return toMapType(ctx, v)
-	case *ast.StructType:
-		return toStructType(ctx, v)
-	case *ast.ChanType:
-		return toChanType(ctx, v)
-	case *ast.FuncType:
-		return toFuncType(ctx, v, nil, nil)
-	case *ast.SelectorExpr:
-		typ := toExternalType(ctx, v)
-		if ctx.inInst == 0 {
-			if t, ok := typ.(*types.Named); ok {
-				if withTypeParams(ctx, t) {
-					panic(ctx.newCodeErrorf(v.Pos(), "cannot use generic type %v without instantiation", t.Obj().Type()))
-				}
-			}
-		}
-		return typ
-	case *ast.ParenExpr:
-		return toType(ctx, v.X)
-	case *ast.BinaryExpr:
-		return toBinaryExprType(ctx, v)
-	case *ast.UnaryExpr:
-		return toUnaryExprType(ctx, v)
-	case *ast.IndexExpr:
-		return toIndexType(ctx, v)
-	case *ast.IndexListExpr:
-		return toIndexListType(ctx, v)
-	}
-	log.Panicln("toType: unknown -", reflect.TypeOf(typ))
-	return nil
-}
-
-var (
-	typesChanDirs = [...]types.ChanDir{
-		ast.RECV:            types.RecvOnly,
-		ast.SEND:            types.SendOnly,
-		ast.SEND | ast.RECV: types.SendRecv,
-	}
-)
-
-func toChanType(ctx *blockCtx, v *ast.ChanType) *types.Chan {
-	return types.NewChan(typesChanDirs[v.Dir], toType(ctx, v.Value))
-}
-
-func toExternalType(ctx *blockCtx, v *ast.SelectorExpr) types.Type {
-	name := v.X.(*ast.Ident).Name
-	if pr, ok := ctx.findImport(name); ok {
-		o := pr.TryRef(v.Sel.Name)
-		if t, ok := o.(*types.TypeName); ok {
-			return t.Type()
-		}
-		panic(ctx.newCodeErrorf(v.Pos(), "%s.%s is not a type", name, v.Sel.Name))
-	}
-	panic(ctx.newCodeErrorf(v.Pos(), "undefined: %s", name))
-}
-
-/*-----------------------------------------------------------------------------
-
-Name context:
-- type
-- pkgRef.type
-- spx.type
-
-// ---------------------------------------------------------------------------*/
-
-func toIdentType(ctx *blockCtx, ident *ast.Ident) types.Type {
-	if ctx.tlookup != nil {
-		if typ := ctx.tlookup.Lookup(ident.Name); typ != nil {
-			return typ
-		}
-	}
-	v, builtin := lookupType(ctx, ident.Name)
-	if isBuiltin(builtin) {
-		panic(ctx.newCodeErrorf(ident.Pos(), "use of builtin %s not in function call", ident.Name))
-	}
-	if t, ok := v.(*types.TypeName); ok {
-		return t.Type()
-	}
-	if v, _ := lookupPkgRef(ctx, nil, ident, objPkgRef); v != nil {
-		if t, ok := v.(*types.TypeName); ok {
-			return t.Type()
-		}
-	}
-	panic(ctx.newCodeErrorf(ident.Pos(), "%s is not a type", ident.Name))
-}
-
-func lookupType(ctx *blockCtx, name string) (obj types.Object, builtin types.Object) {
-	at, o := ctx.cb.Scope().LookupParent(name, token.NoPos)
-	if o != nil {
-		if at != types.Universe {
-			if debugLookup {
-				log.Println("==> LookupParent", name, "=>", o)
-			}
-			return o, nil
-		}
-	}
-	if obj := ctx.pkg.Builtin().TryRef(name); obj != nil {
-		return obj, o
-	}
-	return o, o
-}
-
-type checkRedecl struct {
-	// ctx *blockCtx
-	names map[string]token.Pos
-}
-
-func newCheckRedecl() *checkRedecl {
-	p := &checkRedecl{names: make(map[string]token.Pos)}
-	return p
-}
-
-func (p *checkRedecl) chkRedecl(ctx *blockCtx, name string, pos token.Pos) bool {
-	if name == "_" {
-		return false
-	}
-	if opos, ok := p.names[name]; ok {
-		npos := ctx.Position(pos)
-		ctx.handleCodeErrorf(&npos, "%v redeclared\n\t%v other declaration of %v",
-			name, ctx.Position(opos), name)
-		return true
-	}
-	p.names[name] = pos
-	return false
-}
-
-func toStructType(ctx *blockCtx, v *ast.StructType) *types.Struct {
-	pkg := ctx.pkg.Types
-	fieldList := v.Fields.List
-	fields := make([]*types.Var, 0, len(fieldList))
-	tags := make([]string, 0, len(fieldList))
-	chk := newCheckRedecl()
-	for _, field := range fieldList {
-		typ := toTypeInited(ctx, field.Type)
-		if len(field.Names) == 0 { // embedded
-			name := getTypeName(typ)
-			if chk.chkRedecl(ctx, name, field.Type.Pos()) {
-				continue
-			}
-			fld := types.NewField(field.Type.Pos(), pkg, name, typ, true)
-			fields = append(fields, fld)
-			tags = append(tags, toFieldTag(field.Tag))
-			continue
-		}
-		for _, name := range field.Names {
-			if chk.chkRedecl(ctx, name.Name, name.NamePos) {
-				continue
-			}
-			fld := types.NewField(name.Pos(), pkg, name.Name, typ, false)
-			fields = append(fields, fld)
-			tags = append(tags, toFieldTag(field.Tag))
-		}
-	}
-	return types.NewStruct(fields, tags)
-}
-
-func toFieldTag(v *ast.BasicLit) string {
-	if v != nil {
-		tag, err := strconv.Unquote(v.Value)
-		if err != nil {
-			log.Panicln("TODO: toFieldTag -", err)
-		}
-		return tag
-	}
-	return ""
-}
-
-func getTypeName(typ types.Type) string {
-	if t, ok := typ.(*types.Pointer); ok {
-		typ = t.Elem()
-	}
-	switch t := typ.(type) {
-	case *types.Named:
-		return t.Obj().Name()
-	case *types.Basic:
-		return t.Name()
-	default:
-		panic("TODO: getTypeName")
-	}
-}
-
-func toMapType(ctx *blockCtx, v *ast.MapType) *types.Map {
-	key := toType(ctx, v.Key)
-	val := toType(ctx, v.Value)
-	return types.NewMap(key, val)
-}
-
-func toArrayType(ctx *blockCtx, v *ast.ArrayType) types.Type {
-	elem := toType(ctx, v.Elt)
-	if v.Len == nil {
-		return types.NewSlice(elem)
-	}
-	if _, ok := v.Len.(*ast.Ellipsis); ok {
-		return types.NewArray(elem, -1) // A negative length indicates an unknown length
-	}
-	return types.NewArray(elem, toInt64(ctx, v.Len, "non-constant array bound %s"))
-}
-
-func toInt64(ctx *blockCtx, e ast.Expr, emsg string) int64 {
-	cb := ctx.pkg.ConstStart()
-	compileExpr(ctx, e)
-	tv := cb.EndConst()
-	if val := tv.CVal; val != nil {
-		if val.Kind() == constant.Float {
-			if v, ok := constant.Val(val).(*big.Rat); ok && v.IsInt() {
-				return v.Num().Int64()
-			}
-		} else if v, ok := constant.Int64Val(val); ok {
-			return v
-		}
-	}
-	src, pos := ctx.LoadExpr(e)
-	panic(newCodeErrorf(&pos, emsg, src))
-}
-
-func toInterfaceType(ctx *blockCtx, v *ast.InterfaceType) *types.Interface {
-	methodsList := v.Methods.List
-	if methodsList == nil {
-		return gox.TyEmptyInterface
-	}
-	var pkg = ctx.pkg.Types
-	var methods []*types.Func
-	var embeddeds []types.Type
-	for _, m := range methodsList {
-		if len(m.Names) == 0 { // embedded
-			typ := toTypeInited(ctx, m.Type)
-			embeddeds = append(embeddeds, typ)
-			continue
-		}
-		name := m.Names[0].Name
-		sig := toFuncType(ctx, m.Type.(*ast.FuncType), nil, nil)
-		methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
-	}
-	intf := types.NewInterfaceType(methods, embeddeds).Complete()
-	return intf
-}
-
-func toIndexType(ctx *blockCtx, v *ast.IndexExpr) types.Type {
-	ctx.inInst++
-	defer func() {
-		ctx.inInst--
-	}()
-	ctx.cb.Typ(toTypeInited(ctx, v.X), v.X)
-	ctx.cb.Typ(toTypeInited(ctx, v.Index), v.Index)
-	ctx.cb.Index(1, false, v)
-	return ctx.cb.InternalStack().Pop().Type.(*gox.TypeType).Type()
-}
-
-func toIndexListType(ctx *blockCtx, v *ast.IndexListExpr) types.Type {
-	ctx.inInst++
-	defer func() {
-		ctx.inInst--
-	}()
-	ctx.cb.Typ(toTypeInited(ctx, v.X), v.X)
-	for _, index := range v.Indices {
-		ctx.cb.Typ(toTypeInited(ctx, index), index)
-	}
-	ctx.cb.Index(len(v.Indices), false, v)
-	return ctx.cb.InternalStack().Pop().Type.(*gox.TypeType).Type()
-}
-
-// -----------------------------------------------------------------------------
-
-func toString(l *ast.BasicLit) string {
-	if l.Kind == token.STRING {
-		s, err := strconv.Unquote(l.Value)
-		if err == nil {
-			return s
-		}
-	}
-	panic("TODO: toString - convert ast.BasicLit to string failed")
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/stmt.go b/cl/outline/cl/stmt.go
deleted file mode 100644
index c59eee93..00000000
--- a/cl/outline/cl/stmt.go
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"fmt"
-	"go/constant"
-	"log"
-	"path/filepath"
-	"reflect"
-
-	goast "go/ast"
-	gotoken "go/token"
-	"go/types"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-)
-
-func relFile(dir string, file string) string {
-	if rel, err := filepath.Rel(dir, file); err == nil {
-		if rel[0] == '.' {
-			return rel
-		}
-		return "./" + rel
-	}
-	return file
-}
-
-func commentStmt(ctx *blockCtx, stmt ast.Stmt) {
-	if ctx.fileLine {
-		start := stmt.Pos()
-		pos := ctx.fset.Position(start)
-		if ctx.relativePath {
-			pos.Filename = relFile(ctx.targetDir, pos.Filename)
-		}
-		line := fmt.Sprintf("\n//line %s:%d", pos.Filename, pos.Line)
-		comments := &goast.CommentGroup{
-			List: []*goast.Comment{{Text: line}},
-		}
-		ctx.cb.SetComments(comments, false)
-	}
-}
-
-func compileStmts(ctx *blockCtx, body []ast.Stmt) {
-	for _, stmt := range body {
-		if v, ok := stmt.(*ast.LabeledStmt); ok {
-			expr := v.Label
-			ctx.cb.NewLabel(expr.Pos(), expr.Name)
-		}
-	}
-	for _, stmt := range body {
-		compileStmt(ctx, stmt)
-	}
-}
-
-func compileStmt(ctx *blockCtx, stmt ast.Stmt) {
-	if enableRecover {
-		defer func() {
-			if e := recover(); e != nil {
-				ctx.handleRecover(e)
-				ctx.cb.ResetStmt()
-			}
-		}()
-	}
-	commentStmt(ctx, stmt)
-	switch v := stmt.(type) {
-	case *ast.ExprStmt:
-		inFlags := 0
-		if isCommandWithoutArgs(v.X) {
-			inFlags = clCommandWithoutArgs
-		}
-		compileExpr(ctx, v.X, inFlags)
-		if inFlags != 0 && gox.IsFunc(ctx.cb.InternalStack().Get(-1).Type) {
-			ctx.cb.Call(0)
-		}
-	case *ast.AssignStmt:
-		compileAssignStmt(ctx, v)
-	case *ast.ReturnStmt:
-		compileReturnStmt(ctx, v)
-	case *ast.IfStmt:
-		compileIfStmt(ctx, v)
-	case *ast.SwitchStmt:
-		compileSwitchStmt(ctx, v)
-	case *ast.RangeStmt:
-		compileRangeStmt(ctx, v)
-	case *ast.ForStmt:
-		compileForStmt(ctx, v)
-	case *ast.ForPhraseStmt:
-		compileForPhraseStmt(ctx, v)
-	case *ast.IncDecStmt:
-		compileIncDecStmt(ctx, v)
-	case *ast.DeferStmt:
-		compileDeferStmt(ctx, v)
-	case *ast.GoStmt:
-		compileGoStmt(ctx, v)
-	case *ast.DeclStmt:
-		compileDeclStmt(ctx, v)
-	case *ast.TypeSwitchStmt:
-		compileTypeSwitchStmt(ctx, v)
-	case *ast.SendStmt:
-		compileSendStmt(ctx, v)
-	case *ast.BranchStmt:
-		compileBranchStmt(ctx, v)
-	case *ast.LabeledStmt:
-		compileLabeledStmt(ctx, v)
-	case *ast.BlockStmt:
-		ctx.cb.Block()
-		compileStmts(ctx, v.List)
-		ctx.cb.End()
-		return
-	case *ast.SelectStmt:
-		compileSelectStmt(ctx, v)
-	case *ast.EmptyStmt:
-		// do nothing
-	default:
-		log.Panicln("TODO - compileStmt failed: unknown -", reflect.TypeOf(v))
-	}
-	ctx.cb.EndStmt()
-}
-
-func isCommandWithoutArgs(x ast.Expr) bool {
-retry:
-	switch t := x.(type) {
-	case *ast.Ident:
-		return true
-	case *ast.SelectorExpr:
-		x = t.X
-		goto retry
-	}
-	return false
-}
-
-func compileReturnStmt(ctx *blockCtx, expr *ast.ReturnStmt) {
-	var n = -1
-	var results *types.Tuple
-	for i, ret := range expr.Results {
-		if c, ok := ret.(*ast.CompositeLit); ok && c.Type == nil {
-			if n < 0 {
-				results = ctx.cb.Func().Type().(*types.Signature).Results()
-				n = results.Len()
-			}
-			var typ types.Type
-			if i < n {
-				typ = results.At(i).Type()
-			}
-			compileCompositeLit(ctx, c, typ, true)
-		} else {
-			inFlags := 0
-			if len(expr.Results) == 1 {
-				if _, ok := ret.(*ast.ComprehensionExpr); ok {
-					results = ctx.cb.Func().Type().(*types.Signature).Results()
-					if results.Len() == 2 {
-						inFlags = clCallWithTwoValue
-					}
-				}
-			}
-			switch v := ret.(type) {
-			case *ast.LambdaExpr, *ast.LambdaExpr2:
-				rtyp := ctx.cb.Func().Type().(*types.Signature).Results().At(i).Type()
-				sig, ok := rtyp.(*types.Signature)
-				if !ok {
-					panic(ctx.newCodeErrorf(
-						ret.Pos(), "cannot use lambda expression as type %v in return statement", rtyp))
-				}
-				compileLambda(ctx, v, sig)
-			default:
-				compileExpr(ctx, ret, inFlags)
-			}
-		}
-	}
-	ctx.cb.Return(len(expr.Results), expr)
-}
-
-func compileIncDecStmt(ctx *blockCtx, expr *ast.IncDecStmt) {
-	compileExprLHS(ctx, expr.X)
-	ctx.cb.IncDec(gotoken.Token(expr.Tok))
-}
-
-func compileSendStmt(ctx *blockCtx, expr *ast.SendStmt) {
-	compileExpr(ctx, expr.Chan)
-	compileExpr(ctx, expr.Value)
-	ctx.cb.Send()
-}
-
-func compileAssignStmt(ctx *blockCtx, expr *ast.AssignStmt) {
-	tok := expr.Tok
-	inFlags := 0
-	if len(expr.Lhs) == 2 && len(expr.Rhs) == 1 {
-		inFlags = clCallWithTwoValue
-	}
-	if tok == token.DEFINE {
-		names := make([]string, len(expr.Lhs))
-		for i, lhs := range expr.Lhs {
-			if v, ok := lhs.(*ast.Ident); ok {
-				names[i] = v.Name
-			} else {
-				log.Panicln("TODO: non-name $v on left side of :=")
-			}
-		}
-		ctx.cb.DefineVarStart(expr.Pos(), names...)
-		if enableRecover {
-			defer func() {
-				if e := recover(); e != nil {
-					ctx.cb.ResetInit()
-					panic(e)
-				}
-			}()
-		}
-		for _, rhs := range expr.Rhs {
-			compileExpr(ctx, rhs, inFlags)
-		}
-		ctx.cb.EndInit(len(expr.Rhs))
-		return
-	}
-	for _, lhs := range expr.Lhs {
-		compileExprLHS(ctx, lhs)
-	}
-	for _, rhs := range expr.Rhs {
-		switch e := rhs.(type) {
-		case *ast.LambdaExpr, *ast.LambdaExpr2:
-			if len(expr.Lhs) == 1 && len(expr.Rhs) == 1 {
-				typ := ctx.cb.Get(-1).Type.(interface{ Elem() types.Type }).Elem()
-				sig := checkLambdaFuncType(ctx, e, typ, clLambaAssign, expr.Lhs[0])
-				compileLambda(ctx, e, sig)
-			} else {
-				panic(ctx.newCodeErrorf(e.Pos(), "lambda unsupport multiple assignment"))
-			}
-		default:
-			compileExpr(ctx, rhs, inFlags)
-		}
-	}
-	if tok == token.ASSIGN {
-		ctx.cb.AssignWith(len(expr.Lhs), len(expr.Rhs), expr)
-		return
-	}
-	if len(expr.Lhs) != 1 || len(expr.Rhs) != 1 {
-		panic("TODO: invalid syntax of assign by operator")
-	}
-	ctx.cb.AssignOp(gotoken.Token(tok), expr)
-}
-
-// forRange(names...) x rangeAssignThen
-//
-//	body
-//
-// end
-// forRange k v x rangeAssignThen
-//
-//	body
-//
-// end
-func compileRangeStmt(ctx *blockCtx, v *ast.RangeStmt) {
-	if re, ok := v.X.(*ast.RangeExpr); ok {
-		tok := token.DEFINE
-		if v.Tok == token.ASSIGN {
-			tok = v.Tok
-		}
-		compileForStmt(ctx, toForStmt(v.For, v.Key, v.Body, re, tok, nil))
-		return
-	}
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	if v.Tok == token.DEFINE {
-		names := make([]string, 1, 2)
-		if v.Key == nil {
-			names[0] = "_"
-		} else {
-			names[0] = v.Key.(*ast.Ident).Name
-		}
-		if v.Value != nil {
-			names = append(names, v.Value.(*ast.Ident).Name)
-		}
-		cb.ForRange(names...)
-		compileExpr(ctx, v.X)
-	} else {
-		cb.ForRange()
-		n := 0
-		if v.Key == nil {
-			if v.Value != nil {
-				ctx.cb.VarRef(nil) // underscore
-				n++
-			}
-		} else {
-			compileExprLHS(ctx, v.Key)
-			n++
-		}
-		if v.Value != nil {
-			compileExprLHS(ctx, v.Value)
-			n++
-		}
-		compileExpr(ctx, v.X)
-	}
-	pos := v.TokPos
-	if pos == 0 {
-		pos = v.For
-	}
-	cb.RangeAssignThen(pos)
-	compileStmts(ctx, v.Body.List)
-	cb.SetComments(comments, once)
-	setBodyHandler(ctx)
-	cb.End()
-}
-
-func compileForPhraseStmt(ctx *blockCtx, v *ast.ForPhraseStmt) {
-	if re, ok := v.X.(*ast.RangeExpr); ok {
-		compileForStmt(ctx, toForStmt(v.For, v.Value, v.Body, re, token.DEFINE, v.ForPhrase))
-		return
-	}
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	names := make([]string, 1, 2)
-	if v.Key == nil {
-		names[0] = "_"
-	} else {
-		names[0] = v.Key.Name
-	}
-	if v.Value != nil {
-		names = append(names, v.Value.Name)
-	}
-	cb.ForRange(names...)
-	compileExpr(ctx, v.X)
-	cb.RangeAssignThen(v.TokPos)
-	if v.Cond != nil {
-		cb.If()
-		compileExpr(ctx, v.Cond)
-		cb.Then()
-		compileStmts(ctx, v.Body.List)
-		cb.SetComments(comments, once)
-		cb.End()
-	} else {
-		compileStmts(ctx, v.Body.List)
-		cb.SetComments(comments, once)
-	}
-	setBodyHandler(ctx)
-	cb.End()
-}
-
-func toForStmt(forPos token.Pos, value ast.Expr, body *ast.BlockStmt, re *ast.RangeExpr, tok token.Token, fp *ast.ForPhrase) *ast.ForStmt {
-	nilIdent := value == nil
-	if !nilIdent {
-		if v, ok := value.(*ast.Ident); ok && v.Name == "_" {
-			nilIdent = true
-		}
-	}
-	if nilIdent {
-		value = &ast.Ident{NamePos: forPos, Name: "_gop_k"}
-	}
-	first := re.First
-	if first == nil {
-		first = &ast.BasicLit{ValuePos: forPos, Kind: token.INT, Value: "0"}
-	}
-	initLhs := []ast.Expr{value}
-	initRhs := []ast.Expr{first}
-	replaceValue := false
-	var cond ast.Expr
-	var post ast.Expr
-	switch re.Last.(type) {
-	case *ast.Ident, *ast.BasicLit:
-		cond = re.Last
-	default:
-		replaceValue = true
-		cond = &ast.Ident{NamePos: forPos, Name: "_gop_end"}
-		initLhs = append(initLhs, cond)
-		initRhs = append(initRhs, re.Last)
-	}
-	if re.Expr3 == nil {
-		post = &ast.BasicLit{ValuePos: forPos, Kind: token.INT, Value: "1"}
-	} else {
-		switch re.Expr3.(type) {
-		case *ast.Ident, *ast.BasicLit:
-			post = re.Expr3
-		default:
-			replaceValue = true
-			post = &ast.Ident{NamePos: forPos, Name: "_gop_step"}
-			initLhs = append(initLhs, post)
-			initRhs = append(initRhs, re.Expr3)
-		}
-	}
-	if tok == token.ASSIGN && replaceValue {
-		oldValue := value
-		value = &ast.Ident{NamePos: forPos, Name: "_gop_k"}
-		initLhs[0] = value
-		body.List = append([]ast.Stmt{&ast.AssignStmt{
-			Lhs:    []ast.Expr{oldValue},
-			TokPos: forPos,
-			Tok:    token.ASSIGN,
-			Rhs:    []ast.Expr{value},
-		}}, body.List...)
-		tok = token.DEFINE
-	}
-	if fp != nil && fp.Cond != nil {
-		condStmt := &ast.IfStmt{
-			If:   fp.IfPos,
-			Init: fp.Init,
-			Cond: fp.Cond,
-			Body: body,
-		}
-		body = &ast.BlockStmt{
-			List: []ast.Stmt{condStmt},
-		}
-	}
-	return &ast.ForStmt{
-		For: forPos,
-		Init: &ast.AssignStmt{
-			Lhs:    initLhs,
-			TokPos: re.To,
-			Tok:    tok,
-			Rhs:    initRhs,
-		},
-		Cond: &ast.BinaryExpr{
-			X:     value,
-			OpPos: re.To,
-			Op:    token.LSS,
-			Y:     cond,
-		},
-		Post: &ast.AssignStmt{
-			Lhs:    []ast.Expr{value},
-			TokPos: re.Colon2,
-			Tok:    token.ADD_ASSIGN,
-			Rhs:    []ast.Expr{post},
-		},
-		Body: body,
-	}
-}
-
-// for init; cond then
-//
-//	body
-//	post
-//
-// end
-func compileForStmt(ctx *blockCtx, v *ast.ForStmt) {
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	cb.For()
-	if v.Init != nil {
-		compileStmt(ctx, v.Init)
-	}
-	if v.Cond != nil {
-		compileExpr(ctx, v.Cond)
-	} else {
-		cb.None()
-	}
-	cb.Then()
-	compileStmts(ctx, v.Body.List)
-	if v.Post != nil {
-		cb.Post()
-		compileStmt(ctx, v.Post)
-	}
-	cb.SetComments(comments, once)
-	setBodyHandler(ctx)
-	cb.End()
-}
-
-// if init; cond then
-//
-//	body
-//
-// end
-func compileIfStmt(ctx *blockCtx, v *ast.IfStmt) {
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	cb.If()
-	if v.Init != nil {
-		compileStmt(ctx, v.Init)
-	}
-	compileExpr(ctx, v.Cond)
-	cb.Then()
-	compileStmts(ctx, v.Body.List)
-	if e := v.Else; e != nil {
-		cb.Else()
-		if stmts, ok := e.(*ast.BlockStmt); ok {
-			compileStmts(ctx, stmts.List)
-		} else {
-			compileStmt(ctx, e)
-		}
-	}
-	cb.SetComments(comments, once)
-	cb.End()
-}
-
-// typeSwitch(name) init; expr typeAssertThen()
-// type1 type2 ... typeN typeCase(N)
-//
-//	...
-//	end
-//
-// type1 type2 ... typeM typeCase(M)
-//
-//	...
-//	end
-//
-// end
-func compileTypeSwitchStmt(ctx *blockCtx, v *ast.TypeSwitchStmt) {
-	var cb = ctx.cb
-	comments, once := cb.BackupComments()
-	var name string
-	var ta *ast.TypeAssertExpr
-	switch stmt := v.Assign.(type) {
-	case *ast.AssignStmt:
-		if stmt.Tok != token.DEFINE || len(stmt.Lhs) != 1 || len(stmt.Rhs) != 1 {
-			panic("TODO: type switch syntax error")
-		}
-		name = stmt.Lhs[0].(*ast.Ident).Name
-		ta = stmt.Rhs[0].(*ast.TypeAssertExpr)
-	case *ast.ExprStmt:
-		ta = stmt.X.(*ast.TypeAssertExpr)
-	}
-	if ta.Type != nil {
-		panic("TODO: type switch syntax error, please use x.(type)")
-	}
-	cb.TypeSwitch(name)
-	if v.Init != nil {
-		compileStmt(ctx, v.Init)
-	}
-	compileExpr(ctx, ta.X)
-	cb.TypeAssertThen()
-	seen := make(map[types.Type]ast.Expr)
-	var firstDefault ast.Stmt
-	for _, stmt := range v.Body.List {
-		c, ok := stmt.(*ast.CaseClause)
-		if !ok {
-			log.Panicln("TODO: compile TypeSwitchStmt failed - case clause expected.")
-		}
-		for _, citem := range c.List {
-			compileExpr(ctx, citem)
-			T := cb.Get(-1).Type
-			if tt, ok := T.(*gox.TypeType); ok {
-				T = tt.Type()
-			}
-			var haserr bool
-			for t, other := range seen {
-				if T == nil && t == nil || T != nil && t != nil && types.Identical(T, t) {
-					haserr = true
-					pos := ctx.Position(citem.Pos())
-					if T == types.Typ[types.UntypedNil] {
-						ctx.handleCodeErrorf(&pos, "multiple nil cases in type switch (first at %v)", ctx.Position(other.Pos()))
-					} else {
-						ctx.handleCodeErrorf(&pos, "duplicate case %s in type switch\n\tprevious case at %v", T, ctx.Position(other.Pos()))
-					}
-				}
-			}
-			if !haserr {
-				seen[T] = citem
-			}
-		}
-		if c.List == nil {
-			if firstDefault != nil {
-				pos := ctx.Position(c.Pos())
-				ctx.handleCodeErrorf(&pos, "multiple defaults in type switch (first at %v)", ctx.Position(firstDefault.Pos()))
-			} else {
-				firstDefault = c
-			}
-		}
-		cb.TypeCase(len(c.List)) // TypeCase(0) means default case
-		compileStmts(ctx, c.Body)
-		commentStmt(ctx, stmt)
-		cb.End()
-	}
-	cb.SetComments(comments, once)
-	cb.End()
-}
-
-// switch init; tag then
-// expr1 expr2 ... exprN case(N)
-//
-//	...
-//	end
-//
-// expr1 expr2 ... exprM case(M)
-//
-//	...
-//	end
-//
-// end
-func compileSwitchStmt(ctx *blockCtx, v *ast.SwitchStmt) {
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	cb.Switch()
-	if v.Init != nil {
-		compileStmt(ctx, v.Init)
-	}
-	if v.Tag != nil { // switch tag {....}
-		compileExpr(ctx, v.Tag)
-	} else {
-		cb.None() // switch {...}
-	}
-	cb.Then()
-	seen := make(valueMap)
-	var firstDefault ast.Stmt
-	for _, stmt := range v.Body.List {
-		c, ok := stmt.(*ast.CaseClause)
-		if !ok {
-			log.Panicln("TODO: compile SwitchStmt failed - case clause expected.")
-		}
-		for _, citem := range c.List {
-			compileExpr(ctx, citem)
-			v := cb.Get(-1)
-			if val := goVal(v.CVal); val != nil {
-				// look for duplicate types for a given value
-				// (quadratic algorithm, but these lists tend to be very short)
-				typ := types.Default(v.Type)
-				var haserr bool
-				for _, vt := range seen[val] {
-					if types.Identical(typ, vt.typ) {
-						haserr = true
-						src, pos := ctx.LoadExpr(v.Src)
-						if _, ok := v.Src.(*ast.BasicLit); ok {
-							ctx.handleCodeErrorf(&pos, "duplicate case %s in switch\n\tprevious case at %v",
-								src, ctx.Position(vt.pos))
-						} else {
-							ctx.handleCodeErrorf(&pos, "duplicate case %s (value %#v) in switch\n\tprevious case at %v",
-								src, val, ctx.Position(vt.pos))
-						}
-					}
-				}
-				if !haserr {
-					seen[val] = append(seen[val], valueType{v.Src.Pos(), typ})
-				}
-			}
-		}
-		if c.List == nil {
-			if firstDefault != nil {
-				pos := ctx.Position(c.Pos())
-				ctx.handleCodeErrorf(&pos, "multiple defaults in switch (first at %v)", ctx.Position(firstDefault.Pos()))
-			} else {
-				firstDefault = c
-			}
-		}
-		cb.Case(len(c.List)) // Case(0) means default case
-		body, has := hasFallthrough(c.Body)
-		compileStmts(ctx, body)
-		if has {
-			cb.Fallthrough()
-		}
-		commentStmt(ctx, stmt)
-		cb.End()
-	}
-	cb.SetComments(comments, once)
-	cb.End()
-}
-
-func hasFallthrough(body []ast.Stmt) ([]ast.Stmt, bool) {
-	if n := len(body); n > 0 {
-		if bs, ok := body[n-1].(*ast.BranchStmt); ok && bs.Tok == token.FALLTHROUGH {
-			return body[:n-1], true
-		}
-	}
-	return body, false
-}
-
-// select
-// stmt1 commCase(1)
-//
-//	...
-//	end
-//
-// stmt2 commCase(1)
-//
-//	...
-//	end
-//
-// ...
-// commCase(0)
-//
-//	...
-//	end
-//
-// end
-func compileSelectStmt(ctx *blockCtx, v *ast.SelectStmt) {
-	cb := ctx.cb
-	comments, once := cb.BackupComments()
-	cb.Select()
-	for _, stmt := range v.Body.List {
-		c, ok := stmt.(*ast.CommClause)
-		if !ok {
-			log.Panicln("TODO: compile SelectStmt failed - comm clause expected.")
-		}
-		var n int
-		if c.Comm != nil {
-			compileStmt(ctx, c.Comm)
-			n = 1
-		}
-		cb.CommCase(n) // CommCase(0) means default case
-		compileStmts(ctx, c.Body)
-		commentStmt(ctx, stmt)
-		cb.End()
-	}
-	cb.SetComments(comments, once)
-	cb.End()
-}
-
-func compileBranchStmt(ctx *blockCtx, v *ast.BranchStmt) {
-	label := v.Label
-	switch v.Tok {
-	case token.GOTO:
-		cb := ctx.cb
-		if l, ok := cb.LookupLabel(label.Name); ok {
-			cb.Goto(l)
-			return
-		}
-		compileCallExpr(ctx, &ast.CallExpr{
-			Fun:  &ast.Ident{NamePos: v.TokPos, Name: "goto", Obj: &ast.Object{Data: label}},
-			Args: []ast.Expr{label},
-		}, clIdentGoto)
-	case token.BREAK:
-		ctx.cb.Break(getLabel(ctx, label))
-	case token.CONTINUE:
-		ctx.cb.Continue(getLabel(ctx, label))
-	case token.FALLTHROUGH:
-		pos := ctx.Position(v.Pos())
-		ctx.handleCodeErrorf(&pos, "fallthrough statement out of place")
-	default:
-		panic("unknown branch statement")
-	}
-}
-
-func getLabel(ctx *blockCtx, label *ast.Ident) *gox.Label {
-	if label != nil {
-		if l, ok := ctx.cb.LookupLabel(label.Name); ok {
-			return l
-		}
-		pos := ctx.Position(label.Pos())
-		ctx.handleCodeErrorf(&pos, "label %v is not defined", label.Name)
-	}
-	return nil
-}
-
-func compileLabeledStmt(ctx *blockCtx, v *ast.LabeledStmt) {
-	l, _ := ctx.cb.LookupLabel(v.Label.Name)
-	ctx.cb.Label(l)
-	compileStmt(ctx, v.Stmt)
-}
-
-func compileGoStmt(ctx *blockCtx, v *ast.GoStmt) {
-	compileCallExpr(ctx, v.Call, 0)
-	ctx.cb.Go()
-}
-
-func compileDeferStmt(ctx *blockCtx, v *ast.DeferStmt) {
-	compileCallExpr(ctx, v.Call, 0)
-	ctx.cb.Defer()
-}
-
-func compileDeclStmt(ctx *blockCtx, expr *ast.DeclStmt) {
-	switch d := expr.Decl.(type) {
-	case *ast.GenDecl:
-		switch d.Tok {
-		case token.TYPE:
-			for _, spec := range d.Specs {
-				compileType(ctx, spec.(*ast.TypeSpec))
-			}
-		case token.CONST:
-			cdecl := ctx.pkg.NewConstDefs(ctx.cb.Scope())
-			loadConstSpecs(ctx, cdecl, d.Specs)
-		case token.VAR:
-			vdecl := ctx.pkg.NewVarDefs(ctx.cb.Scope())
-			loadVarSpecs(ctx, vdecl, d.Specs)
-		default:
-			log.Panicln("TODO: compileDeclStmt - unknown")
-		}
-	}
-}
-
-func compileType(ctx *blockCtx, t *ast.TypeSpec) {
-	name := t.Name.Name
-	if name == "_" {
-		return
-	}
-	if t.Assign != token.NoPos { // alias type
-		ctx.cb.AliasType(name, toType(ctx, t.Type))
-	} else {
-		ctx.cb.NewType(name).InitType(ctx.pkg, toType(ctx, t.Type))
-	}
-}
-
-type (
-	valueMap  map[interface{}][]valueType // underlying Go value -> valueType
-	valueType struct {
-		pos token.Pos
-		typ types.Type
-	}
-)
-
-// goVal returns the Go value for val, or nil.
-func goVal(val constant.Value) interface{} {
-	// val should exist, but be conservative and check
-	if val == nil {
-		return nil
-	}
-	// Match implementation restriction of other compilers.
-	// gc only checks duplicates for integer, floating-point
-	// and string values, so only create Go values for these
-	// types.
-	switch val.Kind() {
-	case constant.Int:
-		if x, ok := constant.Int64Val(val); ok {
-			return x
-		}
-		if x, ok := constant.Uint64Val(val); ok {
-			return x
-		}
-	case constant.Float:
-		if x, ok := constant.Float64Val(val); ok {
-			return x
-		}
-	case constant.String:
-		return constant.StringVal(val)
-	}
-	return nil
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/types_go117.go b/cl/outline/cl/types_go117.go
deleted file mode 100644
index e07999d4..00000000
--- a/cl/outline/cl/types_go117.go
+++ /dev/null
@@ -1,65 +0,0 @@
-//go:build !go1.18
-// +build !go1.18
-
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package cl
-
-import (
-	"go/types"
-
-	"github.com/goplus/gop/ast"
-)
-
-func toBinaryExprType(ctx *blockCtx, v *ast.BinaryExpr) types.Type {
-	panic("type parameters are unsupported at this go version")
-}
-
-func toUnaryExprType(ctx *blockCtx, v *ast.UnaryExpr) types.Type {
-	panic("type parameters are unsupported at this go version")
-}
-
-type typeParamLookup struct {
-}
-
-func (p *typeParamLookup) Lookup(name string) types.Type {
-	return nil
-}
-
-func toFuncType(ctx *blockCtx, typ *ast.FuncType, recv *types.Var, d *ast.FuncDecl) *types.Signature {
-	params, variadic := toParams(ctx, typ.Params.List)
-	results := toResults(ctx, typ.Results)
-	return types.NewSignature(recv, params, results, variadic)
-}
-
-func initType(ctx *blockCtx, named *types.Named, spec *ast.TypeSpec) {
-	if spec.TypeParams != nil {
-		panic("Go/Go+ source with generic but go version is too low")
-	}
-	typ := toType(ctx, spec.Type)
-	if named, ok := typ.(*types.Named); ok {
-		typ = getUnderlying(ctx, named)
-	}
-	named.SetUnderlying(typ)
-}
-
-func sliceHasTypeParam(ctx *blockCtx, typ types.Type) bool {
-	return false
-}
-
-func withTypeParams(ctx *blockCtx, t *types.Named) bool {
-	return false
-}
diff --git a/cl/outline/cl/types_go118.go b/cl/outline/cl/types_go118.go
deleted file mode 100644
index fe00872f..00000000
--- a/cl/outline/cl/types_go118.go
+++ /dev/null
@@ -1,266 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-/*
- * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"go/types"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/token"
-)
-
-func toTermList(ctx *blockCtx, expr ast.Expr) []*types.Term {
-retry:
-	switch v := expr.(type) {
-	case *ast.UnaryExpr:
-		if v.Op != token.TILDE {
-			panic(ctx.newCodeErrorf(v.Pos(), "invalid op %v must ~", v.Op))
-		}
-		return []*types.Term{types.NewTerm(true, toType(ctx, v.X))}
-	case *ast.BinaryExpr:
-		if v.Op != token.OR {
-			panic(ctx.newCodeErrorf(v.Pos(), "invalid op %v must |", v.Op))
-		}
-		return append(toTermList(ctx, v.X), toTermList(ctx, v.Y)...)
-	case *ast.ParenExpr:
-		expr = v.X
-		goto retry
-	}
-	return []*types.Term{types.NewTerm(false, toType(ctx, expr))}
-}
-
-func toBinaryExprType(ctx *blockCtx, v *ast.BinaryExpr) types.Type {
-	return types.NewInterfaceType(nil, []types.Type{types.NewUnion(toTermList(ctx, v))})
-}
-
-func toUnaryExprType(ctx *blockCtx, v *ast.UnaryExpr) types.Type {
-	return types.NewInterfaceType(nil, []types.Type{types.NewUnion(toTermList(ctx, v))})
-}
-
-func toTypeParams(ctx *blockCtx, params *ast.FieldList) []*types.TypeParam {
-	if params == nil {
-		return nil
-	}
-	return collectTypeParams(ctx, params)
-}
-
-func recvTypeParams(ctx *blockCtx, typ ast.Expr, named *types.Named) (tparams []*types.TypeParam) {
-	orgTypeParams := named.TypeParams()
-	if orgTypeParams == nil {
-		return nil
-	}
-L:
-	for {
-		switch t := typ.(type) {
-		case *ast.ParenExpr:
-			typ = t.X
-		case *ast.StarExpr:
-			typ = t.X
-		default:
-			break L
-		}
-	}
-	switch t := typ.(type) {
-	case *ast.IndexExpr:
-		if orgTypeParams.Len() != 1 {
-			panic(ctx.newCodeErrorf(typ.Pos(), "got 1 type parameter, but receiver base type declares %v", orgTypeParams.Len()))
-		}
-		v := t.Index.(*ast.Ident)
-		tp := orgTypeParams.At(0)
-		obj := types.NewTypeName(v.Pos(), tp.Obj().Pkg(), v.Name, nil)
-		tparams = []*types.TypeParam{types.NewTypeParam(obj, tp.Constraint())}
-	case *ast.IndexListExpr:
-		n := len(t.Indices)
-		if n != orgTypeParams.Len() {
-			panic(ctx.newCodeErrorf(typ.Pos(), "got %v arguments but %v type parameters", n, orgTypeParams.Len()))
-		}
-		tparams = make([]*types.TypeParam, n)
-		for i := 0; i < n; i++ {
-			v := t.Indices[i].(*ast.Ident)
-			tp := orgTypeParams.At(i)
-			obj := types.NewTypeName(v.Pos(), tp.Obj().Pkg(), v.Name, nil)
-			tparams[i] = types.NewTypeParam(obj, tp.Constraint())
-		}
-	default:
-		panic(ctx.newCodeErrorf(typ.Pos(), "cannot use generic type %v without instantiation", named))
-	}
-	return
-}
-
-func toFuncType(ctx *blockCtx, typ *ast.FuncType, recv *types.Var, d *ast.FuncDecl) *types.Signature {
-	var typeParams []*types.TypeParam
-	if recv != nil && d.Recv != nil {
-		typ := recv.Type()
-		if pt, ok := typ.(*types.Pointer); ok {
-			typ = pt.Elem()
-		}
-		typeParams = recvTypeParams(ctx, d.Recv.List[0].Type, typ.(*types.Named))
-	} else {
-		typeParams = toTypeParams(ctx, typ.TypeParams)
-	}
-	if len(typeParams) > 0 {
-		ctx.tlookup = &typeParamLookup{typeParams}
-		defer func() {
-			ctx.tlookup = nil
-		}()
-	}
-	params, variadic := toParams(ctx, typ.Params.List)
-	results := toResults(ctx, typ.Results)
-	if recv != nil {
-		return types.NewSignatureType(recv, typeParams, nil, params, results, variadic)
-	}
-	return types.NewSignatureType(recv, nil, typeParams, params, results, variadic)
-}
-
-type typeParamLookup struct {
-	typeParams []*types.TypeParam
-}
-
-func (p *typeParamLookup) Lookup(name string) types.Type {
-	for _, t := range p.typeParams {
-		tname := t.Obj().Name()
-		if tname != "_" && name == tname {
-			return t
-		}
-	}
-	return nil
-}
-
-func initType(ctx *blockCtx, named *types.Named, spec *ast.TypeSpec) {
-	typeParams := toTypeParams(ctx, spec.TypeParams)
-	if len(typeParams) > 0 {
-		named.SetTypeParams(typeParams)
-		ctx.tlookup = &typeParamLookup{typeParams}
-		defer func() {
-			ctx.tlookup = nil
-		}()
-	}
-	org := ctx.inInst
-	ctx.inInst = 0
-	defer func() {
-		ctx.inInst = org
-	}()
-	typ := toType(ctx, spec.Type)
-	if named, ok := typ.(*types.Named); ok {
-		typ = getUnderlying(ctx, named)
-	}
-	named.SetUnderlying(typ)
-}
-
-func collectTypeParams(ctx *blockCtx, list *ast.FieldList) []*types.TypeParam {
-	var tparams []*types.TypeParam
-	// Declare type parameters up-front, with empty interface as type bound.
-	// The scope of type parameters starts at the beginning of the type parameter
-	// list (so we can have mutually recursive parameterized interfaces).
-	for _, f := range list.List {
-		tparams = declareTypeParams(ctx, tparams, f.Names)
-	}
-
-	ctx.tlookup = &typeParamLookup{tparams}
-	defer func() {
-		ctx.tlookup = nil
-	}()
-
-	index := 0
-	for _, f := range list.List {
-		var bound types.Type
-		// NOTE: we may be able to assert that f.Type != nil here, but this is not
-		// an invariant of the AST, so we are cautious.
-		if f.Type != nil {
-			bound = boundTypeParam(ctx, f.Type)
-			if isTypeParam(bound) {
-				// We may be able to allow this since it is now well-defined what
-				// the underlying type and thus type set of a type parameter is.
-				// But we may need some additional form of cycle detection within
-				// type parameter lists.
-				//check.error(f.Type, MisplacedTypeParam, "cannot use a type parameter as constraint")
-				bound = types.Typ[types.Invalid]
-			}
-		} else {
-			bound = types.Typ[types.Invalid]
-		}
-		for i := range f.Names {
-			tparams[index+i].SetConstraint(bound)
-		}
-		index += len(f.Names)
-	}
-	return tparams
-}
-
-func declareTypeParams(ctx *blockCtx, tparams []*types.TypeParam, names []*ast.Ident) []*types.TypeParam {
-	// Use Typ[Invalid] for the type constraint to ensure that a type
-	// is present even if the actual constraint has not been assigned
-	// yet.
-	// TODO(gri) Need to systematically review all uses of type parameter
-	//           constraints to make sure we don't rely on them if they
-	//           are not properly set yet.
-	for _, name := range names {
-		tname := types.NewTypeName(name.Pos(), ctx.pkg.Types, name.Name, nil)
-		tpar := types.NewTypeParam(tname, types.Typ[types.Invalid]) // assigns type to tpar as a side-effect
-		// check.declare(check.scope, name, tname, check.scope.pos) // TODO(gri) check scope position
-		tparams = append(tparams, tpar)
-	}
-	return tparams
-}
-
-func isTypeParam(t types.Type) bool {
-	_, ok := t.(*types.TypeParam)
-	return ok
-}
-
-func sliceHasTypeParam(ctx *blockCtx, typ types.Type) bool {
-	if typ == nil {
-		return false
-	}
-	var t *types.Slice
-	switch tt := typ.(type) {
-	case *types.Named:
-		t = getUnderlying(ctx, tt).(*types.Slice)
-	case *types.Slice:
-		t = tt
-	}
-	_, ok := t.Elem().(*types.TypeParam)
-	return ok
-}
-
-func boundTypeParam(ctx *blockCtx, x ast.Expr) types.Type {
-	// A type set literal of the form ~T and A|B may only appear as constraint;
-	// embed it in an implicit interface so that only interface type-checking
-	// needs to take care of such type expressions.
-	wrap := false
-	switch op := x.(type) {
-	case *ast.UnaryExpr:
-		wrap = op.Op == token.TILDE // ~E
-	case *ast.BinaryExpr:
-		wrap = op.Op == token.OR // A|B
-	}
-	if wrap {
-		x := &ast.InterfaceType{Methods: &ast.FieldList{List: []*ast.Field{{Type: x}}}}
-		t := toInterfaceType(ctx, x)
-		t.MarkImplicit() // mark t as implicit interface if all went well
-		return t
-	}
-	return toType(ctx, x)
-}
-
-func withTypeParams(ctx *blockCtx, t *types.Named) bool {
-	ctx.ensureLoaded(t)
-	return t.TypeParams() != nil && t.TypeArgs() == nil
-}
diff --git a/cl/stmt.go b/cl/stmt.go
index 0bb43cf6..0a4146b1 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -578,7 +578,8 @@ func compileTypeSwitchStmt(ctx *blockCtx, v *ast.TypeSwitchStmt) {
 		}
 		if c.List == nil {
 			if firstDefault != nil {
-				ctx.handleErrorf(c.Pos(), "multiple defaults in type switch (first at %v)", ctx.Position(firstDefault.Pos()))
+				ctx.handleErrorf(
+					c.Pos(), "multiple defaults in type switch (first at %v)", ctx.Position(firstDefault.Pos()))
 			} else {
 				firstDefault = c
 			}
@@ -635,12 +636,12 @@ func compileSwitchStmt(ctx *blockCtx, v *ast.SwitchStmt) {
 				for _, vt := range seen[val] {
 					if types.Identical(typ, vt.typ) {
 						haserr = true
-						src, pos := ctx.LoadExpr(v.Src)
-						if _, ok := v.Src.(*ast.BasicLit); ok {
-							ctx.handleCodeErrorf(&pos, "duplicate case %s in switch\n\tprevious case at %v",
+						src := ctx.LoadExpr(v.Src)
+						if lit, ok := v.Src.(*ast.BasicLit); ok {
+							ctx.handleErrorf(lit.Pos(), "duplicate case %s in switch\n\tprevious case at %v",
 								src, ctx.Position(vt.pos))
 						} else {
-							ctx.handleCodeErrorf(&pos, "duplicate case %s (value %#v) in switch\n\tprevious case at %v",
+							ctx.handleErrorf(v.Src.Pos(), "duplicate case %s (value %#v) in switch\n\tprevious case at %v",
 								src, val, ctx.Position(vt.pos))
 						}
 					}
diff --git a/go.mod b/go.mod
index 73c1f41a..9de7efc3 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,8 @@ go 1.18
 
 require (
 	github.com/fsnotify/fsnotify v1.7.0
-	github.com/goplus/c2go v0.7.16
-	github.com/goplus/gox v1.12.8
+	github.com/goplus/c2go v0.7.17-0.20231102134817-4d12585f3af3
+	github.com/goplus/gox v1.12.2-0.20231102132054-7ebd369dd022
 	github.com/goplus/mod v0.11.8
 	github.com/qiniu/x v1.13.1
 	golang.org/x/tools v0.14.0
diff --git a/go.sum b/go.sum
index dc1bcc5d..48220eb2 100644
--- a/go.sum
+++ b/go.sum
@@ -4,12 +4,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/goplus/c2go v0.7.16 h1:B9jRNNytoq7yDBQOZSm2qENQhRQMfNhgOea5XHWNUnI=
-github.com/goplus/c2go v0.7.16/go.mod h1:XODEFX2PeEEJXNLLdykWeZgMSaKJ51fVm+C9IM3FxNQ=
-github.com/goplus/gox v1.12.1/go.mod h1:wymoQJ7ydd42cTlaXb4wNbvn4LlKjR+j8PZehI7v1zQ=
-github.com/goplus/gox v1.12.8 h1:xXpsGbNIIDmykOQwI/kDcoA3cOX5ISvLPlU5RiPtyZY=
-github.com/goplus/gox v1.12.8/go.mod h1:MOJnwqA8/rSUkn0vsayHFK7TD/3XQrdexMTqdzR70X0=
-github.com/goplus/mod v0.11.5/go.mod h1:NDC5E+XOT8vcJCMjqKhLDJHTHX7lyVN4Vbfi2U7dBhs=
+github.com/goplus/c2go v0.7.17-0.20231102134817-4d12585f3af3 h1:+/enB6wmQenM2Ihwv/v41lSgdTf3ARPi6A8FB1A/YH4=
+github.com/goplus/c2go v0.7.17-0.20231102134817-4d12585f3af3/go.mod h1:DX0qhR2JSukHgIGMS9f6Vcu0N76LYBQy2tB+UnmIx3U=
+github.com/goplus/gox v1.12.2-0.20231102132054-7ebd369dd022 h1:1g5BzuA9FfZgQwQ4XJXFsNh7KfscSIJfbUp9KkOWY80=
+github.com/goplus/gox v1.12.2-0.20231102132054-7ebd369dd022/go.mod h1:MOJnwqA8/rSUkn0vsayHFK7TD/3XQrdexMTqdzR70X0=
 github.com/goplus/mod v0.11.8 h1:90Kbg+MJhrdsonNGXYx3HUcW4IbBlRHYpIMssJaMMxM=
 github.com/goplus/mod v0.11.8/go.mod h1:yl2QncBKTdXk+8UaNsdo4u2zSpGEJYA5JKjgD3K2h00=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -20,7 +18,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/qiniu/x v1.13.0/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
 github.com/qiniu/x v1.13.1 h1:hi7tkXFq6BWGbBpMoLV7kvA2elop69j6Kl7TlxnFAiU=
 github.com/qiniu/x v1.13.1/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -30,6 +27,7 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -41,11 +39,13 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -61,6 +61,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=


Test patch:
diff --git a/cl/outline/cl/builtin_test.go b/cl/outline/cl/builtin_test.go
deleted file mode 100644
index 56b07473..00000000
--- a/cl/outline/cl/builtin_test.go
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl
-
-import (
-	"errors"
-	"go/types"
-	"testing"
-
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-	"github.com/goplus/gox/cpackages"
-	"github.com/goplus/gox/packages"
-	"github.com/goplus/mod/modfile"
-)
-
-var (
-	goxConf = getGoxConf()
-)
-
-func getGoxConf() *gox.Config {
-	fset := token.NewFileSet()
-	imp := packages.NewImporter(fset)
-	return &gox.Config{Fset: fset, Importer: imp}
-}
-
-func TestCompileErrWrapExpr(t *testing.T) {
-	defer func() {
-		if e := recover(); e != "TODO: can't use expr? in global" {
-			t.Fatal("TestCompileErrWrapExpr failed")
-		}
-	}()
-	pkg := gox.NewPackage("", "foo", goxConf)
-	ctx := &blockCtx{pkg: pkg, cb: pkg.CB()}
-	compileErrWrapExpr(ctx, &ast.ErrWrapExpr{Tok: token.QUESTION}, 0)
-}
-
-func TestToString(t *testing.T) {
-	defer func() {
-		if e := recover(); e == nil {
-			t.Fatal("toString: no error?")
-		}
-	}()
-	toString(&ast.BasicLit{Kind: token.INT, Value: "1"})
-}
-
-func TestGetTypeName(t *testing.T) {
-	if getTypeName(types.Typ[types.Int]) != "int" {
-		t.Fatal("getTypeName int failed")
-	}
-	defer func() {
-		if e := recover(); e == nil {
-			t.Fatal("getTypeName: no error?")
-		}
-	}()
-	getTypeName(types.NewSlice(types.Typ[types.Int]))
-}
-
-func TestHandleRecover(t *testing.T) {
-	var ctx pkgCtx
-	ctx.handleRecover("hello")
-	if !(len(ctx.errs) == 1 && ctx.errs[0].Error() == "hello") {
-		t.Fatal("TestHandleRecover failed:", ctx.errs)
-	}
-	defer func() {
-		if e := recover(); e == nil {
-			t.Fatal("TestHandleRecover failed: no error?")
-		}
-	}()
-	ctx.handleRecover(100)
-}
-
-func TestCanAutoCall(t *testing.T) {
-	if !isCommandWithoutArgs(
-		&ast.SelectorExpr{
-			X:   &ast.SelectorExpr{X: ast.NewIdent("foo"), Sel: ast.NewIdent("bar")},
-			Sel: ast.NewIdent("val"),
-		}) {
-		t.Fatal("TestCanAutoCall failed")
-	}
-}
-
-func TestClRangeStmt(t *testing.T) {
-	ctx := &blockCtx{
-		cb: &gox.CodeBuilder{},
-	}
-	stmt := &ast.RangeStmt{
-		Tok:  token.DEFINE,
-		X:    &ast.SliceLit{},
-		Body: &ast.BlockStmt{},
-	}
-	compileRangeStmt(ctx, stmt)
-	stmt.Tok = token.ASSIGN
-	stmt.Value = &ast.Ident{Name: "_"}
-	compileRangeStmt(ctx, stmt)
-}
-
-// -----------------------------------------------------------------------------
-
-func TestGetStringConst(t *testing.T) {
-	spx := &gox.PkgRef{Types: types.NewPackage("", "foo")}
-	if v := getStringConst(spx, "unknown"); v != "" {
-		t.Fatal("getStringConst:", v)
-	}
-}
-
-func TestSpxRef(t *testing.T) {
-	defer func() {
-		if e := recover(); !isError(e, "foo.bar not found") {
-			t.Fatal("TestSpxRef:", e)
-		}
-	}()
-	pkg := &gox.PkgRef{
-		Types: types.NewPackage("foo", "foo"),
-	}
-	spxRef(pkg, "bar")
-}
-
-func isError(e interface{}, msg string) bool {
-	if e != nil {
-		if err, ok := e.(error); ok {
-			return err.Error() == msg
-		}
-		if err, ok := e.(string); ok {
-			return err == msg
-		}
-	}
-	return false
-}
-
-func TestGmxSettings(t *testing.T) {
-	pkg := gox.NewPackage("", "foo", goxConf)
-	gmx := newGmx(nil, pkg, "main.t2gmx", &ast.File{IsProj: true}, &Config{
-		LookupClass: lookupClass,
-	})
-	scheds := gmx.getScheds(pkg.CB())
-	if len(scheds) != 2 || scheds[0] == nil || scheds[0] != scheds[1] {
-		t.Fatal("TestGmxSettings failed")
-	}
-	gmx.hasScheds = false
-	if gmx.getScheds(nil) != nil {
-		t.Fatal("TestGmxSettings failed: hasScheds?")
-	}
-	_, err := NewPackage("", &ast.Package{Files: map[string]*ast.File{
-		"main.t2gmx": {
-			IsProj: true,
-		},
-	}}, &Config{
-		LookupClass: lookupClassErr,
-	})
-	if e := err.Error(); e != `github.com/goplus/gop/cl/internal/libc.Game not found` {
-		t.Fatal("newGmx:", e)
-	}
-}
-
-func TestSpxLookup(t *testing.T) {
-	defer func() {
-		if e := recover(); e == nil {
-			t.Fatal("TestSpxLookup failed: no error?")
-		}
-	}()
-	spxLookup(nil, "foo")
-}
-
-func lookupClass(ext string) (c *modfile.Project, ok bool) {
-	switch ext {
-	case ".t2gmx", ".t2spx":
-		return &modfile.Project{
-			Ext: ".t2gmx", Class: "Game",
-			Works:    []*modfile.Class{{Ext: ".t2spx", Class: "Sprite"}},
-			PkgPaths: []string{"github.com/goplus/gop/cl/internal/spx2"}}, true
-	}
-	return
-}
-
-func lookupClassErr(ext string) (c *modfile.Project, ok bool) {
-	switch ext {
-	case ".t2gmx", ".t2spx":
-		return &modfile.Project{
-			Ext: ".t2gmx", Class: "Game",
-			Works:    []*modfile.Class{{Ext: ".t2spx", Class: "Sprite"}},
-			PkgPaths: []string{"github.com/goplus/gop/cl/internal/libc"}}, true
-	}
-	return
-}
-
-func TestGetGoFile(t *testing.T) {
-	if f := genGoFile("a_test.gop", true); f != testingGoFile {
-		t.Fatal("TestGetGoFile:", f)
-	}
-	if f := genGoFile("a_test.gop", false); f != skippingGoFile {
-		t.Fatal("TestGetGoFile:", f)
-	}
-}
-
-func TestC2goBase(t *testing.T) {
-	if c2goBase("") != "github.com/goplus/" {
-		t.Fatal("c2goBase failed")
-	}
-}
-
-func TestErrLoadImport(t *testing.T) {
-	testPanic(t, ".: unknownpkg not found or not a valid C package (c2go.a.pub file not found).\n", func() {
-		pkg := &pkgCtx{
-			nodeInterp: &nodeInterp{
-				fset: token.NewFileSet(),
-			},
-			cpkgs: cpackages.NewImporter(
-				&cpackages.Config{LookupPub: func(pkgPath string) (pubfile string, err error) {
-					return "", errors.New("not found")
-				}})}
-		ctx := &blockCtx{pkgCtx: pkg}
-		spec := &ast.ImportSpec{
-			Path: &ast.BasicLit{Kind: token.STRING, Value: `"C/unknownpkg"`},
-		}
-		loadImport(ctx, spec)
-		panic(ctx.errs[0].Error())
-	})
-}
-
-func TestErrCompileBasicLit(t *testing.T) {
-	testPanic(t, "compileBasicLit: invalid syntax\n", func() {
-		ctx := &blockCtx{cb: new(gox.CodeBuilder)}
-		compileBasicLit(ctx, &ast.BasicLit{Kind: token.CSTRING, Value: `\\x`})
-	})
-}
-
-func testPanic(t *testing.T, panicMsg string, doPanic func()) {
-	t.Run(panicMsg, func(t *testing.T) {
-		defer func() {
-			if e := recover(); e == nil {
-				t.Fatal("testPanic: no error?")
-			} else if msg := e.(string); msg != panicMsg {
-				t.Fatalf("\nResult:\n%s\nExpected Panic:\n%s\n", msg, panicMsg)
-			}
-		}()
-		doPanic()
-	})
-}
-
-// -----------------------------------------------------------------------------
diff --git a/cl/outline/cl/compile_c2go_test.go b/cl/outline/cl/compile_c2go_test.go
deleted file mode 100644
index c02af114..00000000
--- a/cl/outline/cl/compile_c2go_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl_test
-
-import (
-	"path/filepath"
-	"strings"
-)
-
-func lookupPub(pkgPath string) (pubfile string, err error) {
-	relPath := strings.TrimPrefix(pkgPath, "github.com/goplus/gop/")
-	return filepath.Join(gopRootDir, relPath, "c2go.a.pub"), nil
-}
-
-/*
-func TestHelloC2go(t *testing.T) {
-	gopClTest(t, `
-import "C"
-
-C.printf C"Hello, world!\n"
-`, `package main
-
-import (
-	libc "github.com/goplus/gop/cl/internal/libc"
-	unsafe "unsafe"
-)
-
-func main() {
-	libc.Printf((*int8)(unsafe.Pointer(&[15]int8{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', '\x00'})))
-}
-`)
-}
-
-func TestHelloC2go2(t *testing.T) {
-	gopClTest(t, `
-import "C/github.com/goplus/gop/cl/internal/libc"
-
-C.printf C"Hello, world!\n"
-`, `package main
-
-import (
-	libc "github.com/goplus/gop/cl/internal/libc"
-	unsafe "unsafe"
-)
-
-func main() {
-	libc.Printf((*int8)(unsafe.Pointer(&[15]int8{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', '\x00'})))
-}
-`)
-}
-
-func TestHelloC2go3(t *testing.T) {
-	gopClTest(t, `
-import "C/libc"
-
-C.printf C"Hello, world!\n"
-`, `package main
-
-import (
-	libc "github.com/goplus/gop/cl/internal/libc"
-	unsafe "unsafe"
-)
-
-func main() {
-	libc.Printf((*int8)(unsafe.Pointer(&[15]int8{'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', '\x00'})))
-}
-`)
-}
-
-func TestErrHelloC2go(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:7:3: confliction: printf declared both in "github.com/goplus/gop/cl/internal/libc" and "github.com/goplus/gop/cl/internal/libc"`, `
-import (
-	"C"
-	"C/libc"
-)
-
-C.printf C"Hello, world!\n"
-`)
-}
-*/
diff --git a/cl/outline/cl/compile_spx_test.go b/cl/outline/cl/compile_spx_test.go
deleted file mode 100644
index a4d381b1..00000000
--- a/cl/outline/cl/compile_spx_test.go
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl_test
-
-import (
-	"bytes"
-	"os"
-	"path"
-	"testing"
-
-	"github.com/goplus/gop/cl/outline/cl"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/parser/fsx/memfs"
-	"github.com/goplus/gop/scanner"
-	"github.com/goplus/mod/modfile"
-)
-
-func lookupClass(ext string) (c *modfile.Project, ok bool) {
-	switch ext {
-	case ".tgmx", ".tspx":
-		return &modfile.Project{
-			Ext: ".tgmx", Class: "*MyGame",
-			Works:    []*modfile.Class{{Ext: ".tspx", Class: "Sprite"}},
-			PkgPaths: []string{"github.com/goplus/gop/cl/internal/spx", "math"}}, true
-	case ".t2gmx", ".t2spx", ".t2spx2":
-		return &modfile.Project{
-			Ext: ".t2gmx", Class: "Game",
-			Works: []*modfile.Class{{Ext: ".t2spx", Class: "Sprite"},
-				{Ext: ".t2spx2", Class: "Sprite2"}},
-			PkgPaths: []string{"github.com/goplus/gop/cl/internal/spx2"}}, true
-	case ".t3spx", ".t3spx2":
-		return &modfile.Project{
-			Works: []*modfile.Class{{Ext: ".t3spx", Class: "Sprite"},
-				{Ext: ".t3spx2", Class: "Sprite2"}},
-			PkgPaths: []string{"github.com/goplus/gop/cl/internal/spx2"}}, true
-	}
-	return
-}
-
-func spxParserConf() parser.Config {
-	return parser.Config{
-		ClassKind: func(fname string) (isProj bool, ok bool) {
-			ext := path.Ext(fname)
-			c, ok := lookupClass(ext)
-			if ok {
-				isProj = (c.Ext == ext)
-			}
-			return
-		},
-	}
-}
-
-func gopSpxTest(t *testing.T, gmx, spxcode, expected string) {
-	gopSpxTestEx(t, gmx, spxcode, expected, "index.tgmx", "bar.tspx")
-}
-
-func gopSpxTestEx(t *testing.T, gmx, spxcode, expected, gmxfile, spxfile string) {
-	gopSpxTestExConf(t, "gopSpxTest", gblConf, gmx, spxcode, expected, gmxfile, spxfile)
-}
-
-func gopSpxTestExConf(t *testing.T, name string, conf *cl.Config, gmx, spxcode, expected, gmxfile, spxfile string) {
-	t.Run(name, func(t *testing.T) {
-		cl.SetDisableRecover(true)
-		defer cl.SetDisableRecover(false)
-
-		fs := memfs.TwoFiles("/foo", spxfile, spxcode, gmxfile, gmx)
-		pkgs, err := parser.ParseFSDir(gblFset, fs, "/foo", spxParserConf())
-		if err != nil {
-			scanner.PrintError(os.Stderr, err)
-			t.Fatal("ParseFSDir:", err)
-		}
-		bar := pkgs["main"]
-		pkg, err := cl.NewPackage("", bar, conf)
-		if err != nil {
-			t.Fatal("NewPackage:", err)
-		}
-		var b bytes.Buffer
-		err = pkg.WriteTo(&b)
-		if err != nil {
-			t.Fatal("gox.WriteTo failed:", err)
-		}
-		result := b.String()
-		if result != expected {
-			t.Fatalf("\nResult:\n%s\nExpected:\n%s\n", result, expected)
-		}
-	})
-}
-
-func gopSpxErrorTestEx(t *testing.T, msg, gmx, spxcode, gmxfile, spxfile string) {
-	fs := memfs.TwoFiles("/foo", spxfile, spxcode, gmxfile, gmx)
-	pkgs, err := parser.ParseFSDir(gblFset, fs, "/foo", spxParserConf())
-	if err != nil {
-		scanner.PrintError(os.Stderr, err)
-		t.Fatal("ParseFSDir:", err)
-	}
-	conf := *gblConf
-	conf.NoFileLine = false
-	conf.WorkingDir = "/foo"
-	conf.TargetDir = "/foo"
-	bar := pkgs["main"]
-	_, err = cl.NewPackage("", bar, &conf)
-	if err == nil {
-		t.Fatal("no error?")
-	}
-	if ret := err.Error(); ret != msg {
-		t.Fatalf("\nError: \"%s\"\nExpected: \"%s\"\n", ret, msg)
-	}
-}
-
-func TestSpxError(t *testing.T) {
-	gopSpxErrorTestEx(t, `./Game.tgmx:6:2: userScore redeclared
-	./Game.tgmx:5:2 other declaration of userScore`, `
-import "bytes"
-var (
-	Kai Kai
-	userScore int
-	userScore string
-)
-`, `
-println "hi"
-`, "Game.tgmx", "Kai.tspx")
-
-	gopSpxErrorTestEx(t, `./Kai.tspx:4:2: id redeclared
-	./Kai.tspx:3:2 other declaration of id`, `
-var (
-	Kai Kai
-	userScore int
-)
-`, `
-var (
-	id int
-	id string
-)
-println "hi"
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxBasic(t *testing.T) {
-	gopSpxTestEx(t, `
-func onInit() {
-	for {
-	}
-}
-`, `
-func onMsg(msg string) {
-	for {
-		say "Hi"
-	}
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-type Game struct {
-	*spx.MyGame
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-}
-
-func (this *Game) onInit() {
-	for {
-		spx.SchedNow()
-	}
-}
-func (this *Kai) onMsg(msg string) {
-	for {
-		spx.Sched()
-		this.Say("Hi")
-	}
-}
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxBasic2(t *testing.T) {
-	gopSpxTest(t, `
-import (
-	"fmt"
-)
-
-const (
-	Foo = 1
-)
-
-func bar() {
-}
-
-func onInit() {
-	Foo
-	bar
-	fmt.Println("Hi")
-}
-`, ``, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx"
-)
-
-type bar struct {
-	spx.Sprite
-	*index
-}
-type index struct {
-	*spx.MyGame
-}
-
-const Foo = 1
-
-func (this *index) bar() {
-}
-func (this *index) onInit() {
-	this.bar()
-	fmt.Println("Hi")
-}
-`)
-}
-
-func TestSpxMethod(t *testing.T) {
-	gopSpxTestEx(t, `
-func onInit() {
-	sched
-	broadcast "msg1"
-	TestIntValue = 1
-	x := round(1.2)
-}
-`, `
-func onInit() {
-	setCostume "kai-a"
-	play "recordingWhere"
-	say "Where do you come from?", 2
-	broadcast "msg2"
-}
-`, `package main
-
-import (
-	"github.com/goplus/gop/cl/internal/spx"
-	"math"
-)
-
-type Game struct {
-	*spx.MyGame
-}
-type bar struct {
-	spx.Sprite
-	*Game
-}
-
-func (this *Game) onInit() {
-	spx.Sched()
-	this.Broadcast__0("msg1")
-	spx.TestIntValue = 1
-	x := math.Round(1.2)
-}
-func (this *bar) onInit() {
-	this.SetCostume("kai-a")
-	this.Play("recordingWhere")
-	this.Say("Where do you come from?", 2)
-	this.Broadcast__0("msg2")
-}
-`, "Game.tgmx", "bar.tspx")
-}
-
-func TestSpxVar(t *testing.T) {
-	gopSpxTestEx(t, `
-var (
-	Kai Kai
-)
-
-func onInit() {
-	Kai.clone()
-	broadcast("msg1")
-}
-`, `
-var (
-	a int
-)
-
-func onInit() {
-	a = 1
-}
-
-func onCloned() {
-	say("Hi")
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-type Game struct {
-	*spx.MyGame
-	Kai Kai
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-	a int
-}
-
-func (this *Game) onInit() {
-	spx.Gopt_Sprite_Clone__0(this.Kai)
-	this.Broadcast__0("msg1")
-}
-func (this *Kai) onInit() {
-	this.a = 1
-}
-func (this *Kai) onCloned() {
-	this.Say("Hi")
-}
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxRun(t *testing.T) {
-	gopSpxTestEx(t, `
-var (
-	Kai Kai
-	t   Sound
-)
-
-var x float64 = rand(1.2)
-
-run "hzip://open.qiniu.us/weather/res.zip"
-`, `
-println "Hi"
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx"
-)
-
-type Kai struct {
-	spx.Sprite
-	*index
-}
-type index struct {
-	*spx.MyGame
-	Kai Kai
-	t   spx.Sound
-}
-
-var x float64 = spx.Rand__1(1.2)
-
-func (this *Kai) Main() {
-	fmt.Println("Hi")
-}
-func (this *index) MainEntry() {
-	spx.Gopt_MyGame_Run(this, "hzip://open.qiniu.us/weather/res.zip")
-}
-func main() {
-	spx.Gopt_MyGame_Main(new(index))
-}
-`, "index.tgmx", "Kai.tspx")
-}
-
-func TestSpx2(t *testing.T) {
-	gopSpxTestEx(t, `
-println("Hi")
-`, `
-func onMsg(msg string) {
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx2"
-)
-
-type Game struct {
-	spx2.Game
-}
-type Kai struct {
-	spx2.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-	fmt.Println("Hi")
-}
-func (this *Kai) onMsg(msg string) {
-}
-func main() {
-	new(Game).Main()
-}
-`, "Game.t2gmx", "Kai.t2spx")
-
-	gopSpxTestEx(t, `
-println("Hi, Sprite2")
-`, `
-func onMsg(msg string) {
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx2"
-)
-
-type Game struct {
-	spx2.Game
-}
-type Kai struct {
-	spx2.Sprite2
-	*Game
-}
-
-func (this *Game) MainEntry() {
-	fmt.Println("Hi, Sprite2")
-}
-func (this *Kai) onMsg(msg string) {
-}
-func main() {
-	new(Game).Main()
-}
-`, "Game.t2gmx", "Kai.t2spx2")
-
-	gopSpxTestEx(t, `
-println("Hi, Sprite")
-`, `
-func onMsg(msg string) {
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx2"
-)
-
-type Dog struct {
-	spx2.Sprite
-}
-type Kai struct {
-	spx2.Sprite2
-}
-
-func (this *Dog) Main() {
-	fmt.Println("Hi, Sprite")
-}
-func (this *Kai) onMsg(msg string) {
-}
-`, "Dog.t3spx", "Kai.t3spx2")
-}
-
-func TestSpxMainEntry(t *testing.T) {
-	conf := *gblConf
-	conf.Importer = nil
-	conf.NoAutoGenMain = false
-
-	gopSpxTestExConf(t, "Nocode", &conf, `
-`, `
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx2"
-
-type Game struct {
-	spx2.Game
-}
-type Kai struct {
-	spx2.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-}
-func main() {
-	new(Game).Main()
-}
-`, "Game.t2gmx", "Kai.t2spx")
-	gopSpxTestExConf(t, "OnlyGmx", &conf, `
-var (
-	Kai Kai
-)
-`, `
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx2"
-
-type Game struct {
-	spx2.Game
-	Kai Kai
-}
-type Kai struct {
-	spx2.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-}
-func main() {
-	new(Game).Main()
-}
-`, "Game.t2gmx", "Kai.t2spx")
-
-	gopSpxTestExConf(t, "KaiAndGmx", &conf, `
-var (
-	Kai Kai
-)
-func MainEntry() {
-	println "Hi"
-}
-`, `
-func Main() {
-	println "Hello"
-}
-func onMsg(msg string) {
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx2"
-)
-
-type Game struct {
-	spx2.Game
-	Kai Kai
-}
-type Kai struct {
-	spx2.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-	fmt.Println("Hi")
-}
-func (this *Kai) Main() {
-	fmt.Println("Hello")
-}
-func (this *Kai) onMsg(msg string) {
-}
-func main() {
-	new(Game).Main()
-}
-`, "Game.t2gmx", "Kai.t2spx")
-}
-
-func TestSpxGoxBasic(t *testing.T) {
-	gopSpxTestEx(t, `
-func onInit() {
-	for {
-	}
-}
-`, `
-func onMsg(msg string) {
-	for {
-		say "Hi"
-	}
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-type Game struct {
-	*spx.MyGame
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-}
-
-func (this *Game) onInit() {
-	for {
-		spx.SchedNow()
-	}
-}
-func (this *Kai) onMsg(msg string) {
-	for {
-		spx.Sched()
-		this.Say("Hi")
-	}
-}
-`, "Game.tgmx.gox", "Kai.tspx.gox")
-}
-
-func TestSpxClone(t *testing.T) {
-	gopSpxTestEx(t, `
-var (
-	Kai Kai
-)
-
-func onInit() {
-	Kai.clone()
-	broadcast("msg1")
-}
-`, `
-var (
-	a int
-)
-
-type info struct {
-	x int
-	y int
-}
-
-func onInit() {
-	a = 1
-	clone
-	clone info{1,2}
-	clone &info{1,2}
-}
-
-func onCloned() {
-	say("Hi")
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-type Game struct {
-	*spx.MyGame
-	Kai Kai
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-	a int
-}
-type info struct {
-	x int
-	y int
-}
-
-func (this *Game) onInit() {
-	spx.Gopt_Sprite_Clone__0(this.Kai)
-	this.Broadcast__0("msg1")
-}
-func (this *Kai) onInit() {
-	this.a = 1
-	spx.Gopt_Sprite_Clone__0(this)
-	spx.Gopt_Sprite_Clone__1(this, info{1, 2})
-	spx.Gopt_Sprite_Clone__1(this, &info{1, 2})
-}
-func (this *Kai) onCloned() {
-	this.Say("Hi")
-}
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxErrorSel(t *testing.T) {
-	gopSpxErrorTestEx(t, `./Kai.tspx:2:9: this.pos undefined (type *Kai has no field or method pos)`, `
-println "hi"
-`, `
-println this.pos
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxMethodSel(t *testing.T) {
-	gopSpxTestEx(t, `
-sendMessage "Hi"
-`, `
-func onMsg(msg string) {
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-type Game struct {
-	*spx.MyGame
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-	this.SendMessage("Hi")
-}
-func (this *Kai) onMsg(msg string) {
-}
-func main() {
-	spx.Gopt_MyGame_Main(new(Game))
-}
-`, "Game.tgmx", "Kai.tspx")
-}
-
-func TestSpxPkgOverload(t *testing.T) {
-	gopSpxTestEx(t, `
-println "Hi"
-`, `
-func onMsg(msg string) {
-	this.position.add 100,200
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/spx"
-)
-
-type Game struct {
-	*spx.MyGame
-}
-type Kai struct {
-	spx.Sprite
-	*Game
-}
-
-func (this *Game) MainEntry() {
-	fmt.Println("Hi")
-}
-func (this *Kai) onMsg(msg string) {
-	this.Position().Add__0(100, 200)
-}
-func main() {
-	spx.Gopt_MyGame_Main(new(Game))
-}
-`, "Game.tgmx", "Kai.tspx")
-}
diff --git a/cl/outline/cl/compile_test.go b/cl/outline/cl/compile_test.go
deleted file mode 100644
index 52fd5dc4..00000000
--- a/cl/outline/cl/compile_test.go
+++ /dev/null
@@ -1,4616 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl_test
-
-import (
-	"bytes"
-	"os"
-	"strings"
-	"sync"
-	"testing"
-
-	"github.com/goplus/gop"
-	"github.com/goplus/gop/ast"
-	"github.com/goplus/gop/cl/outline/cl"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/parser/fsx/memfs"
-	"github.com/goplus/gop/scanner"
-	"github.com/goplus/gop/token"
-	"github.com/goplus/gox"
-	"github.com/goplus/mod/env"
-)
-
-const (
-	gopRootDir = ".."
-)
-
-var (
-	gblFset *token.FileSet
-	gblConf *cl.Config
-)
-
-func init() {
-	gox.SetDebug(gox.DbgFlagAll)
-	cl.SetDebug(cl.DbgFlagAll)
-	gblFset = token.NewFileSet()
-	imp := gop.NewImporter(nil, &env.Gop{Root: gopRootDir, Version: "1.0"}, gblFset)
-	gblConf = &cl.Config{
-		Fset:          gblFset,
-		Importer:      imp,
-		LookupClass:   lookupClass,
-		LookupPub:     lookupPub,
-		C2goBase:      "github.com/goplus/gop/cl/internal",
-		NoFileLine:    true,
-		NoAutoGenMain: true,
-	}
-}
-
-func gopClNamedTest(t *testing.T, name string, gopcode, expected string) {
-	t.Run(name, func(t *testing.T) {
-		gopClTest(t, gopcode, expected)
-	})
-}
-
-func gopClTest(t *testing.T, gopcode, expected string) {
-	gopClTestEx(t, gblConf, "main", gopcode, expected)
-}
-
-func gopClTestFile(t *testing.T, gopcode, expected string, fname string) {
-	fs := memfs.SingleFile("/foo", fname, gopcode)
-	gopClTestFS(t, gblConf, fs, "main", expected)
-}
-
-func gopClTestEx(t *testing.T, conf *cl.Config, pkgname, gopcode, expected string) {
-	fs := memfs.SingleFile("/foo", "bar.gop", gopcode)
-	gopClTestFS(t, conf, fs, pkgname, expected)
-}
-
-func gopMixedClTest(t *testing.T, pkgname, gocode, gopcode, expected string, outline ...bool) {
-	fs := memfs.TwoFiles("/foo", "a.go", gocode, "b.gop", gopcode)
-	gopClTestFS(t, gblConf, fs, pkgname, expected, outline...)
-}
-
-func gopClTestFS(t *testing.T, conf *cl.Config, fs parser.FileSystem, pkgname, expected string, outline ...bool) {
-	cl.SetDisableRecover(true)
-	defer cl.SetDisableRecover(false)
-
-	pkgs, err := parser.ParseFSDir(gblFset, fs, "/foo", parser.Config{Mode: parser.ParseComments})
-	if err != nil {
-		scanner.PrintError(os.Stderr, err)
-		t.Fatal("ParseFSDir:", err)
-	}
-	bar := pkgs[pkgname]
-	newPackage := cl.NewPackage
-	if outline != nil && outline[0] {
-		newPackage = func(pkgPath string, pkg *ast.Package, conf *cl.Config) (p *gox.Package, err error) {
-			p, _, err = cl.NewOutline(pkgPath, pkg, conf)
-			return
-		}
-	}
-	pkg, err := newPackage("github.com/goplus/gop/cl", bar, conf)
-	if err != nil {
-		t.Fatal("NewPackage:", err)
-	}
-	var b bytes.Buffer
-	err = pkg.WriteTo(&b)
-	if err != nil {
-		t.Fatal("gox.WriteTo failed:", err)
-	}
-	result := b.String()
-	if result != expected {
-		t.Fatalf("\nResult:\n%s\nExpected:\n%s\n", result, expected)
-	}
-}
-
-func TestVargCommand(t *testing.T) {
-	gopClTest(t, `
-type foo int
-
-func (f foo) Ls(args ...string) {
-}
-
-var f foo
-f.ls
-`, `package main
-
-type foo int
-
-var f foo
-
-func (f foo) Ls(args ...string) {
-}
-func main() {
-	f.Ls()
-}
-`)
-}
-
-func _TestCommandInPkg(t *testing.T) {
-	gopClTest(t, `
-func Ls(args ...string) {
-}
-
-ls
-`, `
-`)
-}
-
-func TestFileOpen(t *testing.T) {
-	gopClTest(t, `
-for line <- open("foo.txt")! {
-	println line
-}
-`, `package main
-
-import (
-	"fmt"
-	"os"
-	"github.com/goplus/gop/builtin/iox"
-	"github.com/qiniu/x/errors"
-)
-
-func main() {
-	for _gop_it := iox.EnumLines(func() (_gop_ret *os.File) {
-		var _gop_err error
-		_gop_ret, _gop_err = os.Open("foo.txt")
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "open(\"foo.txt\")", "/foo/bar.gop", 2, "main.main")
-			panic(_gop_err)
-		}
-		return
-	}()); ; {
-		var _gop_ok bool
-		line, _gop_ok := _gop_it.Next()
-		if !_gop_ok {
-			break
-		}
-		fmt.Println(line)
-	}
-}
-`)
-}
-
-func TestFileEnumLines(t *testing.T) {
-	gopClTest(t, `
-import "os"
-
-for line <- os.Stdin {
-	println line
-}
-`, `package main
-
-import (
-	"fmt"
-	"os"
-	"github.com/goplus/gop/builtin/iox"
-)
-
-func main() {
-	for _gop_it := iox.EnumLines(os.Stdin); ; {
-		var _gop_ok bool
-		line, _gop_ok := _gop_it.Next()
-		if !_gop_ok {
-			break
-		}
-		fmt.Println(line)
-	}
-}
-`)
-}
-
-func TestIoxLines(t *testing.T) {
-	gopClTest(t, `
-import "io"
-
-var r io.Reader
-
-for line <- lines(r) {
-	println line
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/builtin/iox"
-	"io"
-)
-
-var r io.Reader
-
-func main() {
-	for _gop_it := iox.Lines(r).Gop_Enum(); ; {
-		var _gop_ok bool
-		line, _gop_ok := _gop_it.Next()
-		if !_gop_ok {
-			break
-		}
-		fmt.Println(line)
-	}
-}
-`)
-}
-
-func TestMixedGo(t *testing.T) {
-	gopMixedClTest(t, "main", `package main
-
-import "strconv"
-
-const n = 10
-
-func f(v int) string {
-	return strconv.Itoa(v)
-}
-
-type foo struct {
-	v int
-}
-
-func (a foo) _() {
-}
-
-func (a foo) Str() string {
-	return f(a.v)
-}
-
-func (a *foo) Bar() int {
-	return 0
-}
-
-type foo2 = foo
-type foo3 foo2
-`, `
-var a [n]int
-var b string = f(n)
-var c foo2
-var d int = c.v
-var e = foo3{}
-var x string = c.str
-`, `package main
-
-var a [10]int
-var b string = f(n)
-var c foo
-var d int = c.v
-var e = foo3{}
-var x string = c.Str()
-`, true)
-	gopMixedClTest(t, "main", `package main
-type Point struct {
-	X int
-	Y int
-}
-`, `
-type T struct{}
-println(&T{},&Point{10,20})
-`, `package main
-
-import "fmt"
-
-type T struct {
-}
-
-func main() {
-	fmt.Println(&T{}, &Point{10, 20})
-}
-`, false)
-}
-
-func Test_RangeExpressionIf_Issue1243(t *testing.T) {
-	gopClTest(t, `
-for i <- :10, i%3 == 0 {
-	println i
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 0; i < 10; i += 1 {
-		if i%3 == 0 {
-			fmt.Println(i)
-		}
-	}
-}
-`)
-}
-
-func Test_CastSlice_Issue1240(t *testing.T) {
-	gopClTest(t, `
-type fvec []float64
-type foo float64
-a := []float64([1, 2])
-b := fvec([1, 2])
-c := foo([1, 2])
-d := fvec([])
-println a, b, c, d
-`, `package main
-
-import "fmt"
-
-type fvec []float64
-type foo float64
-
-func main() {
-	a := []float64{1, 2}
-	b := fvec{1, 2}
-	c := foo([]int{1, 2})
-	d := fvec{}
-	fmt.Println(a, b, c, d)
-}
-`)
-}
-
-func TestUnderscoreRedeclared_Issue1197(t *testing.T) {
-	gopClTest(t, `
-func() (_ [2]int) { type _ int; return }()
-`, `package main
-
-func main() {
-	func() (_ [2]int) {
-		return
-	}()
-}
-`)
-}
-
-func TestInterfaceBugNilUnderlying_Issue1198(t *testing.T) {
-	gopClTest(t, `
-import "runtime"
-
-type Outer interface{ Inner }
-
-type impl struct{}
-
-func New() Outer { return &impl{} }
-
-type Inner interface {
-	DoStuff() error
-}
-
-func (a *impl) DoStuff() error {
-	return nil
-}
-
-func main() {
-	var outer Outer = New()
-}
-`, `package main
-
-type Outer interface {
-	Inner
-}
-type impl struct {
-}
-type Inner interface {
-	DoStuff() error
-}
-
-func New() Outer {
-	return &impl{}
-}
-func (a *impl) DoStuff() error {
-	return nil
-}
-func main() {
-	var outer Outer = New()
-}
-`)
-}
-
-func TestInterfaceBugNilUnderlying_Issue1196(t *testing.T) {
-	gopClTest(t, `
-func main() {
-	i := I(A{})
-
-	b := make(chan I, 1)
-	b <- B{}
-
-	var ok bool
-	i, ok = <-b
-}
-
-type I interface{ M() int }
-
-type T int
-
-func (T) M() int { return 0 }
-
-type A struct{ T }
-type B struct{ T }
-`, `package main
-
-type I interface {
-	M() int
-}
-type T int
-type A struct {
-	T
-}
-type B struct {
-	T
-}
-
-func main() {
-	i := I(A{})
-	b := make(chan I, 1)
-	b <- B{}
-	var ok bool
-	i, ok = <-b
-}
-func (T) M() int {
-	return 0
-}
-`)
-}
-
-func TestMyIntInc_Issue1195(t *testing.T) {
-	gopClTest(t, `
-type MyInt int
-var c MyInt
-c++
-`, `package main
-
-type MyInt int
-
-var c MyInt
-
-func main() {
-	c++
-}
-`)
-}
-
-func TestAutoPropMixedName_Issue1194(t *testing.T) {
-	gopClTest(t, `
-type Point struct {
-	Min, Max int
-}
-
-type Obj struct {
-	bbox Point
-}
-
-func (o *Obj) Bbox() Point {
-	return o.bbox
-}
-
-func (o *Obj) Points() [2]int{
-	return [2]int{o.bbox.Min, o.bbox.Max}
-}
-`, `package main
-
-type Point struct {
-	Min int
-	Max int
-}
-type Obj struct {
-	bbox Point
-}
-
-func (o *Obj) Bbox() Point {
-	return o.bbox
-}
-func (o *Obj) Points() [2]int {
-	return [2]int{o.bbox.Min, o.bbox.Max}
-}
-`)
-}
-
-func TestShiftUntypedInt_Issue1193(t *testing.T) {
-	gopClTest(t, `
-func GetValue(shift uint) uint {
-	return 1 << shift
-}`, `package main
-
-func GetValue(shift uint) uint {
-	return 1 << shift
-}
-`)
-}
-
-func TestInitFunc(t *testing.T) {
-	gopClTest(t, `
-
-func init() {}
-func init() {}
-`, `package main
-
-func init() {
-}
-func init() {
-}
-`)
-}
-
-func TestSlogan(t *testing.T) {
-	gopClTest(t, `
-fields := ["engineering", "STEM education", "data science"]
-println "The Go+ Language for", fields.join(", ")
-`, `package main
-
-import (
-	"fmt"
-	"strings"
-)
-
-func main() {
-	fields := []string{"engineering", "STEM education", "data science"}
-	fmt.Println("The Go+ Language for", strings.Join(fields, ", "))
-}
-`)
-}
-
-func TestAssignPrintln(t *testing.T) {
-	gopClTest(t, `
-p := println
-p "Hello world"
-`, `package main
-
-import "fmt"
-
-func main() {
-	p := fmt.Println
-	p("Hello world")
-}
-`)
-}
-
-func TestRedefineBuiltin(t *testing.T) {
-	gopClTest(t, `
-func main() {
-	const a = append + len
-}
-
-const (
-	append = iota
-	len
-)
-`, `package main
-
-const (
-	append = iota
-	len
-)
-
-func main() {
-	const a = append + len
-}
-`)
-}
-
-func TestTypeConvIssue804(t *testing.T) {
-	gopClTest(t, `
-c := make(chan int)
-d := (chan<- int)(c)
-e := (<-chan int)(c)
-f := (*int)(nil)
-a := c == d
-b := c == e
-`, `package main
-
-func main() {
-	c := make(chan int)
-	d := (chan<- int)(c)
-	e := (<-chan int)(c)
-	f := (*int)(nil)
-	a := c == d
-	b := c == e
-}
-`)
-}
-
-func TestUntypedFloatIssue798(t *testing.T) {
-	gopClTest(t, `
-func isPow10(x uint64) bool {
-	switch x {
-	case 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-		1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19:
-		return true
-	}
-	return false
-}
-`, `package main
-
-func isPow10(x uint64) bool {
-	switch x {
-	case 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19:
-		return true
-	}
-	return false
-}
-`)
-}
-
-func TestInterfaceIssue795(t *testing.T) {
-	gopClTest(t, `
-type I interface {
-	a(s string) I
-	b(s string) string
-}
-
-type T1 int
-
-func (t T1) a(s string) I {
-	return t
-}
-
-func (T1) b(s string) string {
-	return s
-}
-`, `package main
-
-type I interface {
-	a(s string) I
-	b(s string) string
-}
-type T1 int
-
-func (t T1) a(s string) I {
-	return t
-}
-func (T1) b(s string) string {
-	return s
-}
-`)
-}
-
-func TestChanRecvIssue789(t *testing.T) {
-	gopClTest(t, `
-func foo(ch chan int) (int, bool) {
-	x, ok := (<-ch)
-	return x, ok
-}
-`, `package main
-
-func foo(ch chan int) (int, bool) {
-	x, ok := <-ch
-	return x, ok
-}
-`)
-}
-
-func TestNamedChanCloseIssue790(t *testing.T) {
-	gopClTest(t, `
-type XChan chan int
-
-func foo(ch XChan) {
-	close(ch)
-}
-`, `package main
-
-type XChan chan int
-
-func foo(ch XChan) {
-	close(ch)
-}
-`)
-}
-
-func TestUntypedFloatIssue793(t *testing.T) {
-	gopClTest(t, `
-var a [1e1]int
-`, `package main
-
-var a [10]int
-`)
-}
-
-func TestUntypedFloatIssue788(t *testing.T) {
-	gopClTest(t, `
-func foo(v int) bool {
-    return v > 1.1e5
-}
-`, `package main
-
-func foo(v int) bool {
-	return v > 1.1e5
-}
-`)
-}
-
-func TestSwitchCompositeLitIssue801(t *testing.T) {
-	gopClTest(t, `
-type T struct {
-	X int
-}
-
-switch (T{}) {
-case T{1}:
-	panic("bad")
-}
-`, `package main
-
-type T struct {
-	X int
-}
-
-func main() {
-	switch (T{}) {
-	case T{1}:
-		panic("bad")
-	}
-}
-`)
-}
-
-func TestConstIssue800(t *testing.T) {
-	gopClTest(t, `
-const (
-	h0_0, h0_1 = 1.0 / (iota + 1), 1.0 / (iota + 2)
-	h1_0, h1_1
-)
-`, `package main
-
-const (
-	h0_0, h0_1 = 1.0 / (iota + 1), 1.0 / (iota + 2)
-	h1_0, h1_1
-)
-`)
-}
-
-func TestConstIssue805(t *testing.T) {
-	gopClTest(t, `
-const (
-	n1 = +5
-	d1 = +3
-
-	q1 = +1
-	r1 = +2
-)
-
-const (
-	ret1 = n1/d1 != q1
-	ret2 = n1%d1 != r1
-	ret3 = n1/d1 != q1 || n1%d1 != r1
-)
-`, `package main
-
-const (
-	n1 = +5
-	d1 = +3
-	q1 = +1
-	r1 = +2
-)
-const (
-	ret1 = n1/d1 != q1
-	ret2 = n1%d1 != r1
-	ret3 = false
-)
-`)
-}
-
-func TestUntypedNilIssue806(t *testing.T) {
-	gopClTest(t, `
-switch f := func() {}; f {
-case nil:
-}
-`, `package main
-
-func main() {
-	switch f := func() {
-	}; f {
-	case nil:
-	}
-}
-`)
-}
-
-func TestSwitchIssue807(t *testing.T) {
-	gopClTest(t, `
-switch {
-case interface{}(true):
-}
-`, `package main
-
-func main() {
-	switch {
-	case interface {
-	}(true):
-	}
-}
-`)
-}
-
-func TestUntypedComplexIssue799(t *testing.T) {
-	gopClTest(t, `
-const ulp1 = imag(1i + 2i / 3 - 5i / 3)
-const ulp2 = imag(1i + complex(0, 2) / 3 - 5i / 3)
-
-func main() {
-	const a = (ulp1 == ulp2)
-}
-`, `package main
-
-const ulp1 = imag(1i + 2i/3 - 5i/3)
-const ulp2 = imag(1i + complex(0, 2)/3 - 5i/3)
-
-func main() {
-	const a = ulp1 == ulp2
-}
-`)
-}
-
-func TestUnderscoreConstAndVar(t *testing.T) {
-	gopClTest(t, `
-const (
-	c0 = 1 << iota
-	_
-	_
-	_
-	c4
-)
-
-func i() int {
-	return 23
-}
-
-var (
-	_ = i()
-	_ = i()
-)
-`, `package main
-
-const (
-	c0 = 1 << iota
-	_
-	_
-	_
-	c4
-)
-
-var (
-	_ = i()
-	_ = i()
-)
-
-func i() int {
-	return 23
-}
-`)
-}
-
-func TestUnderscoreFuncAndMethod(t *testing.T) {
-	gopClTest(t, `
-func _() {
-}
-
-type T struct {
-	_, _, _ int
-}
-
-func (T) _() {
-}
-
-func (T) _() {
-}
-`, `package main
-
-type T struct {
-	_ int
-	_ int
-	_ int
-}
-
-func _() {
-}
-func (T) _() {
-}
-func (T) _() {
-}
-`)
-}
-
-func TestErrWrapIssue772(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func t() (int,int,error){
-	return 0, 0, nil
-}
-
-func main() {
-	a, b := t()!
-	println(a, b)
-}`, `package main
-
-import (
-	"fmt"
-	"github.com/qiniu/x/errors"
-)
-
-func t() (int, int, error) {
-	return 0, 0, nil
-}
-func main() {
-	a, b := func() (_gop_ret int, _gop_ret2 int) {
-		var _gop_err error
-		_gop_ret, _gop_ret2, _gop_err = t()
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "t()", "/foo/bar.gop", 9, "main.main")
-			panic(_gop_err)
-		}
-		return
-	}()
-	fmt.Println(a, b)
-}
-`)
-}
-
-func TestErrWrapIssue778(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func t() error {
-	return nil
-}
-
-func main() {
-	t()!
-}`, `package main
-
-import "github.com/qiniu/x/errors"
-
-func t() error {
-	return nil
-}
-func main() {
-	func() {
-		var _gop_err error
-		_gop_err = t()
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "t()", "/foo/bar.gop", 9, "main.main")
-			panic(_gop_err)
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestIssue774(t *testing.T) {
-	gopClNamedTest(t, "InterfaceTypeAssert", `
-package main
-
-import "fmt"
-
-func main() {
-	var a AA = &A{str: "hello"}
-	fmt.Println(a.(*A))
-}
-
-type AA interface {
-	String() string
-}
-
-type A struct {
-	str string
-}
-
-func (a *A) String() string {
-	return a.str
-}
-`, `package main
-
-import "fmt"
-
-type AA interface {
-	String() string
-}
-type A struct {
-	str string
-}
-
-func main() {
-	var a AA = &A{str: "hello"}
-	fmt.Println(a.(*A))
-}
-func (a *A) String() string {
-	return a.str
-}
-`)
-	gopClNamedTest(t, "getInterface", `
-package main
-
-import "fmt"
-
-func main() {
-	a := get()
-	fmt.Println(a.(*A))
-}
-
-func get() AA {
-	var a AA
-	return a
-}
-
-type AA interface {
-	String() string
-}
-
-type A struct {
-	str string
-}
-
-func (a *A) String() string {
-	return a.str
-}
-`, `package main
-
-import "fmt"
-
-type AA interface {
-	String() string
-}
-type A struct {
-	str string
-}
-
-func main() {
-	a := get()
-	fmt.Println(a.(*A))
-}
-func get() AA {
-	var a AA
-	return a
-}
-func (a *A) String() string {
-	return a.str
-}
-`)
-}
-
-func TestBlockStmt(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func main() {
-	{
-		type T int
-		t := T(100)
-		println(t)
-	}
-	{
-		type T string
-		t := "hello"
-		println(t)
-	}
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	{
-		type T int
-		t := T(100)
-		fmt.Println(t)
-	}
-	{
-		type T string
-		t := "hello"
-		fmt.Println(t)
-	}
-}
-`)
-}
-
-func TestConstTypeConvIssue792(t *testing.T) {
-	gopClTest(t, `
-const dots = ". . . " + ". . . . . "
-const n = uint(len(dots))
-`, `package main
-
-const dots = ". . . " + ". . . . . "
-const n = uint(len(dots))
-`)
-}
-
-func TestConstDeps(t *testing.T) {
-	gopClTest(t, `
-const (
-	i = a
-	a = 1
-)
-`, `package main
-
-const (
-	i = a
-	a = 1
-)
-`)
-}
-
-func TestVarInitTwoValueIssue791(t *testing.T) {
-	gopClTest(t, `
-var (
-	m      = map[string]string{"a": "A"}
-	a, ok  = m["a"]
-)
-`, `package main
-
-var (
-	m     = map[string]string{"a": "A"}
-	a, ok = m["a"]
-)
-`)
-}
-
-func TestVarAfterMain(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func main() {
-	println(i)
-}
-
-var i int
-`, `package main
-
-import "fmt"
-
-var i int
-
-func main() {
-	fmt.Println(i)
-}
-`)
-	gopClTest(t, `
-package main
-
-func f(v float64) float64 {
-	return v
-}
-func main() {
-	sink = f(100)
-}
-
-var sink float64
-`, `package main
-
-var sink float64
-
-func f(v float64) float64 {
-	return v
-}
-func main() {
-	sink = f(100)
-}
-`)
-}
-
-func TestVarAfterMain2(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func main() {
-	println(i)
-}
-
-var i = 100
-`, `package main
-
-import "fmt"
-
-var i = 100
-
-func main() {
-	fmt.Println(i)
-}
-`)
-}
-
-func TestVarInMain(t *testing.T) {
-	gopClTest(t, `
-package main
-
-func main() {
-	v := []uint64{2, 3, 5}
-	var n = len(v)
-	println(n)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	v := []uint64{2, 3, 5}
-	var n = len(v)
-	fmt.Println(n)
-}
-`)
-}
-
-func TestSelect(t *testing.T) {
-	gopClTest(t, `
-
-func consume(xchg chan int) {
-	select {
-	case c := <-xchg:
-		println(c)
-	case xchg <- 1:
-		println("send ok")
-	default:
-		println(0)
-	}
-}
-`, `package main
-
-import "fmt"
-
-func consume(xchg chan int) {
-	select {
-	case c := <-xchg:
-		fmt.Println(c)
-	case xchg <- 1:
-		fmt.Println("send ok")
-	default:
-		fmt.Println(0)
-	}
-}
-`)
-}
-
-func TestTypeSwitch(t *testing.T) {
-	gopClTest(t, `
-
-func bar(p *interface{}) {
-}
-
-func foo(v interface{}) {
-	switch t := v.(type) {
-	case int, string:
-		bar(&v)
-	case bool:
-		var x bool = t
-	default:
-		bar(nil)
-	}
-}
-`, `package main
-
-func bar(p *interface {
-}) {
-}
-func foo(v interface {
-}) {
-	switch t := v.(type) {
-	case int, string:
-		bar(&v)
-	case bool:
-		var x bool = t
-	default:
-		bar(nil)
-	}
-}
-`)
-}
-
-func TestTypeSwitch2(t *testing.T) {
-	gopClTest(t, `
-
-func bar(p *interface{}) {
-}
-
-func foo(v interface{}) {
-	switch bar(nil); v.(type) {
-	case int, string:
-		bar(&v)
-	}
-}
-`, `package main
-
-func bar(p *interface {
-}) {
-}
-func foo(v interface {
-}) {
-	switch bar(nil); v.(type) {
-	case int, string:
-		bar(&v)
-	}
-}
-`)
-}
-
-func TestTypeAssert(t *testing.T) {
-	gopClTest(t, `
-
-func foo(v interface{}) {
-	x := v.(int)
-	y, ok := v.(string)
-}
-`, `package main
-
-func foo(v interface {
-}) {
-	x := v.(int)
-	y, ok := v.(string)
-}
-`)
-}
-
-func TestInterface(t *testing.T) {
-	gopClTest(t, `
-
-type Shape interface {
-	Area() float64
-}
-
-func foo(shape Shape) {
-	shape.Area()
-}
-`, `package main
-
-type Shape interface {
-	Area() float64
-}
-
-func foo(shape Shape) {
-	shape.Area()
-}
-`)
-}
-
-func TestInterfaceEmbedded(t *testing.T) {
-	gopClTest(t, `
-type Shape interface {
-	Area() float64
-}
-
-type Bar interface {
-	Shape
-}
-`, `package main
-
-type Shape interface {
-	Area() float64
-}
-type Bar interface {
-	Shape
-}
-`)
-}
-
-func TestInterfaceExample(t *testing.T) {
-	gopClTest(t, `
-type Shape interface {
-	Area() float64
-}
-
-type Rect struct {
-	x, y, w, h float64
-}
-
-func (p *Rect) Area() float64 {
-	return p.w * p.h
-}
-
-type Circle struct {
-	x, y, r float64
-}
-
-func (p *Circle) Area() float64 {
-	return 3.14 * p.r * p.r
-}
-
-func Area(shapes ...Shape) float64 {
-	s := 0.0
-	for shape <- shapes {
-		s += shape.Area()
-	}
-	return s
-}
-
-func main() {
-	rect := &Rect{0, 0, 2, 5}
-	circle := &Circle{0, 0, 3}
-	println(Area(circle, rect))
-}
-`, `package main
-
-import "fmt"
-
-type Shape interface {
-	Area() float64
-}
-type Rect struct {
-	x float64
-	y float64
-	w float64
-	h float64
-}
-type Circle struct {
-	x float64
-	y float64
-	r float64
-}
-
-func (p *Rect) Area() float64 {
-	return p.w * p.h
-}
-func (p *Circle) Area() float64 {
-	return 3.14 * p.r * p.r
-}
-func Area(shapes ...Shape) float64 {
-	s := 0.0
-	for _, shape := range shapes {
-		s += shape.Area()
-	}
-	return s
-}
-func main() {
-	rect := &Rect{0, 0, 2, 5}
-	circle := &Circle{0, 0, 3}
-	fmt.Println(Area(circle, rect))
-}
-`)
-}
-
-func TestEmbeddField(t *testing.T) {
-	gopClTest(t, `import "math/big"
-
-type BigInt struct {
-	*big.Int
-}`, `package main
-
-import "math/big"
-
-type BigInt struct {
-	*big.Int
-}
-`)
-}
-
-func TestAutoProperty(t *testing.T) {
-	gopClTest(t, `import "github.com/goplus/gop/ast/goptest"
-
-func foo(script string) {
-	doc := goptest.New(script)!
-
-	println(doc.any.funcDecl.name)
-	println(doc.any.importSpec.name)
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/ast/goptest"
-	"github.com/qiniu/x/errors"
-	"github.com/goplus/gop/ast/gopq"
-)
-
-func foo(script string) {
-	doc := func() (_gop_ret gopq.NodeSet) {
-		var _gop_err error
-		_gop_ret, _gop_err = goptest.New(script)
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "goptest.New(script)", "/foo/bar.gop", 4, "main.foo")
-			panic(_gop_err)
-		}
-		return
-	}()
-	fmt.Println(doc.Any().FuncDecl().Name())
-	fmt.Println(doc.Any().ImportSpec().Name())
-}
-`)
-}
-
-func TestSimplifyAutoProperty(t *testing.T) {
-	gopClTest(t, `import "gop/ast/goptest"
-
-func foo(script string) {
-	doc := goptest.New(script)!
-
-	println(doc.any.funcDecl.name)
-	println(doc.any.importSpec.name)
-}
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/ast/goptest"
-	"github.com/qiniu/x/errors"
-	"github.com/goplus/gop/ast/gopq"
-)
-
-func foo(script string) {
-	doc := func() (_gop_ret gopq.NodeSet) {
-		var _gop_err error
-		_gop_ret, _gop_err = goptest.New(script)
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "goptest.New(script)", "/foo/bar.gop", 4, "main.foo")
-			panic(_gop_err)
-		}
-		return
-	}()
-	fmt.Println(doc.Any().FuncDecl().Name())
-	fmt.Println(doc.Any().ImportSpec().Name())
-}
-`)
-}
-
-func TestErrWrapBasic(t *testing.T) {
-	gopClTest(t, `
-import "strconv"
-
-func add(x, y string) (int, error) {
-	return strconv.Atoi(x)? + strconv.Atoi(y)?, nil
-}
-`, `package main
-
-import (
-	"strconv"
-	"github.com/qiniu/x/errors"
-)
-
-func add(x string, y string) (int, error) {
-	var _autoGo_1 int
-	{
-		var _gop_err error
-		_autoGo_1, _gop_err = strconv.Atoi(x)
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "strconv.Atoi(x)", "/foo/bar.gop", 5, "main.add")
-			return 0, _gop_err
-		}
-		goto _autoGo_2
-	_autoGo_2:
-	}
-	var _autoGo_3 int
-	{
-		var _gop_err error
-		_autoGo_3, _gop_err = strconv.Atoi(y)
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "strconv.Atoi(y)", "/foo/bar.gop", 5, "main.add")
-			return 0, _gop_err
-		}
-		goto _autoGo_4
-	_autoGo_4:
-	}
-	return _autoGo_1 + _autoGo_3, nil
-}
-`)
-}
-
-func TestErrWrapDefVal(t *testing.T) {
-	gopClTest(t, `
-import "strconv"
-
-func addSafe(x, y string) int {
-	return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0
-}
-`, `package main
-
-import "strconv"
-
-func addSafe(x string, y string) int {
-	return func() (_gop_ret int) {
-		var _gop_err error
-		_gop_ret, _gop_err = strconv.Atoi(x)
-		if _gop_err != nil {
-			return 0
-		}
-		return
-	}() + func() (_gop_ret int) {
-		var _gop_err error
-		_gop_ret, _gop_err = strconv.Atoi(y)
-		if _gop_err != nil {
-			return 0
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestErrWrapPanic(t *testing.T) {
-	gopClTest(t, `
-var ret int = println("Hi")!
-`, `package main
-
-import (
-	"fmt"
-	"github.com/qiniu/x/errors"
-)
-
-var ret int = func() (_gop_ret int) {
-	var _gop_err error
-	_gop_ret, _gop_err = fmt.Println("Hi")
-	if _gop_err != nil {
-		_gop_err = errors.NewFrame(_gop_err, "println(\"Hi\")", "/foo/bar.gop", 2, "main.main")
-		panic(_gop_err)
-	}
-	return
-}()
-`)
-}
-
-func TestErrWrapCommand(t *testing.T) {
-	gopClTest(t, `
-func mkdir(name string) error {
-	return nil
-}
-
-mkdir! "foo"
-`, `package main
-
-import "github.com/qiniu/x/errors"
-
-func mkdir(name string) error {
-	return nil
-}
-func main() {
-	func() {
-		var _gop_err error
-		_gop_err = mkdir("foo")
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "mkdir \"foo\"", "/foo/bar.gop", 6, "main.main")
-			panic(_gop_err)
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestErrWrapCall(t *testing.T) {
-	gopClTest(t, `
-func foo() (func(), error) {
-	return nil, nil
-}
-
-foo()!()
-`, `package main
-
-import "github.com/qiniu/x/errors"
-
-func foo() (func(), error) {
-	return nil, nil
-}
-func main() {
-	func() (_gop_ret func()) {
-		var _gop_err error
-		_gop_ret, _gop_err = foo()
-		if _gop_err != nil {
-			_gop_err = errors.NewFrame(_gop_err, "foo()", "/foo/bar.gop", 6, "main.main")
-			panic(_gop_err)
-		}
-		return
-	}()()
-}
-`)
-}
-
-func TestMakeAndNew(t *testing.T) {
-	gopClTest(t, `
-var a *int = new(int)
-var b map[string]int = make(map[string]int)
-var c []byte = make([]byte, 0, 2)
-`, `package main
-
-var a *int = new(int)
-var b map[string]int = make(map[string]int)
-var c []byte = make([]byte, 0, 2)
-`)
-}
-
-func TestVarDecl(t *testing.T) {
-	gopClTest(t, `
-var a int
-var x, y = 1, "Hi"
-`, `package main
-
-var a int
-var x, y = 1, "Hi"
-`)
-}
-
-func TestUint128Add(t *testing.T) {
-	gopClTest(t, `
-var x, y uint128
-var z uint128 = x + y
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x, y ng.Uint128
-var z ng.Uint128 = x.Gop_Add__1(y)
-`)
-}
-
-func TestInt128Add(t *testing.T) {
-	gopClTest(t, `
-var x, y int128
-var z int128 = x + y
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x, y ng.Int128
-var z ng.Int128 = x.Gop_Add__1(y)
-`)
-}
-
-func TestBigIntAdd(t *testing.T) {
-	gopClTest(t, `
-var x, y bigint
-var z bigint = x + y
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x, y ng.Bigint
-var z ng.Bigint = x.Gop_Add(y)
-`)
-}
-
-func TestBigIntLit(t *testing.T) {
-	gopClTest(t, `
-var x = 1r
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-var x = ng.Bigint_Init__1(big.NewInt(1))
-`)
-}
-
-func TestUint128Lit(t *testing.T) {
-	gopClTest(t, `
-var x uint128 = 1
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x ng.Uint128 = ng.Uint128_Init__0(1)
-`)
-}
-
-func TestInt128Lit(t *testing.T) {
-	gopClTest(t, `
-var x int128 = 1
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x ng.Int128 = ng.Int128_Init__0(1)
-`)
-}
-
-func TestBigRatLit(t *testing.T) {
-	gopClTest(t, `
-var x = 1/2r
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-var x = ng.Bigrat_Init__2(big.NewRat(1, 2))
-`)
-}
-
-func TestBigRatLitAdd(t *testing.T) {
-	gopClTest(t, `
-var x = 3 + 1/2r
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-var x = ng.Bigrat_Init__2(big.NewRat(7, 2))
-`)
-}
-
-func TestBigRatAdd(t *testing.T) {
-	gox.SetDebug(gox.DbgFlagAll)
-	gopClTest(t, `
-var x = 3 + 1/2r
-var y = x + 100
-var z = 100 + y
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-var x = ng.Bigrat_Init__2(big.NewRat(7, 2))
-var y = x.Gop_Add(ng.Bigrat_Init__0(100))
-var z = ng.Bigrat_Init__0(100) + y
-`)
-}
-
-func TestTypeConv(t *testing.T) {
-	gopClTest(t, `
-var a = (*struct{})(nil)
-var b = interface{}(nil)
-var c = (func())(nil)
-var x uint32 = uint32(0)
-var y *uint32 = (*uint32)(nil)
-`, `package main
-
-var a = (*struct {
-})(nil)
-var b = interface {
-}(nil)
-var c = (func())(nil)
-var x uint32 = uint32(0)
-var y *uint32 = (*uint32)(nil)
-`)
-}
-
-func TestStar(t *testing.T) {
-	gopClTest(t, `
-var x *uint32 = (*uint32)(nil)
-var y uint32 = *x
-`, `package main
-
-var x *uint32 = (*uint32)(nil)
-var y uint32 = *x
-`)
-}
-
-func TestLHS(t *testing.T) {
-	gopClTest(t, `
-type T struct {
-	a int
-}
-
-func foo() *T {
-	return nil
-}
-
-foo().a = 123
-`, `package main
-
-type T struct {
-	a int
-}
-
-func foo() *T {
-	return nil
-}
-func main() {
-	foo().a = 123
-}
-`)
-}
-
-func TestSend(t *testing.T) {
-	gopClTest(t, `
-var x chan bool
-x <- true
-`, `package main
-
-var x chan bool
-
-func main() {
-	x <- true
-}
-`)
-}
-
-func TestIncDec(t *testing.T) {
-	gopClTest(t, `
-var x uint32
-x++
-`, `package main
-
-var x uint32
-
-func main() {
-	x++
-}
-`)
-}
-
-func TestAssignOp(t *testing.T) {
-	gopClTest(t, `
-var x uint32
-x += 3
-`, `package main
-
-var x uint32
-
-func main() {
-	x += 3
-}
-`)
-}
-
-func TestBigIntAssignOp(t *testing.T) {
-	gopClTest(t, `
-var x bigint
-x += 3
-`, `package main
-
-import "github.com/goplus/gop/builtin/ng"
-
-var x ng.Bigint
-
-func main() {
-	x.Gop_AddAssign(ng.Bigint_Init__0(3))
-}
-`)
-}
-
-func TestBigIntAssignOp2(t *testing.T) {
-	gopClTest(t, `
-x := 3r
-x *= 2
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-func main() {
-	x := ng.Bigint_Init__1(big.NewInt(3))
-	x.Gop_MulAssign(ng.Bigint_Init__0(2))
-}
-`)
-}
-
-func TestBigIntAssignOp3(t *testing.T) {
-	gopClTest(t, `
-x := 3r
-x *= 2r
-`, `package main
-
-import (
-	"github.com/goplus/gop/builtin/ng"
-	"math/big"
-)
-
-func main() {
-	x := ng.Bigint_Init__1(big.NewInt(3))
-	x.Gop_MulAssign(ng.Bigint_Init__1(big.NewInt(2)))
-}
-`)
-}
-
-func TestCompositeLit(t *testing.T) {
-	gopClTest(t, `
-x := []float64{1, 3.4, 5}
-y := map[string]int{"Hello": 1, "Go+": 5}
-z := [...]int{1, 3, 5}
-a := {"Hello": 1, "Go+": 5.1}
-`, `package main
-
-func main() {
-	x := []float64{1, 3.4, 5}
-	y := map[string]int{"Hello": 1, "Go+": 5}
-	z := [...]int{1, 3, 5}
-	a := map[string]float64{"Hello": 1, "Go+": 5.1}
-}
-`)
-}
-
-func TestCompositeLit2(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-	A int
-}
-
-x := []*struct{a int}{
-	{1}, {3}, {5},
-}
-y := map[foo]struct{a string}{
-	{1}: {"Hi"},
-}
-z := [...]foo{
-	{1}, {3}, {5},
-}
-`, `package main
-
-type foo struct {
-	A int
-}
-
-func main() {
-	x := []*struct {
-		a int
-	}{&struct {
-		a int
-	}{1}, &struct {
-		a int
-	}{3}, &struct {
-		a int
-	}{5}}
-	y := map[foo]struct {
-		a string
-	}{foo{1}: struct {
-		a string
-	}{"Hi"}}
-	z := [...]foo{foo{1}, foo{3}, foo{5}}
-}
-`)
-}
-
-// deduce struct type as parameters of a function call
-func TestCompositeLit3(t *testing.T) {
-	gopClTest(t, `
-type Config struct {
-	A int
-}
-
-func foo(conf *Config) {
-}
-
-func bar(conf ...Config) {
-}
-
-foo({A: 1})
-bar({A: 2})
-foo({})
-bar({})
-`, `package main
-
-type Config struct {
-	A int
-}
-
-func foo(conf *Config) {
-}
-func bar(conf ...Config) {
-}
-func main() {
-	foo(&Config{A: 1})
-	bar(Config{A: 2})
-	foo(&Config{})
-	bar(Config{})
-}
-`)
-}
-
-// deduce struct type as results of a function call
-func TestCompositeLit4(t *testing.T) {
-	gopClTest(t, `
-type Result struct {
-	A int
-}
-
-func foo() *Result {
-	return {A: 1}
-}
-`, `package main
-
-type Result struct {
-	A int
-}
-
-func foo() *Result {
-	return &Result{A: 1}
-}
-`)
-}
-
-func TestCompositeLit5(t *testing.T) {
-	gopClTest(t, `
-type mymap map[float64]string
-var x = {1:"hello", 2:"world"}
-var y map[float64]string = {1:"hello", 2:"world"}
-var z mymap = {1:"hello", 2:"world"}
-`, `package main
-
-type mymap map[float64]string
-
-var x = map[int]string{1: "hello", 2: "world"}
-var y map[float64]string = map[float64]string{1: "hello", 2: "world"}
-var z mymap = mymap{1: "hello", 2: "world"}
-`)
-}
-
-func TestSliceLit(t *testing.T) {
-	gopClTest(t, `
-x := [1, 3.4, 5]
-y := [1]
-z := []
-`, `package main
-
-func main() {
-	x := []float64{1, 3.4, 5}
-	y := []int{1}
-	z := []interface {
-	}{}
-}
-`)
-	gopClTest(t, `
-type vector []float64
-var x = [1, 2, 3]
-var y []float64 = [1, 2, 3]
-var z vector = [1, 2, 3]
-`, `package main
-
-type vector []float64
-
-var x = []int{1, 2, 3}
-var y []float64 = []float64{1, 2, 3}
-var z vector = vector{1, 2, 3}
-`)
-}
-
-func TestChan(t *testing.T) {
-	gopClTest(t, `
-a := make(chan int, 10)
-a <- 3
-var b int = <-a
-x, ok := <-a
-`, `package main
-
-func main() {
-	a := make(chan int, 10)
-	a <- 3
-	var b int = <-a
-	x, ok := <-a
-}
-`)
-}
-
-func TestKeyValModeLit(t *testing.T) {
-	gopClTest(t, `
-a := [...]float64{1, 3: 3.4, 5}
-b := []float64{2: 1.2, 3, 6: 4.5}
-`, `package main
-
-func main() {
-	a := [...]float64{1, 3: 3.4, 5}
-	b := []float64{2: 1.2, 3, 6: 4.5}
-}
-`)
-}
-
-func TestStructLit(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-	A int
-	B string "tag1:123"
-}
-
-a := struct {
-	A int
-	B string "tag1:123"
-}{1, "Hello"}
-
-b := foo{1, "Hello"}
-c := foo{B: "Hi"}
-`, `package main
-
-type foo struct {
-	A int
-	B string `+"`tag1:123`"+`
-}
-
-func main() {
-	a := struct {
-		A int
-		B string `+"`tag1:123`"+`
-	}{1, "Hello"}
-	b := foo{1, "Hello"}
-	c := foo{B: "Hi"}
-}
-`)
-}
-
-func TestStructType(t *testing.T) {
-	gopClTest(t, `
-type bar = foo
-
-type foo struct {
-	p *bar
-	A int
-	B string "tag1:123"
-}
-
-func main() {
-	type a struct {
-		p *a
-	}
-	type b = a
-}
-`, `package main
-
-type bar = foo
-type foo struct {
-	p *foo
-	A int
-	B string `+"`tag1:123`"+`
-}
-
-func main() {
-	type a struct {
-		p *a
-	}
-	type b = a
-}
-`)
-}
-
-func TestDeferGo(t *testing.T) {
-	gopClTest(t, `
-go println("Hi")
-defer println("Go+")
-`, `package main
-
-import "fmt"
-
-func main() {
-	go fmt.Println("Hi")
-	defer fmt.Println("Go+")
-}
-`)
-}
-
-func TestFor(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3.4, 5]
-for i := 0; i < 3; i=i+1 {
-	println(i)
-}
-for {
-	println("loop")
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	a := []float64{1, 3.4, 5}
-	for i := 0; i < 3; i = i + 1 {
-		fmt.Println(i)
-	}
-	for {
-		fmt.Println("loop")
-	}
-}
-`)
-}
-
-func TestRangeStmt(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3.4, 5]
-for _, x := range a {
-	println(x)
-}
-for i, x := range a {
-	println(i, x)
-}
-
-var i int
-var x float64
-for _, x = range a {
-	println(i, x)
-}
-for i, x = range a {
-	println(i, x)
-}
-for range a {
-	println("Hi")
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	a := []float64{1, 3.4, 5}
-	for _, x := range a {
-		fmt.Println(x)
-	}
-	for i, x := range a {
-		fmt.Println(i, x)
-	}
-	var i int
-	var x float64
-	for _, x = range a {
-		fmt.Println(i, x)
-	}
-	for i, x = range a {
-		fmt.Println(i, x)
-	}
-	for range a {
-		fmt.Println("Hi")
-	}
-}
-`)
-}
-
-func TestRangeStmtUDT(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(key int, val string)) {
-}
-
-for k, v := range new(foo) {
-	println(k, v)
-}
-`, `package main
-
-import "fmt"
-
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(key int, val string)) {
-}
-func main() {
-	new(foo).Gop_Enum(func(k int, v string) {
-		fmt.Println(k, v)
-	})
-}
-`)
-}
-
-func TestForPhraseUDT(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(val string)) {
-}
-
-for v <- new(foo) {
-	println(v)
-}
-`, `package main
-
-import "fmt"
-
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(val string)) {
-}
-func main() {
-	new(foo).Gop_Enum(func(v string) {
-		fmt.Println(v)
-	})
-}
-`)
-}
-
-func TestForPhraseUDT2(t *testing.T) {
-	gopClTest(t, `
-type fooIter struct {
-}
-
-func (p fooIter) Next() (key string, val int, ok bool) {
-	return
-}
-
-type foo struct {
-}
-
-func (p *foo) Gop_Enum() fooIter {
-}
-
-for k, v <- new(foo) {
-	println(k, v)
-}
-`, `package main
-
-import "fmt"
-
-type fooIter struct {
-}
-type foo struct {
-}
-
-func (p fooIter) Next() (key string, val int, ok bool) {
-	return
-}
-func (p *foo) Gop_Enum() fooIter {
-}
-func main() {
-	for _gop_it := new(foo).Gop_Enum(); ; {
-		var _gop_ok bool
-		k, v, _gop_ok := _gop_it.Next()
-		if !_gop_ok {
-			break
-		}
-		fmt.Println(k, v)
-	}
-}
-`)
-}
-
-func TestForPhraseUDT3(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(val string)) {
-}
-
-println([v for v <- new(foo)])
-`, `package main
-
-import "fmt"
-
-type foo struct {
-}
-
-func (p *foo) Gop_Enum(c func(val string)) {
-}
-func main() {
-	fmt.Println(func() (_gop_ret []string) {
-		new(foo).Gop_Enum(func(v string) {
-			_gop_ret = append(_gop_ret, v)
-		})
-		return
-	}())
-}
-`)
-}
-
-func TestForPhraseUDT4(t *testing.T) {
-	gopClTest(t, `
-type fooIter struct {
-	data *foo
-	idx  int
-}
-
-func (p *fooIter) Next() (key int, val string, ok bool) {
-	if p.idx < len(p.data.key) {
-		key, val, ok = p.data.key[p.idx], p.data.val[p.idx], true
-		p.idx++
-	}
-	return
-}
-
-type foo struct {
-	key []int
-	val []string
-}
-
-func newFoo() *foo {
-	return &foo{key: [3, 7], val: ["Hi", "Go+"]}
-}
-
-func (p *foo) Gop_Enum() *fooIter {
-	return &fooIter{data: p}
-}
-
-for k, v <- newFoo() {
-	println(k, v)
-}
-`, `package main
-
-import "fmt"
-
-type fooIter struct {
-	data *foo
-	idx  int
-}
-type foo struct {
-	key []int
-	val []string
-}
-
-func (p *fooIter) Next() (key int, val string, ok bool) {
-	if p.idx < len(p.data.key) {
-		key, val, ok = p.data.key[p.idx], p.data.val[p.idx], true
-		p.idx++
-	}
-	return
-}
-func newFoo() *foo {
-	return &foo{key: []int{3, 7}, val: []string{"Hi", "Go+"}}
-}
-func (p *foo) Gop_Enum() *fooIter {
-	return &fooIter{data: p}
-}
-func main() {
-	for _gop_it := newFoo().Gop_Enum(); ; {
-		var _gop_ok bool
-		k, v, _gop_ok := _gop_it.Next()
-		if !_gop_ok {
-			break
-		}
-		fmt.Println(k, v)
-	}
-}
-`)
-}
-
-func TestForPhrase(t *testing.T) {
-	gopClTest(t, `
-sum := 0
-for x <- [1, 3, 5, 7, 11, 13, 17], x > 3 {
-	sum = sum + x
-}
-for i, x <- [1, 3, 5, 7, 11, 13, 17] {
-	sum = sum + i*x
-}
-println("sum(5,7,11,13,17):", sum)
-`, `package main
-
-import "fmt"
-
-func main() {
-	sum := 0
-	for _, x := range []int{1, 3, 5, 7, 11, 13, 17} {
-		if x > 3 {
-			sum = sum + x
-		}
-	}
-	for i, x := range []int{1, 3, 5, 7, 11, 13, 17} {
-		sum = sum + i*x
-	}
-	fmt.Println("sum(5,7,11,13,17):", sum)
-}
-`)
-}
-
-func TestMapComprehension(t *testing.T) {
-	gopClTest(t, `
-y := {x: i for i, x <- ["1", "3", "5", "7", "11"]}
-`, `package main
-
-func main() {
-	y := func() (_gop_ret map[string]int) {
-		_gop_ret = map[string]int{}
-		for i, x := range []string{"1", "3", "5", "7", "11"} {
-			_gop_ret[x] = i
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestMapComprehensionCond(t *testing.T) {
-	gopClTest(t, `
-z := {v: k for k, v <- {"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7}, v > 3}
-`, `package main
-
-func main() {
-	z := func() (_gop_ret map[int]string) {
-		_gop_ret = map[int]string{}
-		for k, v := range map[string]int{"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7} {
-			if v > 3 {
-				_gop_ret[v] = k
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestMapComprehensionCond2(t *testing.T) {
-	gopClTest(t, `
-z := {t: k for k, v <- {"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7}, t := v; t > 3}
-`, `package main
-
-func main() {
-	z := func() (_gop_ret map[int]string) {
-		_gop_ret = map[int]string{}
-		for k, v := range map[string]int{"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7} {
-			if t := v; t > 3 {
-				_gop_ret[t] = k
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestExistsComprehension(t *testing.T) {
-	gopClTest(t, `
-hasFive := {for x <- ["1", "3", "5", "7", "11"], x == "5"}
-`, `package main
-
-func main() {
-	hasFive := func() (_gop_ok bool) {
-		for _, x := range []string{"1", "3", "5", "7", "11"} {
-			if x == "5" {
-				return true
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestSelectComprehension(t *testing.T) {
-	gopClTest(t, `
-y := {i for i, x <- ["1", "3", "5", "7", "11"], x == "5"}
-`, `package main
-
-func main() {
-	y := func() (_gop_ret int) {
-		for i, x := range []string{"1", "3", "5", "7", "11"} {
-			if x == "5" {
-				return i
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestSelectComprehensionTwoValue(t *testing.T) {
-	gopClTest(t, `
-y, ok := {i for i, x <- ["1", "3", "5", "7", "11"], x == "5"}
-`, `package main
-
-func main() {
-	y, ok := func() (_gop_ret int, _gop_ok bool) {
-		for i, x := range []string{"1", "3", "5", "7", "11"} {
-			if x == "5" {
-				return i, true
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestSelectComprehensionRetTwoValue(t *testing.T) {
-	gopClTest(t, `
-func foo() (int, bool) {
-	return {i for i, x <- ["1", "3", "5", "7", "11"], x == "5"}
-}
-`, `package main
-
-func foo() (int, bool) {
-	return func() (_gop_ret int, _gop_ok bool) {
-		for i, x := range []string{"1", "3", "5", "7", "11"} {
-			if x == "5" {
-				return i, true
-			}
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestListComprehension(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3.4, 5]
-b := [x*x for x <- a]
-`, `package main
-
-func main() {
-	a := []float64{1, 3.4, 5}
-	b := func() (_gop_ret []float64) {
-		for _, x := range a {
-			_gop_ret = append(_gop_ret, x*x)
-		}
-		return
-	}()
-}
-`)
-}
-
-func TestListComprehensionMultiLevel(t *testing.T) {
-	gopClTest(t, `
-arr := [1, 2, 3, 4.1, 5, 6]
-x := [[a, b] for a <- arr, a < b for b <- arr, b > 2]
-println("x:", x)
-`, `package main
-
-import "fmt"
-
-func main() {
-	arr := []float64{1, 2, 3, 4.1, 5, 6}
-	x := func() (_gop_ret [][]float64) {
-		for _, b := range arr {
-			if b > 2 {
-				for _, a := range arr {
-					if a < b {
-						_gop_ret = append(_gop_ret, []float64{a, b})
-					}
-				}
-			}
-		}
-		return
-	}()
-	fmt.Println("x:", x)
-}
-`)
-}
-
-func TestSliceGet(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3, 5, 7, 9]
-b := a[:3]
-c := a[1:]
-d := a[1:2:3]
-e := "Hello, Go+"[7:]
-`, `package main
-
-func main() {
-	a := []int{1, 3, 5, 7, 9}
-	b := a[:3]
-	c := a[1:]
-	d := a[1:2:3]
-	e := "Hello, Go+"[7:]
-}
-`)
-}
-
-func TestIndexGetTwoValue(t *testing.T) {
-	gopClTest(t, `
-a := {"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7}
-x, ok := a["Hi"]
-y := a["Go+"]
-`, `package main
-
-func main() {
-	a := map[string]int{"Hello": 1, "Hi": 3, "xsw": 5, "Go+": 7}
-	x, ok := a["Hi"]
-	y := a["Go+"]
-}
-`)
-}
-
-func TestIndexGet(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3.4, 5]
-b := a[1]
-`, `package main
-
-func main() {
-	a := []float64{1, 3.4, 5}
-	b := a[1]
-}
-`)
-}
-
-func TestIndexRef(t *testing.T) {
-	gopClTest(t, `
-a := [1, 3.4, 5]
-a[1] = 2.1
-`, `package main
-
-func main() {
-	a := []float64{1, 3.4, 5}
-	a[1] = 2.1
-}
-`)
-}
-
-func TestIndexArrayPtrIssue784(t *testing.T) {
-	gopClTest(t, `
-type intArr [2]int
-
-func foo(a *intArr) {
-	a[1] = 10
-}
-`, `package main
-
-type intArr [2]int
-
-func foo(a *intArr) {
-	a[1] = 10
-}
-`)
-}
-
-func TestMemberVal(t *testing.T) {
-	gopClTest(t, `import "strings"
-
-x := strings.NewReplacer("?", "!").Replace("hello, world???")
-println("x:", x)
-`, `package main
-
-import (
-	"fmt"
-	"strings"
-)
-
-func main() {
-	x := strings.NewReplacer("?", "!").Replace("hello, world???")
-	fmt.Println("x:", x)
-}
-`)
-}
-
-func TestNamedPtrMemberIssue786(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-	req int
-}
-
-type pfoo *foo
-
-func bar(p pfoo) {
-	println(p.req)
-}
-`, `package main
-
-import "fmt"
-
-type foo struct {
-	req int
-}
-type pfoo *foo
-
-func bar(p pfoo) {
-	fmt.Println(p.req)
-}
-`)
-}
-
-func TestMember(t *testing.T) {
-	gopClTest(t, `
-
-import "flag"
-
-a := &struct {
-	A int
-	B string
-}{1, "Hello"}
-
-x := a.A
-a.B = "Hi"
-
-flag.Usage = nil
-`, `package main
-
-import "flag"
-
-func main() {
-	a := &struct {
-		A int
-		B string
-	}{1, "Hello"}
-	x := a.A
-	a.B = "Hi"
-	flag.Usage = nil
-}
-`)
-}
-
-func TestElem(t *testing.T) {
-	gopClTest(t, `
-
-func foo(a *int, b int) {
-	b = *a
-	*a = b
-}
-`, `package main
-
-func foo(a *int, b int) {
-	b = *a
-	*a = b
-}
-`)
-}
-
-func TestNamedPtrIssue797(t *testing.T) {
-	gopClTest(t, `
-type Bar *int
-
-func foo(a Bar) {
-	var b int = *a
-}
-`, `package main
-
-type Bar *int
-
-func foo(a Bar) {
-	var b int = *a
-}
-`)
-}
-
-func TestMethod(t *testing.T) {
-	gopClTest(t, `
-type M int
-
-func (m M) Foo() {
-	println("foo", m)
-}
-
-func (M) Bar() {
-	println("bar")
-}
-`, `package main
-
-import "fmt"
-
-type M int
-
-func (m M) Foo() {
-	fmt.Println("foo", m)
-}
-func (M) Bar() {
-	fmt.Println("bar")
-}
-`)
-}
-
-func TestOverloadOp(t *testing.T) {
-	gopClTest(t, `
-type foo struct {
-}
-
-func (a *foo) + (b *foo) *foo {
-	println("a + b")
-	return &foo{}
-}
-
-func (a foo) - (b foo) foo {
-	println("a - b")
-	return foo{}
-}
-
-func -(a foo) {
-	println("-a")
-}
-
-func ++(a foo) {
-	println("a++")
-}
-
-func (a foo) != (b foo) bool{
-	println("a!=b")	
-	return true
-}
-
-var a, b foo
-var c = a - b
-var d = -a       // TODO: -a have no return value!
-var e = a!=b
-`, `package main
-
-import "fmt"
-
-type foo struct {
-}
-
-var a, b foo
-var c = a.Gop_Sub(b)
-var d = a.Gop_Neg()
-var e = a.Gop_NE(b)
-
-func (a *foo) Gop_Add(b *foo) *foo {
-	fmt.Println("a + b")
-	return &foo{}
-}
-func (a foo) Gop_Sub(b foo) foo {
-	fmt.Println("a - b")
-	return foo{}
-}
-func (a foo) Gop_Neg() {
-	fmt.Println("-a")
-}
-func (a foo) Gop_Inc() {
-	fmt.Println("a++")
-}
-func (a foo) Gop_NE(b foo) bool {
-	fmt.Println("a!=b")
-	return true
-}
-`)
-}
-
-func TestCmdlineNoEOL(t *testing.T) {
-	gopClTest(t, `println "Hi"`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hi")
-}
-`)
-}
-
-func TestImport(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func main() {
-	fmt.println "Hi"
-}`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hi")
-}
-`)
-}
-
-func TestDotImport(t *testing.T) {
-	gopClTest(t, `import . "math"
-
-var a = round(1.2)
-`, `package main
-
-import "math"
-
-var a = math.Round(1.2)
-`)
-}
-
-func TestLocalImport(t *testing.T) {
-	gopClTest(t, `import "./internal/spx"
-
-var a = spx.TestIntValue
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/spx"
-
-var a = spx.TestIntValue
-`)
-}
-
-func TestImportUnused(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func main() {
-}`, `package main
-
-func main() {
-}
-`)
-}
-
-func TestImportForceUsed(t *testing.T) {
-	gopClTest(t, `import _ "fmt"
-
-func main() {
-}`, `package main
-
-import _ "fmt"
-
-func main() {
-}
-`)
-}
-
-func TestAnonymousImport(t *testing.T) {
-	gopClTest(t, `println("Hello")
-printf("Hello Go+\n")
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hello")
-	fmt.Printf("Hello Go+\n")
-}
-`)
-}
-
-func TestVarAndConst(t *testing.T) {
-	gopClTest(t, `
-const (
-	i = 1
-	x float64 = 1
-)
-var j int = i
-`, `package main
-
-const (
-	i         = 1
-	x float64 = 1
-)
-
-var j int = i
-`)
-}
-
-func TestDeclStmt(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func main() {
-	const (
-		i = 1
-		x float64 = 1
-	)
-	var j int = i
-	fmt.Println("Hi")
-}`, `package main
-
-import "fmt"
-
-func main() {
-	const (
-		i         = 1
-		x float64 = 1
-	)
-	var j int = i
-	fmt.Println("Hi")
-}
-`)
-}
-
-func TestIf(t *testing.T) {
-	gopClTest(t, `x := 0
-if t := false; t {
-	x = 3
-} else if !t {
-	x = 5
-} else {
-	x = 7
-}
-println("x:", x)
-`, `package main
-
-import "fmt"
-
-func main() {
-	x := 0
-	if t := false; t {
-		x = 3
-	} else if !t {
-		x = 5
-	} else {
-		x = 7
-	}
-	fmt.Println("x:", x)
-}
-`)
-}
-
-func TestSwitch(t *testing.T) {
-	gopClTest(t, `x := 0
-switch s := "Hello"; s {
-default:
-	x = 7
-case "world", "hi":
-	x = 5
-case "xsw":
-	x = 3
-}
-println("x:", x)
-
-v := "Hello"
-switch {
-case v == "xsw":
-	x = 3
-case v == "hi", v == "world":
-	x = 9
-default:
-	x = 11
-}
-println("x:", x)
-`, `package main
-
-import "fmt"
-
-func main() {
-	x := 0
-	switch s := "Hello"; s {
-	default:
-		x = 7
-	case "world", "hi":
-		x = 5
-	case "xsw":
-		x = 3
-	}
-	fmt.Println("x:", x)
-	v := "Hello"
-	switch {
-	case v == "xsw":
-		x = 3
-	case v == "hi", v == "world":
-		x = 9
-	default:
-		x = 11
-	}
-	fmt.Println("x:", x)
-}
-`)
-}
-
-func TestSwitchFallthrough(t *testing.T) {
-	gopClTest(t, `v := "Hello"
-switch v {
-case "Hello":
-	println(v)
-	fallthrough
-case "hi":
-	println(v)
-	fallthrough
-default:
-	println(v)
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	v := "Hello"
-	switch v {
-	case "Hello":
-		fmt.Println(v)
-		fallthrough
-	case "hi":
-		fmt.Println(v)
-		fallthrough
-	default:
-		fmt.Println(v)
-	}
-}
-`)
-}
-
-func TestBranchStmt(t *testing.T) {
-	gopClTest(t, `
-	a := [1, 3.4, 5]
-label:
-	for i := 0; i < 3; i=i+1 {
-		println(i)
-		break
-		break label
-		continue
-		continue label
-		goto label
-	}
-`, `package main
-
-import "fmt"
-
-func main() {
-	a := []float64{1, 3.4, 5}
-label:
-	for i := 0; i < 3; i = i + 1 {
-		fmt.Println(i)
-		break
-		break label
-		continue
-		continue label
-		goto label
-	}
-}
-`)
-}
-
-func TestReturn(t *testing.T) {
-	gopClTest(t, `
-func foo(format string, args ...interface{}) (int, error) {
-	return printf(format, args...)
-}
-
-func main() {
-}
-`, `package main
-
-import "fmt"
-
-func foo(format string, args ...interface {
-}) (int, error) {
-	return fmt.Printf(format, args...)
-}
-func main() {
-}
-`)
-}
-
-func TestReturnExpr(t *testing.T) {
-	gopClTest(t, `
-func foo(format string, args ...interface{}) (int, error) {
-	return 0, nil
-}
-
-func main() {
-}
-`, `package main
-
-func foo(format string, args ...interface {
-}) (int, error) {
-	return 0, nil
-}
-func main() {
-}
-`)
-}
-
-func TestClosure(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func(v string) {
-	fmt.Println(v)
-}("Hello")
-`, `package main
-
-import "fmt"
-
-func main() {
-	func(v string) {
-		fmt.Println(v)
-	}("Hello")
-}
-`)
-}
-
-func TestFunc(t *testing.T) {
-	gopClTest(t, `func foo(format string, a [10]int, args ...interface{}) {
-}
-
-func main() {
-}`, `package main
-
-func foo(format string, a [10]int, args ...interface {
-}) {
-}
-func main() {
-}
-`)
-}
-
-func TestLambdaExpr(t *testing.T) {
-	gopClTest(t, `
-func Map(c []float64, t func(float64) float64) {
-	// ...
-}
-
-func Map2(c []float64, t func(float64) (float64, float64)) {
-	// ...
-}
-
-Map([1.2, 3.5, 6], x => x * x)
-Map2([1.2, 3.5, 6], x => (x * x, x + x))
-`, `package main
-
-func Map(c []float64, t func(float64) float64) {
-}
-func Map2(c []float64, t func(float64) (float64, float64)) {
-}
-func main() {
-	Map([]float64{1.2, 3.5, 6}, func(x float64) float64 {
-		return x * x
-	})
-	Map2([]float64{1.2, 3.5, 6}, func(x float64) (float64, float64) {
-		return x * x, x + x
-	})
-}
-`)
-	gopClTest(t, `type Foo struct {
-	Plot func(x float64) (float64, float64)
-}
-foo := &Foo{
-	Plot: x => (x * 2, x * x),
-}`, `package main
-
-type Foo struct {
-	Plot func(x float64) (float64, float64)
-}
-
-func main() {
-	foo := &Foo{Plot: func(x float64) (float64, float64) {
-		return x * 2, x * x
-	}}
-}
-`)
-	gopClTest(t, `
-type Fn func(x float64) (float64, float64)
-type Foo struct {
-	Plot Fn
-}
-foo := &Foo{
-	Plot: x => (x * 2, x * x),
-}`, `package main
-
-type Fn func(x float64) (float64, float64)
-type Foo struct {
-	Plot Fn
-}
-
-func main() {
-	foo := &Foo{Plot: func(x float64) (float64, float64) {
-		return x * 2, x * x
-	}}
-}
-`)
-	gopClTest(t, `
-type Fn func() (int, error)
-func Do(fn Fn) {
-}
-
-Do => (100, nil)
-`, `package main
-
-type Fn func() (int, error)
-
-func Do(fn Fn) {
-}
-func main() {
-	Do(func() (int, error) {
-		return 100, nil
-	})
-}
-`)
-	gopClTest(t, `
-var fn func(int) (int,error) = x => (x*x, nil)
-`, `package main
-
-var fn func(int) (int, error) = func(x int) (int, error) {
-	return x * x, nil
-}
-`)
-	gopClTest(t, `
-var fn func(int) (int,error)
-fn = x => (x*x, nil)
-`, `package main
-
-var fn func(int) (int, error)
-
-func main() {
-	fn = func(x int) (int, error) {
-		return x * x, nil
-	}
-}
-`)
-}
-
-func TestLambdaExpr2(t *testing.T) {
-	gopClTest(t, `
-func Do(func()) {
-	// ...
-}
-
-Do => {
-	println "Hi"
-}
-`, `package main
-
-import "fmt"
-
-func Do(func()) {
-}
-func main() {
-	Do(func() {
-		fmt.Println("Hi")
-	})
-}
-`)
-	gopClTest(t, `
-func Do(fn func() (int, error)) {
-	// ...
-}
-
-Do => {
-	return 100, nil
-}
-`, `package main
-
-func Do(fn func() (int, error)) {
-}
-func main() {
-	Do(func() (int, error) {
-		return 100, nil
-	})
-}
-`)
-	gopClTest(t, `type Foo struct {
-	Plot func(x float64) (float64, float64)
-}
-foo := &Foo{
-	Plot: x => {
-		return x * 2, x * x
-	},
-}`, `package main
-
-type Foo struct {
-	Plot func(x float64) (float64, float64)
-}
-
-func main() {
-	foo := &Foo{Plot: func(x float64) (float64, float64) {
-		return x * 2, x * x
-	}}
-}
-`)
-	gopClTest(t, `
-type Fn func(x float64) (float64, float64)
-type Foo struct {
-	Plot Fn
-}
-foo := &Foo{
-	Plot: x => {
-		return x * 2, x * x
-	},
-}`, `package main
-
-type Fn func(x float64) (float64, float64)
-type Foo struct {
-	Plot Fn
-}
-
-func main() {
-	foo := &Foo{Plot: func(x float64) (float64, float64) {
-		return x * 2, x * x
-	}}
-}
-`)
-
-	gopClTest(t, `
-type Fn func() (int, error)
-func Do(fn Fn) {
-}
-
-Do => {
-	return 100, nil
-}
-`, `package main
-
-type Fn func() (int, error)
-
-func Do(fn Fn) {
-}
-func main() {
-	Do(func() (int, error) {
-		return 100, nil
-	})
-}
-`)
-	gopClTest(t, `
-var fn func(int) (int,error) = x => {
-	return x * x, nil
-}
-`, `package main
-
-var fn func(int) (int, error) = func(x int) (int, error) {
-	return x * x, nil
-}
-`)
-	gopClTest(t, `
-var fn func(int) (int,error)
-fn = x => {
-	return x * x, nil
-}
-`, `package main
-
-var fn func(int) (int, error)
-
-func main() {
-	fn = func(x int) (int, error) {
-		return x * x, nil
-	}
-}
-`)
-}
-
-func TestLambdaExpr3(t *testing.T) {
-	gopClTest(t, `
-func intSeq() func() int {
-	i := 0
-	return => {
-		i++
-		return i
-	}
-}
-`, `package main
-
-func intSeq() func() int {
-	i := 0
-	return func() int {
-		i++
-		return i
-	}
-}
-`)
-	gopClTest(t, `
-func intDouble() func(int) int {
-	return i => i*2
-}
-`, `package main
-
-func intDouble() func(int) int {
-	return func(i int) int {
-		return i * 2
-	}
-}
-`)
-}
-
-func TestUnnamedMainFunc(t *testing.T) {
-	gopClTest(t, `i := 1`, `package main
-
-func main() {
-	i := 1
-}
-`)
-}
-
-func TestFuncAsParam(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func bar(foo func(string, ...interface{}) (int, error)) {
-	foo("Hello, %v!\n", "Go+")
-}
-
-bar(fmt.Printf)
-`, `package main
-
-import "fmt"
-
-func bar(foo func(string, ...interface {
-}) (int, error)) {
-	foo("Hello, %v!\n", "Go+")
-}
-func main() {
-	bar(fmt.Printf)
-}
-`)
-}
-
-func TestFuncAsParam2(t *testing.T) {
-	gopClTest(t, `import (
-	"fmt"
-	"strings"
-)
-
-func foo(x string) string {
-	return strings.NewReplacer("?", "!").Replace(x)
-}
-
-func printf(format string, args ...interface{}) (n int, err error) {
-	n, err = fmt.Printf(format, args...)
-	return
-}
-
-func bar(foo func(string, ...interface{}) (int, error)) {
-	foo("Hello, %v!\n", "Go+")
-}
-
-bar(printf)
-fmt.Println(foo("Hello, world???"))
-fmt.Println(printf("Hello, %v\n", "Go+"))
-`, `package main
-
-import (
-	"fmt"
-	"strings"
-)
-
-func foo(x string) string {
-	return strings.NewReplacer("?", "!").Replace(x)
-}
-func printf(format string, args ...interface {
-}) (n int, err error) {
-	n, err = fmt.Printf(format, args...)
-	return
-}
-func bar(foo func(string, ...interface {
-}) (int, error)) {
-	foo("Hello, %v!\n", "Go+")
-}
-func main() {
-	bar(printf)
-	fmt.Println(foo("Hello, world???"))
-	fmt.Println(printf("Hello, %v\n", "Go+"))
-}
-`)
-}
-
-func TestFuncCall(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-fmt.Println("Hello")`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("Hello")
-}
-`)
-}
-
-func TestFuncCallEllipsis(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func foo(args ...interface{}) {
-	fmt.Println(args...)
-}
-
-func main() {
-}`, `package main
-
-import "fmt"
-
-func foo(args ...interface {
-}) {
-	fmt.Println(args...)
-}
-func main() {
-}
-`)
-}
-
-func TestFuncCallCodeOrder(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func main() {
-	foo("Hello", 123)
-}
-
-func foo(args ...interface{}) {
-	fmt.Println(args...)
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	foo("Hello", 123)
-}
-func foo(args ...interface {
-}) {
-	fmt.Println(args...)
-}
-`)
-}
-
-func TestInterfaceMethods(t *testing.T) {
-	gopClTest(t, `package main
-
-func foo(v ...interface { Bar() }) {
-}
-
-func main() {
-}`, `package main
-
-func foo(v ...interface {
-	Bar()
-}) {
-}
-func main() {
-}
-`)
-}
-
-func TestAssignUnderscore(t *testing.T) {
-	gopClTest(t, `import log "fmt"
-
-_, err := log.Println("Hello")
-`, `package main
-
-import "fmt"
-
-func main() {
-	_, err := fmt.Println("Hello")
-}
-`)
-}
-
-func TestOperator(t *testing.T) {
-	gopClTest(t, `
-a := "Hi"
-b := a + "!"
-c := 13
-d := -c
-`, `package main
-
-func main() {
-	a := "Hi"
-	b := a + "!"
-	c := 13
-	d := -c
-}
-`)
-}
-
-var (
-	autogen sync.Mutex
-)
-
-func removeAutogenFiles() {
-	os.Remove("./internal/gop-in-go/foo/gop_autogen.go")
-	os.Remove("./internal/gop-in-go/foo/gop_autogen_test.go")
-	os.Remove("./internal/gop-in-go/foo/gop_autogen2_test.go")
-}
-
-func _TestImportGopPkg(t *testing.T) {
-	autogen.Lock()
-	defer autogen.Unlock()
-
-	dir, _ := os.Getwd()
-	os.Chdir("../..")
-	defer os.Chdir(dir)
-
-	removeAutogenFiles()
-	gopClTest(t, `import "github.com/goplus/gop/cl/internal/gop-in-go/foo"
-
-rmap := foo.ReverseMap(map[string]int{"Hi": 1, "Hello": 2})
-println(rmap)
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/cl/internal/gop-in-go/foo"
-)
-
-func main() {
-	rmap := foo.ReverseMap(map[string]int{"Hi": 1, "Hello": 2})
-	fmt.Println(rmap)
-}
-`)
-}
-
-func TestCallDep(t *testing.T) {
-	for i := 0; i < 2; i++ {
-		gopClTest(t, `
-import (
-	"reflect"
-	"testing"
-)
-
-func TestNew(t *testing.T) {
-	ret := New()
-	expected := Result{}
-	if reflect.DeepEqual(ret, expected) {
-		t.Fatal("Test failed:", ret, expected)
-	}
-}
-
-type Repo struct {
-	Title string
-}
-
-func newRepo() Repo {
-	return {Title: "Hi"}
-}
-
-type Result struct {
-	Repo Repo
-}
-
-func New() Result {
-	repo := newRepo()
-	return {Repo: repo}
-}
-`, `package main
-
-import (
-	"reflect"
-	"testing"
-)
-
-type Repo struct {
-	Title string
-}
-type Result struct {
-	Repo Repo
-}
-
-func TestNew(t *testing.T) {
-	ret := New()
-	expected := Result{}
-	if reflect.DeepEqual(ret, expected) {
-		t.Fatal("Test failed:", ret, expected)
-	}
-}
-func newRepo() Repo {
-	return Repo{Title: "Hi"}
-}
-func New() Result {
-	repo := newRepo()
-	return Result{Repo: repo}
-}
-`)
-	}
-}
-
-func testRangeExpr(t *testing.T, codeTpl, expect string) {
-	for k, s := range []string{" <- ", " := range ", " = range "} {
-		if k == 2 {
-			codeTpl = "i:=0\n" + codeTpl
-			expect = strings.Replace(expect, "for i := ", "i := 0\n\tfor i = ", -1)
-		}
-		gopClTest(t, strings.Replace(codeTpl, "$", s, -1), expect)
-	}
-}
-
-func TestRangeExpr(t *testing.T) {
-	testRangeExpr(t, `
-for i $ :10 {
-	println(i)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 0; i < 10; i += 1 {
-		fmt.Println(i)
-	}
-}
-`)
-	testRangeExpr(t, `
-for i $ 1:10:3 {
-	println(i)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 1; i < 10; i += 3 {
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestRangeExpr2(t *testing.T) {
-	testRangeExpr(t, `
-for i $ 1:10:2 {
-	println(i)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 1; i < 10; i += 2 {
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestRangeExpr3(t *testing.T) {
-	testRangeExpr(t, `
-for i $ 1:10 {
-	println(i)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 1; i < 10; i += 1 {
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestRangeExpr4(t *testing.T) {
-	testRangeExpr(t, `
-for i $ :10:2 {
-	println(i)
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for i := 0; i < 10; i += 2 {
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestRangeExpr5(t *testing.T) {
-	gopClTest(t, `
-for range :10 {
-	println("Hi")
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for _gop_k := 0; _gop_k < 10; _gop_k += 1 {
-		fmt.Println("Hi")
-	}
-}
-`)
-}
-
-func TestRangeExpr6(t *testing.T) {
-	gopClTest(t, `
-for _ <- :10 {
-	println("Hi")
-}`, `package main
-
-import "fmt"
-
-func main() {
-	for _gop_k := 0; _gop_k < 10; _gop_k += 1 {
-		fmt.Println("Hi")
-	}
-}
-`)
-}
-
-func TestRangeExpr7(t *testing.T) {
-	gopClTest(t, `
-println [x for x <- 0:3:1]
-`, `package main
-
-import (
-	"fmt"
-	"github.com/goplus/gop/builtin"
-)
-
-func main() {
-	fmt.Println(func() (_gop_ret []int) {
-		for _gop_it := builtin.NewRange__0(0, 3, 1).Gop_Enum(); ; {
-			var _gop_ok bool
-			x, _gop_ok := _gop_it.Next()
-			if !_gop_ok {
-				break
-			}
-			_gop_ret = append(_gop_ret, x)
-		}
-		return
-	}())
-}
-`)
-}
-
-func testRangeExpr8(t *testing.T, codeTpl, expect string) {
-	for _, s := range []string{" <- ", " := range "} {
-		gopClTest(t, strings.Replace(codeTpl, "$", s, -1), expect)
-	}
-}
-
-func TestRangeExpr8(t *testing.T) {
-	testRangeExpr8(t, `
-	type T struct{}
-
-	func (t T)start()int{
-		return 0
-	}
-	func (t T)end()int{
-		return 3 
-	}
-	func (t T)step()int{
-		return 1 
-	}
-	
-	t:=T{}
-	
-	for i <- t.start():t.end():t.step(){
-		println i
-	}
-	`, `package main
-
-import "fmt"
-
-type T struct {
-}
-
-func (t T) start() int {
-	return 0
-}
-func (t T) end() int {
-	return 3
-}
-func (t T) step() int {
-	return 1
-}
-func main() {
-	t := T{}
-	for i, _gop_end, _gop_step := t.start(), t.end(), t.step(); i < _gop_end; i += _gop_step {
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestRangeExpr9(t *testing.T) {
-	testRangeExpr8(t, `
-	type T struct{}
-
-	func (t T)start()int{
-		return 0
-	}
-	func (t T)end()int{
-		return 3 
-	}
-	func (t T)step()int{
-		return 1 
-	}
-	
-	t:=T{}
-	i:=0
-	for i =range t.start():t.end():t.step(){
-		println i
-	}
-	`, `package main
-
-import "fmt"
-
-type T struct {
-}
-
-func (t T) start() int {
-	return 0
-}
-func (t T) end() int {
-	return 3
-}
-func (t T) step() int {
-	return 1
-}
-func main() {
-	t := T{}
-	i := 0
-	for _gop_k, _gop_end, _gop_step := t.start(), t.end(), t.step(); _gop_k < _gop_end; _gop_k += _gop_step {
-		i = _gop_k
-		fmt.Println(i)
-	}
-}
-`)
-}
-
-func TestGoFuncInstr(t *testing.T) {
-	gopClTest(t, `package main
-
-//go:noinline
-//go:uintptrescapes
-func test(s string, p, q uintptr, rest ...uintptr) int {
-}`, `package main
-//go:noinline
-//go:uintptrescapes
-func test(s string, p uintptr, q uintptr, rest ...uintptr) int {
-}
-`)
-}
-
-func TestGoTypeInstr(t *testing.T) {
-	gopClTest(t, `package main
-
-//go:notinheap
-type S struct{ x int }
-`, `package main
-//go:notinheap
-type S struct {
-	x int
-}
-`)
-}
-
-func TestNoEntrypoint(t *testing.T) {
-	gopClTest(t, `println("init")
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("init")
-}
-`)
-	gopClTestEx(t, gblConf, "bar", `package bar
-println("init")
-`, `package bar
-
-import "fmt"
-
-func init() {
-	fmt.Println("init")
-}
-`)
-}
-
-func TestParentExpr(t *testing.T) {
-	gopClTest(t, `var t1 *(int)
-var t2 chan (int)
-`, `package main
-
-var t1 *int
-var t2 chan int
-`)
-}
-
-func TestCommandStyle(t *testing.T) {
-	gopClTest(t, `
-println []
-println {}
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println([]interface {
-	}{})
-	fmt.Println(map[string]interface {
-	}{})
-}
-`)
-}
-
-func TestTypeLoader(t *testing.T) {
-	gopClTest(t, `import "fmt"
-
-func (p *Point) String() string {
-	return fmt.Sprintf("%v-%v",p.X,p.Y)
-}
-
-type Point struct {
-	X int
-	Y int
-}
-`, `package main
-
-import "fmt"
-
-type Point struct {
-	X int
-	Y int
-}
-
-func (p *Point) String() string {
-	return fmt.Sprintf("%v-%v", p.X, p.Y)
-}
-`)
-}
-
-func TestCallPrintln(t *testing.T) {
-	gopClTest(t, `
-print
-print "hello"
-print("hello")
-println
-println "hello"
-println("hello")
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Print()
-	fmt.Print("hello")
-	fmt.Print("hello")
-	fmt.Println()
-	fmt.Println("hello")
-	fmt.Println("hello")
-}
-`)
-}
-
-func TestAnyAlias(t *testing.T) {
-	gopClTest(t, `
-var a any = 100
-println(a)
-`, `package main
-
-import "fmt"
-
-var a interface {
-} = 100
-
-func main() {
-	fmt.Println(a)
-}
-`)
-}
-
-func TestMainEntry(t *testing.T) {
-	conf := *gblConf
-	conf.NoAutoGenMain = false
-
-	gopClTestEx(t, &conf, "main", `
-`, `package main
-
-func main() {
-}
-`)
-	gopClTestEx(t, &conf, "main", `
-func test() {
-	println "hello"
-}
-`, `package main
-
-import "fmt"
-
-func test() {
-	fmt.Println("hello")
-}
-func main() {
-}
-`)
-
-	gopClTestEx(t, &conf, "main", `
-func main() {
-	println "hello"
-}
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println("hello")
-}
-`)
-}
-
-func TestCommandNotExpr(t *testing.T) {
-	gopClTest(t, `
-println !true
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println(false)
-}
-`)
-	gopClTest(t, `
-a := true
-println !a
-`, `package main
-
-import "fmt"
-
-func main() {
-	a := true
-	fmt.Println(!a)
-}
-`)
-	gopClTest(t, `
-println !func() bool { return true }()
-`, `package main
-
-import "fmt"
-
-func main() {
-	fmt.Println(!func() bool {
-		return true
-	}())
-}
-`)
-}
-
-func TestClassFileGopx(t *testing.T) {
-	gopClTestFile(t, `
-var (
-	BaseClass
-	Width, Height float64
-	*AggClass
-)
-
-type BaseClass struct{
-	x int
-	y int
-}
-type AggClass struct{}
-
-func Area() float64 {
-	return Width * Height
-}
-`, `package main
-
-type Rect struct {
-	BaseClass
-	Width  float64
-	Height float64
-	*AggClass
-}
-type BaseClass struct {
-	x int
-	y int
-}
-type AggClass struct {
-}
-
-func (this *Rect) Area() float64 {
-	return this.Width * this.Height
-}
-`, "Rect.gox")
-	gopClTestFile(t, `
-import "bytes"
-var (
-	bytes.Buffer
-)
-func test(){}
-`, `package main
-
-import "bytes"
-
-type Rect struct {
-	bytes.Buffer
-}
-
-func (this *Rect) test() {
-}
-`, "Rect.gox")
-	gopClTestFile(t, `
-import "bytes"
-var (
-	*bytes.Buffer
-)
-func test(){}
-`, `package main
-
-import "bytes"
-
-type Rect struct {
-	*bytes.Buffer
-}
-
-func (this *Rect) test() {
-}
-`, "Rect.gox")
-	gopClTestFile(t, `
-import "bytes"
-var (
-	*bytes.Buffer "spec:\"buffer\""
-	a int "json:\"a\""
-	b int
-)
-func test(){}
-`, `package main
-
-import "bytes"
-
-type Rect struct {
-	*bytes.Buffer `+"`spec:\"buffer\"`"+`
-	a             int `+"`json:\"a\"`"+`
-	b             int
-}
-
-func (this *Rect) test() {
-}
-`, "Rect.gox")
-}
-
-func TestOverload(t *testing.T) {
-	gopClTest(t, `
-import "github.com/goplus/gop/cl/internal/overload/foo"
-
-type Mesh struct {
-}
-
-func (p *Mesh) Name() string {
-	return "hello"
-}
-
-var (
-	m1 = &Mesh{}
-	m2 = &Mesh{}
-)
-
-foo.onKey "hello", => {
-}
-foo.onKey "hello", key => {
-}
-foo.onKey ["1"], => {
-}
-foo.onKey ["2"], key => {
-}
-foo.onKey [m1,m2], => {
-}
-foo.onKey [m1,m2], key => {
-}
-foo.onKey ["a"], ["b"], key => {
-}
-foo.onKey ["a"], [m1,m2], key => {
-}
-foo.onKey ["a"],nil,key => {
-}
-n := &foo.N{}
-n.onKey "hello", => {
-}
-n.onKey "hello", key => {
-}
-n.onKey ["1"], => {
-}
-n.onKey ["2"], key => {
-}
-n.onKey [m1,m2], => {
-}
-n.onKey [m1,m2], key => {
-}
-n.onKey ["a"], ["b"], key => {
-}
-n.onKey ["a"], [m1,m2], key => {
-}
-n.onKey ["a"],nil,key => {
-}
-`, `package main
-
-import "github.com/goplus/gop/cl/internal/overload/foo"
-
-type Mesh struct {
-}
-
-var (
-	m1 = &Mesh{}
-	m2 = &Mesh{}
-)
-
-func (p *Mesh) Name() string {
-	return "hello"
-}
-func main() {
-	foo.OnKey__0("hello", func() {
-	})
-	foo.OnKey__1("hello", func(key string) {
-	})
-	foo.OnKey__2([]string{"1"}, func() {
-	})
-	foo.OnKey__3([]string{"2"}, func(key string) {
-	})
-	foo.OnKey__4([]foo.Mesher{m1, m2}, func() {
-	})
-	foo.OnKey__5([]foo.Mesher{m1, m2}, func(key foo.Mesher) {
-	})
-	foo.OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
-	})
-	foo.OnKey__7([]string{"a"}, []foo.Mesher{m1, m2}, func(key string) {
-	})
-	foo.OnKey__6([]string{"a"}, nil, func(key string) {
-	})
-	n := &foo.N{}
-	n.OnKey__0("hello", func() {
-	})
-	n.OnKey__1("hello", func(key string) {
-	})
-	n.OnKey__2([]string{"1"}, func() {
-	})
-	n.OnKey__3([]string{"2"}, func(key string) {
-	})
-	n.OnKey__4([]foo.Mesher{m1, m2}, func() {
-	})
-	n.OnKey__5([]foo.Mesher{m1, m2}, func(key foo.Mesher) {
-	})
-	n.OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
-	})
-	n.OnKey__7([]string{"a"}, []foo.Mesher{m1, m2}, func(key string) {
-	})
-	n.OnKey__6([]string{"a"}, nil, func(key string) {
-	})
-}
-`)
-}
-
-func TestClassFileMember(t *testing.T) {
-	gopClTestFile(t, `type Engine struct {
-}
-
-func (e *Engine) EnterPointerLock() {
-}
-
-func (e *Engine) SetEnable(b bool) {
-}
-
-
-func Engine() *Engine {
-	return &Engine{}
-}
-
-func Test() {
-	engine.setEnable true
-	engine.enterPointerLock
-}
-`, `package main
-
-type Rect struct {
-}
-type Engine struct {
-}
-
-func (e *Engine) EnterPointerLock() {
-}
-func (e *Engine) SetEnable(b bool) {
-}
-func (this *Rect) Engine() *Engine {
-	return &Engine{}
-}
-func (this *Rect) Test() {
-	this.Engine().SetEnable(true)
-	this.Engine().EnterPointerLock()
-}
-`, "Rect.gox")
-}
diff --git a/cl/outline/cl/error_msg_test.go b/cl/outline/cl/error_msg_test.go
deleted file mode 100644
index 29919464..00000000
--- a/cl/outline/cl/error_msg_test.go
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package cl_test
-
-import (
-	"fmt"
-	"os"
-	"path/filepath"
-	"runtime"
-	"testing"
-
-	"github.com/goplus/gop/cl/outline/cl"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/parser/fsx/memfs"
-	"github.com/goplus/gop/scanner"
-)
-
-func codeErrorTest(t *testing.T, msg, src string) {
-	codeErrorTestEx(t, "main", "bar.gop", msg, src)
-}
-
-func codeErrorTestEx(t *testing.T, pkgname, filename, msg, src string) {
-	fs := memfs.SingleFile("/foo", filename, src)
-	pkgs, err := parser.ParseFSDir(gblFset, fs, "/foo", parser.Config{})
-	if err != nil {
-		scanner.PrintError(os.Stderr, err)
-		t.Fatal("parser.ParseFSDir failed")
-	}
-	conf := *gblConf
-	conf.NoFileLine = false
-	conf.WorkingDir = "/foo"
-	conf.TargetDir = "/foo"
-	bar := pkgs[pkgname]
-	_, err = cl.NewPackage("", bar, &conf)
-	if err == nil {
-		t.Fatal("no error?")
-	}
-	if ret := err.Error(); ret != msg {
-		t.Fatalf("\nError: \"%s\"\nExpected: \"%s\"\n", ret, msg)
-	}
-}
-
-func TestErrLambdaExpr(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:7:6: too few arguments in lambda expression\n\thave ()\n\twant (int, int)", `
-
-func foo(func(int, int)) {
-}
-
-func main() {
-	foo(=> {})
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:7:6: too many arguments in lambda expression\n\thave (x, y, z)\n\twant (int, int)", `
-
-func foo(func(int, int)) {
-}
-
-func main() {
-	foo((x, y, z) => {})
-}
-`)
-	codeErrorTest(t, "./bar.gop:6:8: cannot use lambda literal as type int in field value to Plot", `
-type Foo struct {
-	Plot int
-}
-foo := &Foo{
-	Plot: x => (x * 2, x * x),
-}
-`)
-	codeErrorTest(t, "./bar.gop:6:8: cannot use lambda literal as type int in field value to Plot", `
-type Foo struct {
-	Plot int
-}
-foo := &Foo{
-	Plot: x => {
-		return x * 2, x * x
-	},
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:5: cannot use lambda literal as type int in argument to foo", `
-func foo(int) {
-}
-foo(=> {})
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:5: cannot use lambda literal as type func() in argument to foo", `
-func foo(func()) {
-}
-foo => (100)
-`)
-	codeErrorTest(t,
-		"./bar.gop:6:8: cannot use lambda literal as type func() int in field value to Plot", `
-type Foo struct {
-	Plot func() int
-}
-foo := &Foo{
-	Plot: x => (x * 2, x * x),
-}
-`)
-
-	codeErrorTest(t,
-		"./bar.gop:2:18: cannot use lambda literal as type func() in assignment to foo", `
-var foo func() = => (100)
-`)
-	codeErrorTest(t,
-		"./bar.gop:3:7: cannot use lambda literal as type func() in assignment to foo", `
-var foo func()
-foo = => (100)
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:29: lambda unsupport multiple assignment", `
-var foo, foo1 func() = nil, => {}
-`)
-	codeErrorTest(t,
-		"./bar.gop:3:15: lambda unsupport multiple assignment", `
-var foo func()
-_, foo = nil, => {}
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:9: cannot use lambda expression as type int in return statement", `
-func intSeq() int {
-	i := 0
-	return => {
-		i++
-		return i
-	}
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:6:10: cannot use i (type int) as type string in return argument", `
-func intSeq() func() string {
-	i := 0
-	return => {
-		i++
-		return i
-	}
-}
-`)
-}
-
-func TestErrErrWrap(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: a", `func main() {
-	a!
-}
-`)
-}
-
-func TestErrVar(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:6:5: assignment mismatch: 1 variables but fmt.Println returns 2 values", `import "fmt"
-
-func main() {
-}
-
-var a = fmt.Println(1)
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:5: assignment mismatch: 1 variables but 2 values", `func main() {
-}
-
-var a = 1, 2
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: foo", `func main() {
-	foo.x = 1
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:2: use of builtin len not in function call", `func main() {
-	len.x = 1
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:10: undefined: foo", `func main() {
-	println(foo.x)
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:10: use of builtin len not in function call", `func main() {
-	println(len.x)
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:10: undefined: foo", `func main() {
-	println(foo)
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:3:20: use of builtin len not in function call", `package main
-
-func foo(v map[int]len) {
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:5:20: bar is not a type", `package main
-
-var bar = 1
-
-func foo(v map[int]bar) {
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:6: use of builtin len not in function call", `func main() {
-	new(len)
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: foo", `func main() {
-	foo = 1
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:9: cannot use _ as value", `func main() {
-	foo := _
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:9: use of builtin len not in function call", `func main() {
-	foo := len
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:2: println is not a variable", `func main() {
-	println = "hello"
-}
-`)
-}
-
-func TestErrImport(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:8:2: confliction: NewEncoding declared both in "encoding/base64" and "encoding/base32"`, `
-import (
-	. "encoding/base32"
-	. "encoding/base64"
-)
-
-func foo() {
-	NewEncoding("Hi")
-}`)
-	codeErrorTest(t,
-		"./bar.gop:5:2: cannot refer to unexported name os.undefined", `
-import "os"
-
-func foo() {
-	os.undefined
-}`)
-	codeErrorTest(t,
-		"./bar.gop:5:2: undefined: os.UndefinedObject", `
-import "os"
-
-func foo() {
-	os.UndefinedObject
-}`)
-	codeErrorTest(t,
-		"./bar.gop:2:13: undefined: testing", `
-func foo(t *testing.T) {
-}`)
-	codeErrorTest(t,
-		"./bar.gop:4:12: testing.Verbose is not a type", `
-import "testing"
-
-func foo(t testing.Verbose) {
-}`)
-}
-
-func TestErrConst(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:3:7: a redeclared in this block\n\t./bar.gop:2:5 other declaration of a", `
-var a int
-const a = 1
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:2: missing value in const declaration", `
-const (
-	a = iota
-	b, c
-)
-`)
-}
-
-func TestErrNewVar(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:3:5: a redeclared in this block\n\t./bar.gop:2:5 other declaration of a", `
-var a int
-var a string
-`)
-}
-
-func TestErrDefineVar(t *testing.T) {
-	codeErrorTest(t, "./bar.gop:3:1: no new variables on left side of :=\n"+
-		"./bar.gop:3:6: cannot use \"Hi\" (type untyped string) as type int in assignment", `
-a := 1
-a := "Hi"
-`)
-}
-
-func TestErrAssignMismatchT(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:2:16: cannot use []string{} (type []string) as type string in assignment`, `
-var a string = []string{}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:16: cannot use [2]string{} (type [2]string) as type string in assignment`, `
-var a string = [2]string{}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:16: cannot use map[int]string{} (type map[int]string) as type string in assignment`, `
-var a string = map[int]string{}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:16: cannot use T{} (type T) as type string in assignment`, `
-type T struct{}
-var a string = T{}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:16: cannot use func(){} (type func()) as type string in assignment`, `
-var a string = func(){}
-`)
-}
-
-func TestErrAssign(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:8:1: assignment mismatch: 1 variables but bar returns 2 values`, `
-
-func bar() (n int, err error) {
-	return
-}
-
-x := 1
-x = bar()
-`)
-	codeErrorTest(t,
-		`./bar.gop:4:1: assignment mismatch: 1 variables but 2 values`, `
-
-x := 1
-x = 1, "Hi"
-`)
-}
-
-func TestErrReturn(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:4:2: too few arguments to return\n\thave (untyped int)\n\twant (int, error)", `
-
-func foo() (int, error) {
-	return 1
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:2: too many arguments to return\n\thave (untyped int, untyped int, untyped string)\n\twant (int, error)", `
-
-func foo() (int, error) {
-	return 1, 2, "Hi"
-}
-`)
-	codeErrorTest(t,
-		`./bar.gop:4:12: cannot use "Hi" (type untyped string) as type error in return argument`, `
-
-func foo() (int, error) {
-	return 1, "Hi"
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:8:2: too few arguments to return\n\thave (byte)\n\twant (int, error)", `
-
-func bar() (v byte) {
-	return
-}
-
-func foo() (int, error) {
-	return bar()
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:8:2: too many arguments to return\n\thave (n int, err error)\n\twant (v byte)", `
-
-func bar() (n int, err error) {
-	return
-}
-
-func foo() (v byte) {
-	return bar()
-}
-`)
-	codeErrorTest(t,
-		`./bar.gop:8:2: cannot use byte value as type error in return argument`, `
-
-func bar() (n int, v byte) {
-	return
-}
-
-func foo() (int, error) {
-	return bar()
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:4:2: not enough arguments to return\n\thave ()\n\twant (byte)", `
-
-func foo() byte {
-	return
-}
-`)
-}
-
-func TestErrForRange(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:4:8: cannot assign type string to a (type int) in range`, `
-a := 1
-var b []string
-for _, a = range b {
-}
-`)
-}
-
-func TestErrInitFunc(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:2:6: func init must have no arguments and no return values`, `
-func init(v byte) {
-}
-`)
-}
-
-func TestErrRecv(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:5:9: invalid receiver type a (a is a pointer type)`, `
-
-type a *int
-
-func (p a) foo() {
-}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:9: invalid receiver type error (error is an interface type)`, `
-func (p error) foo() {
-}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:9: invalid receiver type []byte`, `
-func (p []byte) foo() {
-}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:9: invalid receiver type *[]byte`, `
-func (p *[]byte) foo() {
-}
-`)
-}
-
-func TestErrStructLit(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:39: too many values in struct{x int; y string}{...}`, `
-x := 1
-a := struct{x int; y string}{1, "Hi", 2}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:30: too few values in struct{x int; y string}{...}`, `
-x := 1
-a := struct{x int; y string}{1}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:33: cannot use x (type int) as type string in value of field y`, `
-x := 1
-a := struct{x int; y string}{1, x}
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:30: z undefined (type struct{x int; y string} has no field or method z)`, `
-a := struct{x int; y string}{z: 1}
-`)
-}
-
-func TestErrArray(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:8: non-constant array bound n`, `
-var n int
-var a [n]int
-`)
-}
-
-func TestErrArrayLit(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:14: cannot use a as index which must be non-negative integer constant`,
-		`
-a := "Hi"
-b := [10]int{a: 1}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:20: array index 10 out of bounds [0:10]`,
-		`
-a := "Hi"
-b := [10]int{9: 1, 3}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:16: array index 1 out of bounds [0:1]`,
-		`
-a := "Hi"
-b := [1]int{1, 2}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:14: array index 12 (value 12) out of bounds [0:10]`,
-		`
-a := "Hi"
-b := [10]int{12: 2}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:14: cannot use a+"!" (type string) as type int in array literal`,
-		`
-a := "Hi"
-b := [10]int{a+"!"}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:17: cannot use a (type string) as type int in array literal`,
-		`
-a := "Hi"
-b := [10]int{2: a}
-`)
-}
-
-func TestErrSliceLit(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:12: cannot use a as index which must be non-negative integer constant`,
-		`
-a := "Hi"
-b := []int{a: 1}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:12: cannot use a (type string) as type int in slice literal`,
-		`
-a := "Hi"
-b := []int{a}
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:15: cannot use a (type string) as type int in slice literal`,
-		`
-a := "Hi"
-b := []int{2: a}
-`)
-}
-
-func TestErrMapLit(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:2:21: cannot use 1+2 (type untyped int) as type string in map key
-./bar.gop:3:27: cannot use "Go" + "+" (type untyped string) as type int in map value`,
-		`
-a := map[string]int{1+2: 2}
-b := map[string]int{"Hi": "Go" + "+"}
-`)
-}
-
-func TestErrSlice(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:4:6: cannot slice a (type *byte)`,
-		`
-var a *byte
-x := 1
-b := a[x:2]
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:6: cannot slice a (type bool)`,
-		`
-a := true
-b := a[1:2]
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:6: invalid operation a[1:2:5] (3-index slice of string)`,
-		`
-a := "Hi"
-b := a[1:2:5]
-`)
-}
-
-func TestErrIndex(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:10: assignment mismatch: 2 variables but 1 values`,
-		`
-a := "Hi"
-b, ok := a[1]
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:6: invalid operation: a[1] (type bool does not support indexing)`,
-		`
-a := true
-b := a[1]
-`)
-}
-
-func TestErrIndexRef(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:1: cannot assign to a[1] (strings are immutable)`,
-		`
-a := "Hi"
-a[1] = 'e'
-`)
-}
-
-func TestErrStar(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:2: invalid indirect of a (type string)`,
-		`
-a := "Hi"
-*a = 'e'
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:7: invalid indirect of a (type string)`,
-		`
-a := "Hi"
-b := *a
-`)
-}
-
-func TestErrMember(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:6: a.x undefined (type string has no field or method x)`,
-		`
-a := "Hello"
-b := a.x
-`)
-}
-
-func TestErrMemberRef(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:3:1: a.x undefined (type string has no field or method x)`,
-		`
-a := "Hello"
-a.x = 1
-`)
-	codeErrorTest(t,
-		`./bar.gop:5:1: a.x undefined (type aaa has no field or method x)`,
-		`
-type aaa byte
-
-a := aaa(0)
-a.x = 1
-`)
-	codeErrorTest(t,
-		`./bar.gop:5:1: a.z undefined (type aaa has no field or method z)`,
-		`
-type aaa struct {x int; y string}
-
-a := aaa{}
-a.z = 1
-`)
-	codeErrorTest(t,
-		`./bar.gop:3:1: a.z undefined (type struct{x int; y string} has no field or method z)`,
-		`
-a := struct{x int; y string}{}
-a.z = 1
-`)
-}
-
-func TestErrLabel(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:4:1: label foo already defined at ./bar.gop:2:1
-./bar.gop:2:1: label foo defined and not used`,
-		`x := 1
-foo:
-	i := 1
-foo:
-	i++
-`)
-	codeErrorTest(t,
-		`./bar.gop:2:6: label foo is not defined`,
-		`x := 1
-goto foo`)
-	codeErrorTest(t,
-		`./bar.gop:2:7: label foo is not defined`,
-		`x := 1
-break foo`)
-}
-
-func TestErrBranchStmt(t *testing.T) {
-	codeErrorTest(t,
-		`./bar.gop:2:2: fallthrough statement out of place`,
-		`func foo() {
-	fallthrough
-}`)
-}
-
-func TestErrNoEntrypoint(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: println1", `func main() {
-	println1 "hello"
-}
-`)
-	codeErrorTest(t,
-		"./bar.gop:1:1: undefined: println1", `println1 "hello"`)
-
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: println1", `
-	println1 "hello"
-`)
-	codeErrorTest(t,
-		"./bar.gop:2:2: undefined: println1", `package main
-	println1 "hello"
-`)
-	codeErrorTest(t,
-		`./bar.gop:1:9: undefined: abc`,
-		`println abc
-`)
-	codeErrorTestEx(t, "bar", "bar.gop",
-		`./bar.gop:2:9: undefined: abc`,
-		`package bar
-println abc
-`)
-}
-
-func TestErrTypeRedefine(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:9:6: Point redeclared in this block\n\tprevious declaration at ./bar.gop:5:6",
-		`import "fmt"
-func (p *Point) String() string {
-	return fmt.Sprintf("%v-%v",p.X,p.Y)
-}
-type Point struct {
-	X int
-	Y int
-}
-type Point struct {
-	X int
-	Y int
-}
-`)
-}
-
-func TestErrSwitchDuplicate(t *testing.T) {
-	codeErrorTest(t,
-		"./bar.gop:4:7: duplicate case 100 in switch\n\tprevious case at ./bar.gop:3:7",
-		`var n int
-switch n {
-	case 100:
-	case 100:
-}`)
-	codeErrorTest(t,
-		"./bar.gop:4:7: duplicate case int(100) (value 100) in switch\n\tprevious case at ./bar.gop:3:7",
-		`var n int
-switch n {
-	case 100:
-	case int(100):
-}`)
-	codeErrorTest(t,
-		"./bar.gop:4:7: duplicate case 50 + 50 (value 100) in switch\n\tprevious case at ./bar.gop:3:7",
-		`var n int
-switch n {
-	case 100:
-	case 50 + 50:
-}`)
-	codeErrorTest(t,
-		"./bar.gop:5:7: duplicate case int(100) (value 100) in switch\n\tprevious case at ./bar.gop:3:7",
-		`var n interface{}
-switch n {
-	case 100:
-	case uint(100):
-	case int(100):
-}`)
-	codeErrorTest(t,
-		"./bar.gop:4:7: duplicate case 100.0 in switch\n\tprevious case at ./bar.gop:3:7",
-		`var n interface{}
-switch n {
-	case 100.0:
-	case 100.0:
-}`)
-	codeErrorTest(t,
-		"./bar.gop:5:7: duplicate case v (value 100) in switch\n\tprevious case at ./bar.gop:4:7",
-		`var n interface{}
-const v = 100.0
-switch n {
-	case 100.0:
-	case v:
-}`)
-	codeErrorTest(t,
-		"./bar.gop:5:7: duplicate case v (value \"hello\") in switch\n\tprevious case at ./bar.gop:4:7",
-		`var n interface{}
-const v = "hello"
-switch n {
-	case "hello":
-	case v:
-}`)
-	codeErrorTest(t,
-		`./bar.gop:4:7: duplicate case 100 in switch
-	previous case at ./bar.gop:3:7
-./bar.gop:5:7: duplicate case 50 + 50 (value 100) in switch
-	previous case at ./bar.gop:3:7`,
-		`var n int
-switch n {
-	case 100:
-	case 100:
-	case 50 + 50:
-}`)
-	codeErrorTest(t,
-		"./bar.gop:4:2: multiple defaults in switch (first at ./bar.gop:3:2)",
-		`var n interface{}
-switch n {
-	default:
-	default:
-}`)
-	codeErrorTest(t, `./bar.gop:4:2: multiple defaults in switch (first at ./bar.gop:3:2)
-./bar.gop:5:2: multiple defaults in switch (first at ./bar.gop:3:2)`,
-		`var n interface{}
-switch n {
-	default:
-	default:
-	default:
-}`)
-}
-
-func TestErrTypeSwitchDuplicate(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:4:7: duplicate case int in type switch
-	previous case at ./bar.gop:3:7
-./bar.gop:5:7: duplicate case int in type switch
-	previous case at ./bar.gop:3:7`,
-		`var n interface{} = 100
-switch n.(type) {
-	case int:
-	case int:
-	case int:
-}
-`)
-	codeErrorTest(t, `./bar.gop:4:7: multiple nil cases in type switch (first at ./bar.gop:3:7)
-./bar.gop:5:7: multiple nil cases in type switch (first at ./bar.gop:3:7)`,
-		`var n interface{} = 100
-switch n.(type) {
-	case nil:
-	case nil:
-	case nil:
-}
-`)
-	codeErrorTest(t, `./bar.gop:4:2: multiple defaults in type switch (first at ./bar.gop:3:2)
-./bar.gop:5:2: multiple defaults in type switch (first at ./bar.gop:3:2)`,
-		`var n interface{} = 100
-switch n.(type) {
-	default:
-	default:
-	default:
-}
-`)
-}
-
-func TestErrAutoProperty(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:4:11: cannot refer to unexported name fmt.println`, `
-import "fmt"
-
-n, err := fmt.println
-`)
-}
-
-func TestFiledsNameRedecl(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:6:2: Id redeclared
-	./bar.gop:5:2 other declaration of Id
-./bar.gop:7:2: Id redeclared
-	./bar.gop:5:2 other declaration of Id
-./bar.gop:9:2: name redeclared
-	./bar.gop:8:2 other declaration of name`, `
-type Id struct {
-}
-type A struct {
-	Id   int
-	Id   string
-	Id
-	name string
-	name string
-}
-`)
-}
-
-func TestErrImportPkg(t *testing.T) {
-	root := filepath.Join(runtime.GOROOT(), "src", "fmt2")
-	where := "GOROOT"
-	ver := runtime.Version()[:6]
-	if ver >= "go1.21" {
-		where = "std"
-	}
-	codeErrorTest(t,
-		fmt.Sprintf(`./bar.gop:3:2: package fmt2 is not in `+where+` (%v)
-`, root), `
-import (
-	"fmt2"
-)
-`)
-
-	codeErrorTest(t, `./bar.gop:3:2: no required module provides package github.com/goplus/gop/fmt2; to add it:
-	go get github.com/goplus/gop/fmt2
-`, `
-import (
-	"github.com/goplus/gop/fmt2"
-)
-`)
-}
-
-func TestErrClassFileGopx(t *testing.T) {
-	codeErrorTestEx(t, "main", "Rect.gox",
-		`./Rect.gox:5:2: A redeclared
-	./Rect.gox:3:2 other declaration of A`, `
-var (
-	A
-	i int
-	A
-)
-type A struct{}
-println "hello"
-`)
-}
-
-func TestErrVarInFunc(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:6:10: not enough arguments in call to set
-	have (untyped string)
-	want (name string, v int)
-./bar.gop:7:10: undefined: a`, `
-func set(name string, v int) string {
-	return name
-}
-func test() {
-	var a = set("box")
-	println(a)
-}
-`)
-}
-
-func TestErrInt128(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:2:16: cannot use 1<<127 (type untyped int) as type github.com/goplus/gop/builtin/ng.Int128 in assignment`, `
-var a int128 = 1<<127
-`)
-	codeErrorTest(t, `./bar.gop:2:13: cannot convert 1<<127 (untyped int constant 170141183460469231731687303715884105728) to type Int128`, `
-a := int128(1<<127)
-`)
-	codeErrorTest(t, `./bar.gop:2:13: cannot convert -1<<127-1 (untyped int constant -170141183460469231731687303715884105729) to type Int128`, `
-a := int128(-1<<127-1)
-`)
-	codeErrorTest(t, `./bar.gop:3:13: cannot convert b (untyped int constant -170141183460469231731687303715884105729) to type Int128`, `
-const b = -1<<127-1
-a := int128(b)
-`)
-}
-
-func TestErrUint128(t *testing.T) {
-	codeErrorTest(t, `./bar.gop:2:17: cannot use 1<<128 (type untyped int) as type github.com/goplus/gop/builtin/ng.Uint128 in assignment`, `
-var a uint128 = 1<<128
-`)
-	codeErrorTest(t, `./bar.gop:2:14: cannot convert 1<<128 (untyped int constant 340282366920938463463374607431768211456) to type Uint128`, `
-a := uint128(1<<128)
-`)
-	codeErrorTest(t, `./bar.gop:2:17: cannot use -1 (type untyped int) as type github.com/goplus/gop/builtin/ng.Uint128 in assignment`, `
-var a uint128 = -1
-`)
-	codeErrorTest(t, `./bar.gop:2:14: cannot convert -1 (untyped int constant -1) to type Uint128`, `
-a := uint128(-1)
-`)
-	codeErrorTest(t, `./bar.gop:3:14: cannot convert b (untyped int constant -1) to type Uint128`, `
-const b = -1
-a := uint128(b)
-`)
-}
diff --git a/cl/outline/cl/typeparams_test.go b/cl/outline/cl/typeparams_test.go
deleted file mode 100644
index 644e084f..00000000
--- a/cl/outline/cl/typeparams_test.go
+++ /dev/null
@@ -1,588 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-package cl_test
-
-import (
-	"os"
-	"runtime"
-	"testing"
-
-	"github.com/goplus/gop/cl/outline/cl"
-	"github.com/goplus/gop/parser"
-	"github.com/goplus/gop/parser/fsx/memfs"
-	"github.com/goplus/gop/scanner"
-)
-
-func _TestTypeParams(t *testing.T) {
-	gopMixedClTest(t, "main", `package main
-
-type Data[X, Y any] struct {
-	v X
-}
-
-func (p *Data[T, R]) foo() {
-	fmt.Println(p.v)
-}
-`, `
-v := Data[int, float64]{1}
-v.foo()
-`, `
-`)
-}
-
-func TestTypeParamsFunc(t *testing.T) {
-	gopMixedClTest(t, "main", `package main
-
-type Number interface {
-	~int | ~uint | (float64)
-}
-
-func Sum[T Number](vec []T) T {
-	var sum T
-	for _, elt := range vec {
-		sum = sum + elt
-	}
-	return sum
-}
-
-func At[T interface{ ~[]E }, E any](x T, i int) E {
-	return x[i]
-}
-
-func Loader[T1 any, T2 any](p1 T1, p2 T2) T1 {
-	return p1
-}
-
-func Add[T1 any, T2 ~int|~uint](v1 T1, v2 ...T2) (sum T2) {
-	println(v1)
-	for _, v := range v2 {
-		sum += v
-	}
-	return sum
-}
-
-type Int []int
-var MyInts = Int{1,2,3,4}
-`, `
-_ = At[[]int]
-_ = At[[]int,int]
-_ = Sum[int]
-_ = Loader[*int,int]
-_ = Add[string,int]
-var s1 int = Sum([1, 2, 3])
-var s2 int = Sum[int]([1, 2, 3])
-var v1 int = At([1, 2, 3], 1)
-var v2 int = At[[]int]([1, 2, 3], 1)
-var v3 int = At[[]int, int]([1, 2, 3], 1)
-var n1 int = Add("hello", 1, 2, 3)
-var n2 int = Add[string]("hello", 1, 2, 3)
-var n3 int = Add[string, int]("hello", 1, 2, 3)
-var n4 int = Add("hello", [1, 2, 3]...)
-var n5 int = Add("hello", [1, 2, 3]...)
-var n6 int = Add[string]("hello", MyInts...)
-var n7 int = Add[string, int]("hello", [1, 2, 3]...)
-var p1 *int = Loader[*int](nil, 1)
-var p2 *int = Loader[*int, int](nil, 1)
-var fn1 func(p1 *int, p2 int) *int
-fn1 = Loader[*int, int]
-fn1(nil, 1)
-`, `package main
-
-func main() {
-	_ = At[[]int]
-	_ = At[[]int, int]
-	_ = Sum[int]
-	_ = Loader[*int, int]
-	_ = Add[string, int]
-	var s1 int = Sum([]int{1, 2, 3})
-	var s2 int = Sum[int]([]int{1, 2, 3})
-	var v1 int = At([]int{1, 2, 3}, 1)
-	var v2 int = At[[]int]([]int{1, 2, 3}, 1)
-	var v3 int = At[[]int, int]([]int{1, 2, 3}, 1)
-	var n1 int = Add("hello", 1, 2, 3)
-	var n2 int = Add[string]("hello", 1, 2, 3)
-	var n3 int = Add[string, int]("hello", 1, 2, 3)
-	var n4 int = Add("hello", []int{1, 2, 3}...)
-	var n5 int = Add("hello", []int{1, 2, 3}...)
-	var n6 int = Add[string]("hello", MyInts...)
-	var n7 int = Add[string, int]("hello", []int{1, 2, 3}...)
-	var p1 *int = Loader[*int](nil, 1)
-	var p2 *int = Loader[*int, int](nil, 1)
-	var fn1 func(p1 *int, p2 int) *int
-	fn1 = Loader[*int, int]
-	fn1(nil, 1)
-}
-`)
-}
-
-func _TestTypeParamsType(t *testing.T) {
-	gopMixedClTest(t, "main", `package main
-type Data[T any] struct {
-	v T
-}
-func(p *Data[T]) Set(v T) {
-	p.v = v
-}
-func(p *(Data[T1])) Set2(v T1) {
-	p.v = v
-}
-type sliceOf[E any] interface {
-	~[]E
-}
-type Slice[S sliceOf[T], T any] struct {
-	Data S
-}
-func (p *Slice[S, T]) Append(t ...T) S {
-	p.Data = append(p.Data, t...)
-	return p.Data
-}
-func (p *Slice[S1, T1]) Append2(t ...T1) S1 {
-	p.Data = append(p.Data, t...)
-	return p.Data
-}
-type (
-	DataInt = Data[int]
-	SliceInt = Slice[[]int,int]
-)
-`, `
-type DataString = Data[string]
-type SliceString = Slice[[]string,string]
-println(DataInt{1}.v)
-println(DataString{"hello"}.v)
-println(Data[int]{100}.v)
-println(Data[string]{"hello"}.v)
-println(Data[struct{X int;Y int}]{}.v.X)
-
-v1 := SliceInt{}
-v2 := SliceString{}
-v3 := Slice[[]int,int]{}
-v3.Append([1,2,3,4]...)
-v3.Append2([1,2,3,4]...)
-`, `package main
-
-import "fmt"
-
-type DataString = Data[string]
-type SliceString = Slice[[]string, string]
-
-func main() {
-	fmt.Println(Data[int]{1}.v)
-	fmt.Println(Data[string]{"hello"}.v)
-	fmt.Println(Data[int]{100}.v)
-	fmt.Println(Data[string]{"hello"}.v)
-	fmt.Println(Data[struct {
-		X int
-		Y int
-	}]{}.v.X)
-	v1 := Slice[[]int, int]{}
-	v2 := Slice[[]string, string]{}
-	v3 := Slice[[]int, int]{}
-	v3.Append([]int{1, 2, 3, 4}...)
-	v3.Append2([]int{1, 2, 3, 4}...)
-}
-`)
-}
-
-func TestTypeParamsComparable(t *testing.T) {
-	gopMixedClTest(t, "main", `package main
-// Index returns the index of x in s, or -1 if not found.
-func Index[T comparable](s []T, x T) int {
-	for i, v := range s {
-		// v and x are type T, which has the comparable
-		// constraint, so we can use == here.
-		if v == x {
-			return i
-		}
-	}
-	return -1
-}
-
-var IndexInt = Index[int]
-`, `
-v1 := IndexInt([1,2,3,4],1)
-v2 := Index([1,2,3,4],1)
-v3 := Index[int]([1,2,3,4],1)
-v4 := Index(["a","b","c","d"],"b")
-`, `package main
-
-func main() {
-	v1 := IndexInt([]int{1, 2, 3, 4}, 1)
-	v2 := Index([]int{1, 2, 3, 4}, 1)
-	v3 := Index[int]([]int{1, 2, 3, 4}, 1)
-	v4 := Index([]string{"a", "b", "c", "d"}, "b")
-}
-`)
-}
-
-func mixedErrorTest(t *testing.T, msg, gocode, gopcode string) {
-	mixedErrorTestEx(t, "main", msg, gocode, gopcode)
-}
-
-func mixedErrorTestEx(t *testing.T, pkgname, msg, gocode, gopcode string) {
-	fs := memfs.TwoFiles("/foo", "a.go", gocode, "b.gop", gopcode)
-	pkgs, err := parser.ParseFSDir(gblFset, fs, "/foo", parser.Config{})
-	if err != nil {
-		scanner.PrintError(os.Stderr, err)
-		t.Fatal("parser.ParseFSDir failed")
-	}
-	conf := *gblConf
-	conf.NoFileLine = false
-	conf.WorkingDir = "/foo"
-	conf.TargetDir = "/foo"
-	bar := pkgs[pkgname]
-	_, err = cl.NewPackage("", bar, &conf)
-	if err == nil {
-		t.Fatal("no error?")
-	}
-	if ret := err.Error(); ret != msg {
-		t.Fatalf("\nError: \"%s\"\nExpected: \"%s\"\n", ret, msg)
-	}
-}
-
-func TestTypeParamsErrorInstantiate(t *testing.T) {
-	var msg string
-	switch runtime.Version()[:6] {
-	case "go1.18":
-		msg = `./b.gop:2:1: uint does not implement Number`
-	case "go1.19":
-		msg = `./b.gop:2:1: uint does not implement Number (uint missing in ~int | float64)`
-	default:
-		msg = `./b.gop:2:1: uint does not satisfy Number (uint missing in ~int | float64)`
-	}
-
-	mixedErrorTest(t, msg, `
-package main
-
-type Number interface {
-	~int | float64
-}
-
-func Sum[T Number](vec []T) T {
-	var sum T
-	for _, elt := range vec {
-		sum = sum + elt
-	}
-	return sum
-}
-
-var	SumInt = Sum[int]
-`, `
-Sum[uint]
-`)
-}
-
-func TestTypeParamsErrorMatch(t *testing.T) {
-	var msg string
-	switch runtime.Version()[:6] {
-	case "go1.18", "go1.19":
-		msg = `./b.gop:2:5: T does not match ~[]E`
-	case "go1.20":
-		msg = `./b.gop:2:5: int does not match ~[]E`
-	default:
-		msg = `./b.gop:2:5: T (type int) does not satisfy interface{interface{~[]E}}`
-	}
-	mixedErrorTest(t, msg, `
-package main
-
-func At[T interface{ ~[]E }, E any](x T, i int) E {
-	return x[i]
-}
-
-var	AtInt = At[[]int]
-`, `
-_ = At[int]
-`)
-}
-
-func TestTypeParamsErrInferFunc(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:5: cannot infer T2 (/foo/a.go:4:21)`, `
-package main
-
-func Loader[T1 any, T2 any](p1 T1, p2 T2) T1 {
-	return p1
-}
-`, `
-_ = Loader[int]
-`)
-}
-
-func TestTypeParamsErrArgumentsParameters1(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:7: got 1 type arguments but Data[T1, T2 interface{}] has 2 type parameters`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-var v Data[int]
-`)
-}
-
-func TestTypeParamsErrArgumentsParameters2(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:7: got 3 type arguments but Data[T1, T2 interface{}] has 2 type parameters`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-var v Data[int,int,int]
-`)
-}
-
-func TestTypeParamsErrArgumentsParameters3(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: got 3 type arguments but func[T1, T2 interface{}](t1 T1, t2 T2) has 2 type parameters`, `
-package main
-
-func Test[T1 any, T2 any](t1 T1, t2 T2) {
-	println(t1,t2)
-}
-`, `
-Test[int,int,int](1,2)
-`)
-}
-
-func TestTypeParamsErrCallArguments1(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: not enough arguments in call to Test
-	have (untyped int)
-	want (T1, T2)`, `
-package main
-
-func Test[T1 any, T2 any](t1 T1, t2 T2) {
-	println(t1,t2)
-}
-`, `
-Test(1)
-`)
-}
-
-func TestTypeParamsErrCallArguments2(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: too many arguments in call to Test
-	have (untyped int, untyped int, untyped int)
-	want (T1, T2)`, `
-package main
-
-func Test[T1 any, T2 any](t1 T1, t2 T2) {
-	println(t1,t2)
-}
-`, `
-Test(1,2,3)
-`)
-}
-
-func TestTypeParamsErrCallArguments3(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: too many arguments in call to Test
-	have (untyped int, untyped int)
-	want ()`, `
-package main
-
-func Test[T1 any, T2 any]() {
-	var t1 T1
-	var t2 T2
-	println(t1,t2)
-}
-`, `
-Test(1,2)
-`)
-}
-
-func TestTypeParamsErrCallVariadicArguments1(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: not enough arguments in call to Add
-	have ()
-	want (T1, ...T2)`, `
-package main
-
-func Add[T1 any, T2 ~int|~uint](v1 T1, v2 ...T2) (sum T2) {
-	println(v1)
-	for _, v := range v2 {
-		sum += v
-	}
-	return sum
-}
-`, `
-Add()
-`)
-}
-
-func TestTypeParamsErrCallVariadicArguments2(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:1: cannot infer T2 (./a.go:4:18)`, `
-package main
-
-func Add[T1 any, T2 ~int|~uint](v1 T1, v2 ...T2) (sum T2) {
-	println(v1)
-	for _, v := range v2 {
-		sum += v
-	}
-	return sum
-}
-`, `
-Add(1)
-`)
-}
-
-func TestTypeParamsRecvTypeError1(t *testing.T) {
-	mixedErrorTest(t, `./a.go:7:9: cannot use generic type Data[T interface{}] without instantiation`, `
-package main
-
-type Data[T any] struct {
-	v T
-}
-func(p *Data) Test() {
-}
-`, `
-Data[int]{}.Test()
-`)
-}
-
-func _TestTypeParamsRecvTypeError2(t *testing.T) {
-	mixedErrorTest(t, `./a.go:7:9: got 2 arguments but 1 type parameters`, `
-package main
-
-type Data[T any] struct {
-	v T
-}
-func(p *Data[T1,T2]) Test() {
-}
-`, `
-Data[int]{}.Test()
-`)
-}
-
-func _TestTypeParamsRecvTypeError3(t *testing.T) {
-	mixedErrorTest(t, `./a.go:8:9: got 1 type parameter, but receiver base type declares 2`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-func(p *Data[T1]) Test() {
-}
-`, `
-Data[int,int]{}.Test()
-`)
-}
-
-func TestGenericTypeWithoutInst1(t *testing.T) {
-	mixedErrorTest(t, `./a.go:8:9: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-func(p *Data) Test() {
-}
-`, `
-var v Data[int,int]
-`)
-}
-
-func _TestGenericTypeWithoutInst2(t *testing.T) {
-	mixedErrorTest(t, `./a.go:10:2: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-
-type My[T any] struct {
-	Data
-}
-`, `
-var v My[int]
-`)
-}
-
-func _TestGenericTypeWithoutInst3(t *testing.T) {
-	mixedErrorTest(t, `./a.go:10:2: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-
-type My struct {
-	Data
-}
-`, `
-var v My
-`)
-}
-
-func _TestGenericTypeWithoutInst4(t *testing.T) {
-	mixedErrorTest(t, `./a.go:10:15: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-
-type My struct {
-	v map[string]Data
-}
-`, `
-var v My
-`)
-}
-
-func _TestGenericTypeWithoutInst5(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:7: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-var v Data
-`)
-}
-
-func _TestGenericTypeWithoutInst6(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:8: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-type T Data
-`)
-}
-
-func _TestGenericTypeWithoutInst7(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:3:2: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-type My struct {
-	Data
-}
-`)
-}
-
-func _TestGenericTypeWithoutInst8(t *testing.T) {
-	mixedErrorTest(t, `./b.gop:2:23: cannot use generic type Data[T1, T2 interface{}] without instantiation`, `
-package main
-
-type Data[T1 any, T2 any] struct {
-	v1 T1
-	v2 T2
-}
-`, `
-func test(v1 int, v2 *Data) {
-}
-`)
-}