Handle composite types with sub-types imported from runtime
This commit is contained in:
24
_test/type2.go
Normal file
24
_test/type2.go
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user