Repository: goplus/gop
Pull request #626 (2020-11-16 08:19:00)

bytecode: add builtinAddrOps for BigInt
BigInt addr operator  += -= *= /= + -- 


Patch:
diff --git a/cl/context.go b/cl/context.go
index d3798d74..cab618b6 100644
--- a/cl/context.go
+++ b/cl/context.go
@@ -51,9 +51,6 @@ func newPkgCtx(out exec.Builder, pkg *ast.Package, fset *token.FileSet) *pkgCtx
 }
 
 func (p *pkgCtx) code(v ast.Node) string {
-	if expr, ok := v.(*ast.ParenExpr); ok {
-		v = expr.X
-	}
 	_, code := p.getCodeInfo(v)
 	return code
 }
diff --git a/cl/expr.go b/cl/expr.go
index 1d33204c..2ed7300d 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -69,7 +69,7 @@ func compileExpr(ctx *blockCtx, expr ast.Expr) func() {
 	case *ast.UnaryExpr:
 		return compileUnaryExpr(ctx, v)
 	case *ast.SelectorExpr:
-		return compileSelectorExpr(ctx, nil, v, false)
+		return compileSelectorExpr(ctx, v, false)
 	case *ast.ErrWrapExpr:
 		return compileErrWrapExpr(ctx, v)
 	case *ast.IndexExpr:
@@ -737,7 +737,7 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, ct callType) func() {
 	case *ast.Ident:
 		exprFun = compileIdent(ctx, f, true)
 	case *ast.SelectorExpr:
-		exprFun = compileSelectorExpr(ctx, v, f, true)
+		exprFun = compileSelectorExpr(ctx, f, true)
 	default:
 		exprFun = compileExpr(ctx, f)
 	}
@@ -1248,43 +1248,7 @@ func funcToClosure(ctx *blockCtx, fun ast.Expr, ftyp *ast.FuncType) *funcDecl {
 	return newFuncDecl("", nil, typ, body, funCtx)
 }
 
-func toElem(t reflect.Type) reflect.Type {
-	if t.Kind() == reflect.Ptr {
-		t = t.Elem()
-	}
-	return t
-}
-
-func isUserStruct(t reflect.Type) bool {
-	t = toElem(t)
-	return t.Kind() == reflect.Struct && (t.PkgPath() == "" || t.PkgPath() == "main")
-}
-
-func findUserStructAnonymous(ctx *blockCtx, t reflect.Type, name string) []string {
-	t = toElem(t)
-	for i := 0; i < t.NumField(); i++ {
-		sf := t.Field(i)
-		if sf.Anonymous {
-			var found bool
-			if isUserStruct(sf.Type) {
-				_, found = ctx.findMethod(sf.Type, name)
-				if !found {
-					if names := findUserStructAnonymous(ctx, sf.Type, name); names != nil {
-						return append([]string{sf.Name}, names...)
-					}
-				}
-			} else {
-				_, found = sf.Type.MethodByName(name)
-			}
-			if found {
-				return []string{sf.Name}
-			}
-		}
-	}
-	return nil
-}
-
-func compileSelectorExpr(ctx *blockCtx, call *ast.CallExpr, v *ast.SelectorExpr, compileByCallExpr bool) func() {
+func compileSelectorExpr(ctx *blockCtx, v *ast.SelectorExpr, compileByCallExpr bool) func() {
 	exprX := compileExpr(ctx, v.X)
 	if v.Sel == nil {
 		return exprX
@@ -1388,48 +1352,33 @@ func compileSelectorExpr(ctx *blockCtx, call *ast.CallExpr, v *ast.SelectorExpr,
 					}
 				}
 			}
-			if call != nil && isUserStruct(t) {
-				if names := findUserStructAnonymous(ctx, t, name); names != nil {
-					ctx.infer.Pop()
-					x := &ast.SelectorExpr{X: v.X}
-					for i := 0; i < len(names)-1; i++ {
-						x.X = &ast.SelectorExpr{X: x.X, Sel: &ast.Ident{Name: names[i]}}
-					}
-					x.Sel = &ast.Ident{Name: names[len(names)-1]}
-					fun := &ast.SelectorExpr{X: x, Sel: v.Sel}
-					call.Fun = fun
-					return compileSelectorExpr(ctx, call, fun, compileByCallExpr)
-				}
-			}
 		}
