diff --git a/_test/type2.go b/_test/type2.go new file mode 100644 index 00000000..453fd4b6 --- /dev/null +++ b/_test/type2.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + "time" +) + +type Options struct { + debug bool +} + +type T1 struct { + opt Options + time time.Time +} + +func main() { + t := T1{} + t.time = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(t.time) +} + +// Output: +// 2009-11-10 23:00:00 +0000 UTC diff --git a/interp/cfg.go b/interp/cfg.go index 1a1d86e3..156fdc45 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -156,10 +156,10 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { typeName := n.child[0].ident if n.child[1].kind == Ident { // Create a type alias of an existing one - interp.types[typeName] = &Type{cat: AliasT, val: nodeType(interp.types, n.child[1])} + interp.types[typeName] = &Type{cat: AliasT, val: nodeType(interp, n.child[1])} } else { // Define a new type - interp.types[typeName] = nodeType(interp.types, n.child[1]) + interp.types[typeName] = nodeType(interp, n.child[1]) } //if canExport(typeName) { // (*exports)[funcName] = reflect.MakeFunc(n.child[2].typ.TypeOf(), n.wrapNode).Interface() @@ -167,7 +167,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { return false case ArrayType, BasicLit, ChanType, MapType, StructType: - n.typ = nodeType(interp.types, n) + n.typ = nodeType(interp, n) return false } return true @@ -307,7 +307,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { n.child[0].typ = &Type{cat: BuiltinT} if n.child[0].ident == "make" { if n.typ = interp.types[n.child[1].ident]; n.typ == nil { - n.typ = nodeType(interp.types, n.child[1]) + n.typ = nodeType(interp, n.child[1]) } n.child[1].val = n.typ n.child[1].kind = BasicLit @@ -343,7 +343,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { } else if n.child[0].kind == SelectorExpr { if n.child[0].typ.cat == ValueT { n.run = callBinMethod - // TODO: handle multiple return value + // TODO: handle multiple return value (_test/time2.go) n.child[0].kind = BasicLit // Temporary hack for force value() to return n.val at run n.typ = &Type{cat: ValueT, rtype: n.child[0].typ.rtype} n.fsize = n.child[0].fsize @@ -450,7 +450,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { // Otherwise, just point to corresponding location in frame, resolved in // ident child. l := len(n.child) - 1 - n.typ = nodeType(interp.types, n.child[l]) + n.typ = nodeType(interp, n.child[l]) if l == 0 { frameIndex.max++ n.findex = frameIndex.max @@ -554,7 +554,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { funcDef = true case FuncType: - n.typ = nodeType(interp.types, n) + n.typ = nodeType(interp, n) // Store list of parameter frame indices in params val var list []int for _, c := range n.child[0].child { @@ -736,9 +736,9 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node { if typ := reflect.TypeOf(s); typ.Kind() == reflect.Func { n.typ = &Type{cat: ValueT, rtype: typ} n.fsize = typ.NumOut() - } else if typ.Kind() == reflect.Ptr { + //} else if typ.Kind() == reflect.Ptr { // a symbol of kind pointer must be dereferenced to access type - n.typ = &Type{cat: ValueT, rtype: typ.Elem(), rzero: n.val.(reflect.Value).Elem()} + // n.typ = &Type{cat: ValueT, rtype: typ.Elem(), rzero: n.val.(reflect.Value).Elem()} } else { n.typ = &Type{cat: ValueT, rtype: typ} n.rval = n.val.(reflect.Value) diff --git a/interp/interp_test.go b/interp/interp_test.go index 391fed98..61534139 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -2749,6 +2749,38 @@ func main() { // hello } +func Example_type2() { + src := ` +package main + +import ( + "fmt" + "time" +) + +type Options struct { + debug bool +} + +type T1 struct { + opt Options + time time.Time +} + +func main() { + t := T1{} + t.time = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + fmt.Println(t.time) +} +` + i := NewInterpreter(Opt{Entry: "main"}) + i.ImportBin(export.Pkg) + i.Eval(src) + + // Output: + // 2009-11-10 23:00:00 +0000 UTC +} + func Example_var() { src := ` package main diff --git a/interp/type.go b/interp/type.go index d1b9ae9e..8ad3f640 100644 --- a/interp/type.go +++ b/interp/type.go @@ -139,7 +139,7 @@ var defaultTypes TypeMap = map[string]*Type{ } // return a type definition for the corresponding AST subtree -func nodeType(tdef TypeMap, n *Node) *Type { +func nodeType(interp *Interpreter, n *Node) *Type { if n.typ != nil { return n.typ } @@ -147,7 +147,7 @@ func nodeType(tdef TypeMap, n *Node) *Type { switch n.kind { case ArrayType: t.cat = ArrayT - t.val = nodeType(tdef, n.child[0]) + t.val = nodeType(interp, n.child[0]) case BasicLit: switch n.val.(type) { case bool: @@ -167,42 +167,51 @@ func nodeType(tdef TypeMap, n *Node) *Type { } case ChanType: t.cat = ChanT - t.val = nodeType(tdef, n.child[0]) + t.val = nodeType(interp, n.child[0]) case Ellipsis: - t = nodeType(tdef, n.child[0]) + t = nodeType(interp, n.child[0]) t.variadic = true case FuncType: t.cat = FuncT for _, arg := range n.child[0].child { - t.arg = append(t.arg, nodeType(tdef, arg.child[len(arg.child)-1])) + t.arg = append(t.arg, nodeType(interp, arg.child[len(arg.child)-1])) } if len(n.child) == 2 { for _, ret := range n.child[1].child { - t.ret = append(t.ret, nodeType(tdef, ret.child[len(ret.child)-1])) + t.ret = append(t.ret, nodeType(interp, ret.child[len(ret.child)-1])) } } case Ident: - t = tdef[n.ident] + t = interp.types[n.ident] case InterfaceType: t.cat = InterfaceT //for _, method := range n.child[0].child { - // t.method = append(t.method, nodeType(tdef, method)) + // t.method = append(t.method, nodeType(interp, method)) //} case MapType: t.cat = MapT - t.key = nodeType(tdef, n.child[0]) - t.val = nodeType(tdef, n.child[1]) + t.key = nodeType(interp, n.child[0]) + t.val = nodeType(interp, n.child[1]) + case SelectorExpr: + pkgName, typeName := n.child[0].ident, n.child[1].ident + if pkg, ok := interp.binPkg[pkgName]; ok { + if typ, ok := (*pkg)[typeName]; ok { + t.cat = ValueT + t.rtype = reflect.TypeOf(typ).Elem() + log.Println("found bin type", t.rtype) + } + } case StarExpr: t.cat = PtrT - t.val = nodeType(tdef, n.child[0]) + t.val = nodeType(interp, n.child[0]) case StructType: t.cat = StructT for _, c := range n.child[0].child { if len(c.child) == 1 { - t.field = append(t.field, StructField{typ: nodeType(tdef, c.child[0])}) + t.field = append(t.field, StructField{typ: nodeType(interp, c.child[0])}) } else { l := len(c.child) - typ := nodeType(tdef, c.child[l-1]) + typ := nodeType(interp, c.child[l-1]) for _, d := range c.child[:l-1] { t.field = append(t.field, StructField{name: d.ident, typ: typ}) }