Handle composite types with sub-types imported from runtime

This commit is contained in:
Marc Vertes
2018-06-28 14:22:20 +02:00
parent 77c015fcb8
commit 539f6f1c6f
4 changed files with 87 additions and 22 deletions

24
_test/type2.go Normal file
View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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})
}