-		_, toptr, ok := findMethod(t, name)
-		if !ok && isLower(name) {
+
+		if _, ok := vx.t.MethodByName(name); !ok && isLower(name) {
 			name = strings.Title(name)
-			if _, toptr, ok = findMethod(t, name); ok {
+			if _, ok = vx.t.MethodByName(name); ok {
 				v.Sel.Name = name
 				autoCall = !compileByCallExpr
+			} else {
+				log.Panicln("compileSelectorExpr: symbol not found -", v.Sel.Name)
 			}
 		}
-		if !ok {
-			log.Panicln("compileSelectorExpr: symbol not found -", vx.t, v.Sel.Name)
-		}
-		if n > 1 {
-			log.Panicf("calling method %v with receiver %v (type %v) requires explicit dereference.", v.Sel.Name, ctx.code(v.X), vx.t)
-		}
-		pkgPath := t.PkgPath()
+		pkgPath, method := normalizeMethod(n, t, name)
 		pkg := ctx.FindGoPackage(pkgPath)
 		if pkg == nil {
 			log.Panicln("compileSelectorExpr failed: package not found -", pkgPath)
 		}
-		var fnname string
-		if toptr {
-			fnname = "(*" + t.Name() + ")." + name
-		} else {
-			fnname = "(" + t.Name() + ")." + name
+		addr, kind, ok := pkg.Find(method)
+		if !ok {
+			cn := 0
+			if n == 0 {
+				cn = 1
+			}
+			_, cm := normalizeMethod(cn, t, name)
+			addr, kind, ok = pkg.Find(cm)
 		}
-		addr, kind, ok := pkg.Find(fnname)
 		if !ok {
-			log.Panicln("compileSelectorExpr: method not found -", fnname)
+			log.Panicln("compileSelectorExpr: method not found -", method)
 		}
 		if !compileByCallExpr && !autoCall {
 			ctx.infer.Pop()
@@ -1493,14 +1442,12 @@ func countPtr(t reflect.Type) (int, reflect.Type) {
 	return n, t
 }
 
-func findMethod(t reflect.Type, name string) (method reflect.Method, toptr bool, found bool) {
-	method, found = t.MethodByName(name)
-	if !found && t.Kind() == reflect.Struct {
-		t = reflect.PtrTo(t)
-		toptr = true
-		method, found = t.MethodByName(name)
+func normalizeMethod(n int, t reflect.Type, name string) (pkgPath string, formalName string) {
+	typName := t.Name()
+	if n > 0 {
+		typName = strings.Repeat("*", n) + typName
 	}
-	return
+	return t.PkgPath(), "(" + typName + ")." + name
 }
 
 // -----------------------------------------------------------------------------
diff --git a/cl/type_decl.go b/cl/type_decl.go
index 5bcc0c32..87f95fb5 100644
--- a/cl/type_decl.go
+++ b/cl/type_decl.go
@@ -22,7 +22,6 @@ import (
 
 	"github.com/goplus/gop/ast"
 	"github.com/goplus/gop/exec.spec"
-	"github.com/goplus/reflectx"
 	"github.com/qiniu/x/log"
 )
 
@@ -227,7 +226,7 @@ func toStructType(ctx *blockCtx, v *ast.StructType) iType {
 	for _, field := range v.Fields.List {
 		fields = append(fields, toStructField(ctx, field)...)
 	}
-	return reflectx.StructOf(fields)
+	return reflect.StructOf(fields)
 }
 
 func toInterfaceType(ctx *blockCtx, v *ast.InterfaceType) iType {
@@ -324,26 +323,11 @@ func toStructField(ctx *blockCtx, field *ast.Field) []reflect.StructField {
 	return fields
 }
 
-func typeName(typ ast.Expr) string {
-	switch v := typ.(type) {
-	case *ast.Ident:
-		return v.Name
-	case *ast.SelectorExpr:
-		return typeName(v.Sel)
-	case *ast.StarExpr:
-		return typeName(v.X)
-	}
-	return ""
-}
-
 func buildField(ctx *blockCtx, field *ast.Field, anonymous bool, fieldName string) reflect.StructField {
 	var f = reflect.StructField{}
 	if !anonymous {
 		f = reflect.StructField{}
 	}
-	if anonymous {
-		fieldName = typeName(field.Type)
-	}
 	f = reflect.StructField{
 		Name:      fieldName,
 		Type:      toType(ctx, field.Type).(reflect.Type),
diff --git a/exec.spec/operator.go b/exec.spec/operator.go
index 35b9ee2d..bc15c719 100644
--- a/exec.spec/operator.go
+++ b/exec.spec/operator.go
@@ -212,10 +212,10 @@ type AddrOperatorInfo struct {
 }
 
 var addropInfos = [...]AddrOperatorInfo{
-	OpAddAssign:    {"+=", bitsAllNumber | bitString, bitSameAsFirst},
-	OpSubAssign:    {"-=", bitsAllNumber, bitSameAsFirst},
-	OpMulAssign:    {"*=", bitsAllNumber, bitSameAsFirst},
-	OpQuoAssign:    {"/=", bitsAllNumber, bitSameAsFirst},
+	OpAddAssign:    {"+=", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst},
+	OpSubAssign:    {"-=", bitsAllNumber | bitBigInt, bitSameAsFirst},
+	OpMulAssign:    {"*=", bitsAllNumber | bitBigInt, bitSameAsFirst},
+	OpQuoAssign:    {"/=", bitsAllNumber | bitBigInt, bitSameAsFirst},
 	OpModAssign:    {"%=", bitsAllIntUint, bitSameAsFirst},
 	OpAndAssign:    {"&=", bitsAllIntUint, bitSameAsFirst},
 	OpOrAssign:     {"|=", bitsAllIntUint, bitSameAsFirst},
@@ -223,8 +223,8 @@ var addropInfos = [...]AddrOperatorInfo{
 	OpAndNotAssign: {"&^=", bitsAllIntUint, bitSameAsFirst},
 	OpLshAssign:    {"<<=", bitsAllIntUint, bitsAllIntUint},
 	OpRshAssign:    {">>=", bitsAllIntUint, bitsAllIntUint},
-	OpInc:          {"++", bitsAllNumber, bitNone},
-	OpDec:          {"--", bitsAllNumber, bitNone},
+	OpInc:          {"++", bitsAllNumber | bitBigInt, bitNone},
+	OpDec:          {"--", bitsAllNumber | bitBigInt, bitNone},
 }
 
 // GetInfo returns the information of this operator.
diff --git a/exec/bytecode/exec_addrop_autogen.go b/exec/bytecode/exec_addrop_autogen.go
index c29e6e6b..12ffa3d5 100644
--- a/exec/bytecode/exec_addrop_autogen.go
+++ b/exec/bytecode/exec_addrop_autogen.go
@@ -21,6 +21,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpAddAssign) << bitsKind) | int(Complex64):  execAddAssignComplex64,
 	(int(OpAddAssign) << bitsKind) | int(Complex128): execAddAssignComplex128,
 	(int(OpAddAssign) << bitsKind) | int(String):     execAddAssignString,
+	(int(OpAddAssign) << bitsKind) | int(BigInt):     execAddAssignBigInt,
 	(int(OpAddAssign) << bitsKind) | int(BigRat):     execAddAssignBigRat,
 	(int(OpAddAssign) << bitsKind) | int(BigFloat):   execAddAssignBigFloat,
 	(int(OpSubAssign) << bitsKind) | int(Int):        execSubAssignInt,
@@ -38,6 +39,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpSubAssign) << bitsKind) | int(Float64):    execSubAssignFloat64,
 	(int(OpSubAssign) << bitsKind) | int(Complex64):  execSubAssignComplex64,
 	(int(OpSubAssign) << bitsKind) | int(Complex128): execSubAssignComplex128,
+	(int(OpSubAssign) << bitsKind) | int(BigInt):     execSubAssignBigInt,
 	(int(OpSubAssign) << bitsKind) | int(BigRat):     execSubAssignBigRat,
 	(int(OpSubAssign) << bitsKind) | int(BigFloat):   execSubAssignBigFloat,
 	(int(OpMulAssign) << bitsKind) | int(Int):        execMulAssignInt,
@@ -55,6 +57,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpMulAssign) << bitsKind) | int(Float64):    execMulAssignFloat64,
 	(int(OpMulAssign) << bitsKind) | int(Complex64):  execMulAssignComplex64,
 	(int(OpMulAssign) << bitsKind) | int(Complex128): execMulAssignComplex128,
+	(int(OpMulAssign) << bitsKind) | int(BigInt):     execMulAssignBigInt,
 	(int(OpMulAssign) << bitsKind) | int(BigRat):     execMulAssignBigRat,
 	(int(OpMulAssign) << bitsKind) | int(BigFloat):   execMulAssignBigFloat,
 	(int(OpQuoAssign) << bitsKind) | int(Int):        execQuoAssignInt,
@@ -72,6 +75,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpQuoAssign) << bitsKind) | int(Float64):    execQuoAssignFloat64,
 	(int(OpQuoAssign) << bitsKind) | int(Complex64):  execQuoAssignComplex64,
 	(int(OpQuoAssign) << bitsKind) | int(Complex128): execQuoAssignComplex128,
+	(int(OpQuoAssign) << bitsKind) | int(BigInt):     execQuoAssignBigInt,
 	(int(OpQuoAssign) << bitsKind) | int(BigRat):     execQuoAssignBigRat,
 	(int(OpQuoAssign) << bitsKind) | int(BigFloat):   execQuoAssignBigFloat,
 	(int(OpModAssign) << bitsKind) | int(Int):        execModAssignInt,
@@ -166,6 +170,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpInc) << bitsKind) | int(Float64):          execIncFloat64,
 	(int(OpInc) << bitsKind) | int(Complex64):        execIncComplex64,
 	(int(OpInc) << bitsKind) | int(Complex128):       execIncComplex128,
