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
|
typeName := n.child[0].ident
|
||||||
if n.child[1].kind == Ident {
|
if n.child[1].kind == Ident {
|
||||||
// Create a type alias of an existing one
|
// 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 {
|
} else {
|
||||||
// Define a new type
|
// Define a new type
|
||||||
interp.types[typeName] = nodeType(interp.types, n.child[1])
|
interp.types[typeName] = nodeType(interp, n.child[1])
|
||||||
}
|
}
|
||||||
//if canExport(typeName) {
|
//if canExport(typeName) {
|
||||||
// (*exports)[funcName] = reflect.MakeFunc(n.child[2].typ.TypeOf(), n.wrapNode).Interface()
|
// (*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
|
return false
|
||||||
|
|
||||||
case ArrayType, BasicLit, ChanType, MapType, StructType:
|
case ArrayType, BasicLit, ChanType, MapType, StructType:
|
||||||
n.typ = nodeType(interp.types, n)
|
n.typ = nodeType(interp, n)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -307,7 +307,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
|
|||||||
n.child[0].typ = &Type{cat: BuiltinT}
|
n.child[0].typ = &Type{cat: BuiltinT}
|
||||||
if n.child[0].ident == "make" {
|
if n.child[0].ident == "make" {
|
||||||
if n.typ = interp.types[n.child[1].ident]; n.typ == nil {
|
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].val = n.typ
|
||||||
n.child[1].kind = BasicLit
|
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 {
|
} else if n.child[0].kind == SelectorExpr {
|
||||||
if n.child[0].typ.cat == ValueT {
|
if n.child[0].typ.cat == ValueT {
|
||||||
n.run = callBinMethod
|
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.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.typ = &Type{cat: ValueT, rtype: n.child[0].typ.rtype}
|
||||||
n.fsize = n.child[0].fsize
|
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
|
// Otherwise, just point to corresponding location in frame, resolved in
|
||||||
// ident child.
|
// ident child.
|
||||||
l := len(n.child) - 1
|
l := len(n.child) - 1
|
||||||
n.typ = nodeType(interp.types, n.child[l])
|
n.typ = nodeType(interp, n.child[l])
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
frameIndex.max++
|
frameIndex.max++
|
||||||
n.findex = frameIndex.max
|
n.findex = frameIndex.max
|
||||||
@@ -554,7 +554,7 @@ func (interp *Interpreter) Cfg(root *Node, sdef *NodeMap) []*Node {
|
|||||||
funcDef = true
|
funcDef = true
|
||||||
|
|
||||||
case FuncType:
|
case FuncType:
|
||||||
n.typ = nodeType(interp.types, n)
|
n.typ = nodeType(interp, n)
|
||||||
// Store list of parameter frame indices in params val
|
// Store list of parameter frame indices in params val
|
||||||
var list []int
|
var list []int
|
||||||
for _, c := range n.child[0].child {
|
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 {
|
if typ := reflect.TypeOf(s); typ.Kind() == reflect.Func {
|
||||||
n.typ = &Type{cat: ValueT, rtype: typ}
|
n.typ = &Type{cat: ValueT, rtype: typ}
|
||||||
n.fsize = typ.NumOut()
|
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
|
// 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 {
|
} else {
|
||||||
n.typ = &Type{cat: ValueT, rtype: typ}
|
n.typ = &Type{cat: ValueT, rtype: typ}
|
||||||
n.rval = n.val.(reflect.Value)
|
n.rval = n.val.(reflect.Value)
|
||||||
|
|||||||
@@ -2749,6 +2749,38 @@ func main() {
|
|||||||
// hello
|
// 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() {
|
func Example_var() {
|
||||||
src := `
|
src := `
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ var defaultTypes TypeMap = map[string]*Type{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return a type definition for the corresponding AST subtree
|
// 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 {
|
if n.typ != nil {
|
||||||
return n.typ
|
return n.typ
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ func nodeType(tdef TypeMap, n *Node) *Type {
|
|||||||
switch n.kind {
|
switch n.kind {
|
||||||
case ArrayType:
|
case ArrayType:
|
||||||
t.cat = ArrayT
|
t.cat = ArrayT
|
||||||
t.val = nodeType(tdef, n.child[0])
|
t.val = nodeType(interp, n.child[0])
|
||||||
case BasicLit:
|
case BasicLit:
|
||||||
switch n.val.(type) {
|
switch n.val.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
@@ -167,42 +167,51 @@ func nodeType(tdef TypeMap, n *Node) *Type {
|
|||||||
}
|
}
|
||||||
case ChanType:
|
case ChanType:
|
||||||
t.cat = ChanT
|
t.cat = ChanT
|
||||||
t.val = nodeType(tdef, n.child[0])
|
t.val = nodeType(interp, n.child[0])
|
||||||
case Ellipsis:
|
case Ellipsis:
|
||||||
t = nodeType(tdef, n.child[0])
|
t = nodeType(interp, n.child[0])
|
||||||
t.variadic = true
|
t.variadic = true
|
||||||
case FuncType:
|
case FuncType:
|
||||||
t.cat = FuncT
|
t.cat = FuncT
|
||||||
for _, arg := range n.child[0].child {
|
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 {
|
if len(n.child) == 2 {
|
||||||
for _, ret := range n.child[1].child {
|
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:
|
case Ident:
|
||||||
t = tdef[n.ident]
|
t = interp.types[n.ident]
|
||||||
case InterfaceType:
|
case InterfaceType:
|
||||||
t.cat = InterfaceT
|
t.cat = InterfaceT
|
||||||
//for _, method := range n.child[0].child {
|
//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:
|
case MapType:
|
||||||
t.cat = MapT
|
t.cat = MapT
|
||||||
t.key = nodeType(tdef, n.child[0])
|
t.key = nodeType(interp, n.child[0])
|
||||||
t.val = nodeType(tdef, n.child[1])
|
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:
|
case StarExpr:
|
||||||
t.cat = PtrT
|
t.cat = PtrT
|
||||||
t.val = nodeType(tdef, n.child[0])
|
t.val = nodeType(interp, n.child[0])
|
||||||
case StructType:
|
case StructType:
|
||||||
t.cat = StructT
|
t.cat = StructT
|
||||||
for _, c := range n.child[0].child {
|
for _, c := range n.child[0].child {
|
||||||
if len(c.child) == 1 {
|
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 {
|
} else {
|
||||||
l := len(c.child)
|
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] {
|
for _, d := range c.child[:l-1] {
|
||||||
t.field = append(t.field, StructField{name: d.ident, typ: typ})
|
t.field = append(t.field, StructField{name: d.ident, typ: typ})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user