+	(int(OpInc) << bitsKind) | int(BigInt):           execIncBigInt,
 	(int(OpInc) << bitsKind) | int(BigRat):           execIncBigRat,
 	(int(OpInc) << bitsKind) | int(BigFloat):         execIncBigFloat,
 	(int(OpDec) << bitsKind) | int(Int):              execDecInt,
@@ -183,6 +188,7 @@ var builtinAddrOps = [...]func(i Instr, p *Context){
 	(int(OpDec) << bitsKind) | int(Float64):          execDecFloat64,
 	(int(OpDec) << bitsKind) | int(Complex64):        execDecComplex64,
 	(int(OpDec) << bitsKind) | int(Complex128):       execDecComplex128,
+	(int(OpDec) << bitsKind) | int(BigInt):           execDecBigInt,
 	(int(OpDec) << bitsKind) | int(BigRat):           execDecBigRat,
 	(int(OpDec) << bitsKind) | int(BigFloat):         execDecBigFloat,
 }
@@ -283,6 +289,13 @@ func execAddAssignString(i Instr, p *Context) {
 	p.data = p.data[:n-2]
 }
 
+func execAddAssignBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Add(x, p.data[n-2].(*big.Int))
+	p.data = p.data[:n-2]
+}
+
 func execAddAssignBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
@@ -387,6 +400,13 @@ func execSubAssignComplex128(i Instr, p *Context) {
 	p.data = p.data[:n-2]
 }
 
+func execSubAssignBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Sub(x, p.data[n-2].(*big.Int))
+	p.data = p.data[:n-2]
+}
+
 func execSubAssignBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
@@ -491,6 +511,13 @@ func execMulAssignComplex128(i Instr, p *Context) {
 	p.data = p.data[:n-2]
 }
 
+func execMulAssignBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Mul(x, p.data[n-2].(*big.Int))
+	p.data = p.data[:n-2]
+}
+
 func execMulAssignBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
@@ -595,6 +622,13 @@ func execQuoAssignComplex128(i Instr, p *Context) {
 	p.data = p.data[:n-2]
 }
 
+func execQuoAssignBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Quo(x, p.data[n-2].(*big.Int))
+	p.data = p.data[:n-2]
+}
+
 func execQuoAssignBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
@@ -1161,6 +1195,13 @@ func execIncComplex128(i Instr, p *Context) {
 	p.data = p.data[:n-1]
 }
 
+func execIncBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Add(x, bigIntOne)
+	p.data = p.data[:n-1]
+}
+
 func execIncBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
@@ -1265,6 +1306,13 @@ func execDecComplex128(i Instr, p *Context) {
 	p.data = p.data[:n-1]
 }
 
+func execDecBigInt(i Instr, p *Context) {
+	n := len(p.data)
+	x := p.data[n-1].(*big.Int)
+	x.Sub(x, bigIntOne)
+	p.data = p.data[:n-1]
+}
+
 func execDecBigRat(i Instr, p *Context) {
 	n := len(p.data)
 	x := p.data[n-1].(*big.Rat)
diff --git a/exec/bytecode/gopkg.go b/exec/bytecode/gopkg.go
index 57fcbaee..d297c83e 100644
--- a/exec/bytecode/gopkg.go
+++ b/exec/bytecode/gopkg.go
@@ -20,7 +20,6 @@ import (
 	"reflect"
 
 	"github.com/goplus/gop/exec.spec"
-	"github.com/goplus/reflectx"
 	"github.com/qiniu/x/log"
 )
 
@@ -67,15 +66,15 @@ func execAddrGoVar(i Instr, p *Context) {
 func execLoadField(i Instr, p *Context) {
 	index := p.Pop()
 	v := reflect.ValueOf(p.Pop())
-	v = toElem(v)
-	p.Push(reflectx.FieldByIndex(v, index.([]int)).Interface())
+	v = reflect.Indirect(v)
+	p.Push(FieldByIndex(v, index.([]int)).Interface())
 }
 
 func execAddrField(i Instr, p *Context) {
 	index := p.Pop()
 	v := reflect.ValueOf(p.Pop())
 	v = toElem(v)
-	p.Push(reflectx.FieldByIndex(v, index.([]int)).Addr().Interface())
+	p.Push(FieldByIndex(v, index.([]int)).Addr().Interface())
 }
 
 func toElem(v reflect.Value) reflect.Value {
@@ -98,7 +97,7 @@ func storeField(v reflect.Value, index []int, value interface{}) {
 	if !v.CanSet() {
 		log.Panicf("cannot assign to %v\n", v)
 	}
-	setValue(reflectx.FieldByIndex(v, index), value)
+	setValue(FieldByIndex(v, index), value)
 }
 
 // -----------------------------------------------------------------------------
diff --git a/exec/bytecode/reflect.go b/exec/bytecode/reflect.go
new file mode 100644
index 00000000..83c9c8e1
--- /dev/null
+++ b/exec/bytecode/reflect.go
@@ -0,0 +1,64 @@
+/*
+ Copyright 2020 The GoPlus Authors (goplus.org)
+
+ 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 bytecode
+
+import (
+	"reflect"
+	"unsafe"
+
+	"github.com/goplus/gop/ast"
+)
+
+type Value struct {
+	typ *unsafe.Pointer
+	ptr unsafe.Pointer
+	flag
+}
+
+type flag uintptr
+
+const (
+	flagKindWidth        = 5 // there are 27 kinds
+	flagKindMask    flag = 1<<flagKindWidth - 1
+	flagStickyRO    flag = 1 << 5
+	flagEmbedRO     flag = 1 << 6
+	flagIndir       flag = 1 << 7
+	flagAddr        flag = 1 << 8
+	flagMethod      flag = 1 << 9
+	flagMethodShift      = 10
+	flagRO          flag = flagStickyRO | flagEmbedRO
+)
+
+func Field(v reflect.Value, i int) reflect.Value {
+	sf := v.Type().Field(i)
+	if !ast.IsExported(sf.Name) {
+		vf := v.Field(i)
+		(*Value)(unsafe.Pointer(&vf)).flag &= ^flagRO
+		return vf
+	}
+	return v.Field(i)
+}
+
+func FieldByIndex(v reflect.Value, index []int) reflect.Value {
+	sf := v.Type().FieldByIndex(index)
+	if !ast.IsExported(sf.Name) {
+		vf := v.FieldByIndex(index)
+		(*Value)(unsafe.Pointer(&vf)).flag &= ^flagRO
+		return vf
+	}
+	return v.FieldByIndex(index)
+}
diff --git a/exec/bytecode/struct.go b/exec/bytecode/struct.go
index e5a7f207..17cb97ff 100644
--- a/exec/bytecode/struct.go
+++ b/exec/bytecode/struct.go
@@ -20,7 +20,6 @@ import (
 	"reflect"
 	"strconv"
 
-	"github.com/goplus/reflectx"
 	"github.com/qiniu/x/log"
 )
 
@@ -163,12 +162,12 @@ func (p *Builder) Struct(typ reflect.Type, arity int) *Builder {
 }
 
 func execStruct(i Instr, p *Context) {
-	typ := getType(i&bitsOpCallFuncvOperand, p)
+	typStruct := getType(i&bitsOpCallFuncvOperand, p)
 	arity := int((i >> bitsOpCallFuncvShift) & bitsFuncvArityOperand)
 	if arity == bitsFuncvArityMax {
 		arity = p.Pop().(int) + bitsFuncvArityMax
 	}
-	makeStruct(typ, arity, p)
+	makeStruct(typStruct, arity, p)
 }
 
 func makeStruct(typStruct reflect.Type, arity int, p *Context) {
@@ -176,14 +175,14 @@ func makeStruct(typStruct reflect.Type, arity int, p *Context) {
 	args := p.GetArgs(n)
 
 	var ptr bool
-	for typStruct.Kind() == reflect.Ptr {
+	if typStruct.Kind() == reflect.Ptr {
 		ptr = true
 		typStruct = typStruct.Elem()
 	}
 	v := reflect.New(typStruct).Elem()
 	for i := 0; i < n; i += 2 {
 		index := args[i].(int)
-		reflectx.Field(v, index).Set(reflect.ValueOf(args[i+1]))
+		Field(v, index).Set(reflect.ValueOf(args[i+1]))
 	}
 	if ptr {
 		p.Ret(n, v.Addr().Interface())
diff --git a/exec/golang/expr.go b/exec/golang/expr.go
index eaf8f665..dea2fac5 100644
--- a/exec/golang/expr.go
+++ b/exec/golang/expr.go
@@ -446,7 +446,7 @@ func (p *Builder) fieldExpr(typ reflect.Type, index []int) ast.Expr {
 	}
 	for i := 0; i < len(index); i++ {
 		sf := typ.FieldByIndex(index[:i+1])
-		if sf.Anonymous && i < len(index)-1 {
+		if sf.Anonymous {
 			continue
 		}
 		if expr.Sel != nil {
diff --git a/exec/golang/type.go b/exec/golang/type.go
index 287596cf..ebda278e 100644
--- a/exec/golang/type.go
+++ b/exec/golang/type.go
@@ -37,10 +37,8 @@ func StructType(p *Builder, typ reflect.Type) ast.Expr {
 
 func toStructField(p *Builder, f reflect.StructField) *ast.Field {
 	var field = &ast.Field{}
-	if !f.Anonymous {
-		field.Names = []*ast.Ident{
-			Ident(f.Name),
-		}
+	field.Names = []*ast.Ident{
+		Ident(f.Name),
 	}
 	field.Type = Type(p, f.Type)
 	return field
diff --git a/go.mod b/go.mod
index 70a74a59..6b1deeb9 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,6 @@ module github.com/goplus/gop
 go 1.14
 
 require (
-	github.com/goplus/reflectx v0.3.1
 	github.com/peterh/liner v1.2.0
 	github.com/qiniu/x v1.11.5
 )
diff --git a/go.sum b/go.sum
index 1d574965..72a2c58b 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,6 @@
-github.com/goplus/reflectx v0.3.1 h1:qf45CZJfo4VqbuMFyOjrjnF7LDIHoB9c6ltbejQLuvw=
-github.com/goplus/reflectx v0.3.1/go.mod h1:XPDe5lYQ/8FN05bhqv6r1hhLxwmYIkZ5UvIkN1GNRYg=
+github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
 github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg=
 github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
 github.com/qiniu/x v1.11.5 h1:TYr5cl4g2yoHAZeDK4MTjKF6CMoG+IHlCDvvM5qym6U=
 github.com/qiniu/x v1.11.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=


Test patch:
diff --git a/cl/expr_test.go b/cl/expr_test.go
index 5512c655..edc5b29e 100644
--- a/cl/expr_test.go
+++ b/cl/expr_test.go
@@ -833,20 +833,6 @@ func TestPkgMethod(t *testing.T) {
 	`, "int\n")
 }
 
-func TestPkgMethodBadCall(t *testing.T) {
-	cltest.Expect(t, `
-	import "bytes"
-	buf := bytes.NewBuffer([]byte("hello"))
-	println((&buf).String())
-	`, "", "calling method String with receiver &buf (type **bytes.Buffer) requires explicit dereference.")
-	cltest.Expect(t, `
-	import "reflect"
-	v := reflect.ValueOf(100)
-	p := &v
-	println((&p).Kind())
-	`, "", "calling method Kind with receiver &p (type **reflect.Value) requires explicit dereference.")
-}
-
 func TestComplex(t *testing.T) {
 	cltest.Expect(t, `
 	c := complex(1,2)
@@ -1429,208 +1415,6 @@ func TestMethodCases(t *testing.T) {
 	testScripts(t, "TestMethod", testMethodClauses)
 }
 
-func TestEmbeddedField(t *testing.T) {
-	cltest.Expect(t, `
-	type Base struct {
-		Info string
-	}
-	type Point struct {
-		X int
-		Y int
-	}
-	type My struct {
-		Base
-		Point
-	}
-	m := &My{Base:Base{"hello"},Point{10,20}}
-	println(m.Info,m.X,m.Y)
-	m.Info = "world"
-	m.Point = Point{-10,-20}
-	println(m.Info,m.X,m.Y)
-	m.Base = Base{"goplus"}
-	m.Point.X = 100
-	m.Y = 200
-	println(m.Info,m.X,m.Y)
-	`, "hello 10 20\nworld -10 -20\ngoplus 100 200\n")
-	cltest.Expect(t, `
-	type Base struct {
-		Info string
-	}
-	type Point struct {
-		X int
-		Y int
-	}
-	type My struct {
-		Base
-		*Point
-	}
-	m := &My{Base:Base{"hello"},&Point{10,20}}
-	println(m.Info,m.X,m.Y)
-	m.Info = "world"
-	m.Point = &Point{-10,-20}
-	println(m.Info,m.X,m.Y)
-	m.Base = Base{"goplus"}
-	m.Point.X = 100
-	m.Y = 200
-	println(m.Info,m.X,m.Y)
-	`, "hello 10 20\nworld -10 -20\ngoplus 100 200\n")
-	cltest.Expect(t, `
-	import "bytes"
-	type Buf struct {
-		*bytes.Buffer
-	}
-	buf := &Buf{bytes.NewBufferString("hello")}
-	println(buf)
-	`, "&{hello}\n")
-	cltest.Expect(t, `
-	import "reflect"
-	type Value struct {
-		reflect.Value
-	}
-	v := Value{reflect.ValueOf(100)}
-	println(v.Value)
-	`, "100\n")
-}
-
-func TestEmbeddedMethod(t *testing.T) {
-	cltest.Expect(t, `
-	import "bytes"
-	type Buf struct {
-		*bytes.Buffer
-	}
-	buf := &Buf{&bytes.Buffer{}}
-	buf.Write([]byte("hello"))
-	println(buf.String())
-	`, "hello\n")
-	cltest.Expect(t, `
-	import "bytes"
-	type Buf struct {
-		*bytes.Buffer
-	}
-	buf := Buf{&bytes.Buffer{}}
-	buf.Write([]byte("hello"))
-	println(buf.String())
-	`, "hello\n")
-	cltest.Expect(t, `
-	import "bytes"
-	type Buf struct {
-		*bytes.Buffer
-		size int
-	}
-	buf := Buf{&bytes.Buffer{},1}
-	buf.Write([]byte("hello"))
-	println(buf)
-	`, "{hello 1}\n")
-	cltest.Expect(t, `
-	import "reflect"
-	type Value struct {
-		reflect.Value
-	}
-	v := Value{reflect.ValueOf(100)}
-	println(v.Kind())
-	`, "int\n")
-	cltest.Expect(t, `
-	import "reflect"
-	type Value struct {
-		reflect.Value
-	}
-	v := &Value{reflect.ValueOf(100)}
-	println(v.Kind())
-	`, "int\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p Point) Test() {
-		println(p.X,p.Y)
-	}
-	type My struct {
-		Point
-	}
-	m := &My{Point{10,20}}
-	m.Test()
-	`, "10 20\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p Point) Test() {
-		println(p.X,p.Y)
-	}
-	type My struct {
-		Point
-	}
-	m := My{Point{10,20}}
-	m.Test()
-	`, "10 20\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p *Point) Test() {
-		println(p.X,p.Y)
-	}
-	type My struct {
-		Point
-	}
-	m := &My{Point{10,20}}
-	m.Test()
-	`, "10 20\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p *Point) Test() {
-		println(p.X,p.Y)
-	}
-	type My struct {
-		*Point
-	}
-	m := &My{&Point{10,20}}
-	m.Test()
-	`, "10 20\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p *Point) Test() {
-		println(p.X,p.Y)
-	}
-	type Base struct {
-		*Point
-	}
-	type My struct {
-		Base
-	}
-	m := &My{}
-	m.Point = &Point{10,20}
-	m.Test()
-	`, "10 20\n")
-	cltest.Expect(t, `
-	type Point struct {
-		X int
-		Y int
-	}
-	func (p *Point) Test() {
-		println(p.X,p.Y)
-	}
-	type Base struct {
-		*Point
-	}
-	type My struct {
-		*Base
-		size int
-	}
-	m := &My{&Base{&Point{10,20}},1}
-	m.Test()
-	`, "10 20\n")
-}
-
 // -----------------------------------------------------------------------------
 
 var testStarExprClauses = map[string]testData{