improve handling of closures (in progress)

This commit is contained in:
Marc Vertes
2018-10-24 15:13:21 +02:00
parent 0618fa54db
commit 799e832193
11 changed files with 547 additions and 360 deletions

25
_test/a16.go Normal file
View File

@@ -0,0 +1,25 @@
package main
func main() {
a := [6]int{1, 2, 3, 4, 5, 6}
println(a[1]) // 2
for k := 0; k < 2; k++ {
for i, v := range a {
println(v)
if i == 3 {
break
}
}
}
}
// Output:
// 2
// 1
// 2
// 3
// 4
// 1
// 2
// 3
// 4

11
_test/a17.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := make([]int, 2, 7)
fmt.Println(a, len(a), cap(a))
}
// Output:
// [0 0] 2 7

View File

@@ -2,12 +2,13 @@ package main
import "fmt"
var (
samples = []int{}
b = 1
)
//var (
// samples = []int{}
// b = 1
//)
func main() {
var samples = []int{}
samples = append(samples, 1)
fmt.Println(samples)
}

View File

@@ -3,8 +3,10 @@ package main
type adder func(int, int) int
func genAdd(k int) adder {
println("k:", k)
return func(i, j int) int {
return i + j
println("#1 k:", k)
return i + j + k
}
}
@@ -14,4 +16,4 @@ func main() {
}
// Output:
// 7
// 12

View File

@@ -1,8 +1,11 @@
package main
func main() {
dict := map[string]string{}
dict["truc"] = "machin"
//dict := map[string]string{}
dict := map[string]string{"bidule": "machin", "truc": "bidule"}
//println(dict)
//dict["truc"] = "machin"
//println(dict)
println(dict["truc"])
}

12
_test/map6.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func main() {
dict := map[string]string{"bidule": "machin", "truc": "chouette"}
for k, v := range dict {
println(k, v)
}
}
// Output:
// bidule machin
// truc chouette

28
_test/struct8.go Normal file
View File

@@ -0,0 +1,28 @@
package main
type T3 struct {
k int
}
type T2 struct {
h int
T3
}
type T struct {
f int
g int
T2
}
func f(i int) int { return i * i }
func main() {
a := T{5, 7, T2{8, T3{9}}}
//println(a.f, a.g, a.T2.h, a.T2.T3.k)
//fmt.Println(a.T2)
println(a.h)
}
// Output:
// 5 7 8 9

View File

@@ -221,6 +221,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
scope.sym[name] = &Symbol{index: scope.size, kind: Var}
}
if n.child[1].action == GetFunc {
log.Println(n.index, "assign getFunc")
scope.sym[name].index = -1
scope.sym[name].node = n.child[1]
}
@@ -488,19 +489,11 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
n.typ = &Type{cat: ValueT}
} else {
n.val = sym.node
if def := n.val.(*Node); def != nil {
// Reserve as many frame entries as nb of ret values for called function
// node frame index should point to the first entry
j := len(def.child[2].child) - 1
l := len(def.child[2].child[j].child) // Number of return values for def
if l == 1 {
// If def returns exactly one value, propagate its type in call node.
// Multiple return values will be handled differently through AssignX.
n.typ = scope.getType(def.child[2].child[j].child[0].child[0].ident)
}
n.fsize = l
} else {
log.Println(n.index, "call to unknown def", n.child[0].ident, sym.typ)
n.fsize = len(sym.typ.ret)
if n.fsize == 1 {
// If called func returns exactly one value, propagate its type in call node.
// Multiple return values will be handled differently through AssignX.
n.typ = sym.typ.ret[0]
}
}
} else if n.child[0].kind == SelectorSrc {
@@ -569,6 +562,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
} else {
for _, f := range n.child[:l] {
scope.sym[f.ident].typ = n.typ
f.typ = n.typ
}
}
@@ -660,7 +654,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
interp.scope[pkgName].sym[funcName].typ = n.typ
interp.scope[pkgName].sym[funcName].kind = Func
interp.scope[pkgName].sym[funcName].node = n
n.types = frameTypes(n.child[3], n.flen)
n.types = frameTypes(n, n.flen)
case FuncLit:
n.typ = n.child[2].typ
@@ -668,8 +662,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
n.flen = scope.size + 1
scope = scope.pop()
funcDef = true
n.types = frameTypes(n.child[3], n.flen)
n.start = n.child[3].start
n.types = frameTypes(n, n.flen)
case FuncType:
n.typ = nodeType(interp, scope, n)
@@ -965,12 +958,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
}
})
//root.Walk(func(n *Node) bool {
// n.value = genValue(n)
// //n.pvalue = genPvalue(n)
// return true
//}, nil)
return initNodes
}
@@ -1098,7 +1085,10 @@ func valueGenerator(n *Node, i int) func(*Frame) reflect.Value {
case 0:
return func(f *Frame) reflect.Value { return f.data[i] }
case 1:
return func(f *Frame) reflect.Value { return f.anc.data[i] }
return func(f *Frame) reflect.Value {
//log.Println(n.index, i, f.anc.data[i])
return f.anc.data[i]
}
case 2:
return func(f *Frame) reflect.Value { return f.anc.anc.data[i] }
default:
@@ -1178,14 +1168,18 @@ func frameTypes(node *Node, size int) []reflect.Type {
ft := make([]reflect.Type, size)
node.Walk(func(n *Node) bool {
if n.kind == FuncDecl || n.kind == ImportDecl || n.kind == TypeDecl {
return false
if n.kind == FuncDecl || n.kind == ImportDecl || n.kind == TypeDecl || n.kind == FuncLit {
return n == node // Do not dive in substree, except if this the entry point
}
if n.typ == nil || n.level > 0 || n.kind == BasicLit || n.kind == SelectorSrc {
return true
}
if ft[n.findex] == nil {
ft[n.findex] = n.typ.TypeOf()
if n.typ.cat == FuncT {
ft[n.findex] = reflect.TypeOf(n)
} else {
ft[n.findex] = n.typ.TypeOf()
}
} else {
// TODO: Check that type is identical
}

View File

@@ -2,6 +2,32 @@ package interp
// Do not edit! File generated by ../_test/gen_example.sh
func Example_a1() {
src := `
package main
func main() {
a := [6]int{1, 2, 3, 4, 5, 6}
println(a[1]) // 2
for i, v := range a {
println(v)
if i == 3 {
break
}
}
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 2
// 1
// 2
// 3
// 4
}
func Example_a10() {
src := `
package main
@@ -125,17 +151,19 @@ func main() {
}
func Example_a1() {
func Example_a16() {
src := `
package main
func main() {
a := [6]int{1, 2, 3, 4, 5, 6}
println(a[1]) // 2
for i, v := range a {
println(v)
if i == 3 {
break
for k := 0; k < 2; k++ {
for i, v := range a {
println(v)
if i == 3 {
break
}
}
}
}
@@ -149,6 +177,28 @@ func main() {
// 2
// 3
// 4
// 1
// 2
// 3
// 4
}
func Example_a17() {
src := `
package main
import "fmt"
func main() {
a := make([]int, 2, 7)
fmt.Println(a, len(a), cap(a))
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// [0 0] 2 7
}
func Example_a2() {
@@ -292,12 +342,13 @@ package main
import "fmt"
var (
samples = []int{}
b = 1
)
//var (
// samples = []int{}
// b = 1
//)
func main() {
var samples = []int{}
samples = append(samples, 1)
fmt.Println(samples)
}
@@ -357,20 +408,6 @@ func main() {
// 1 2
}
func Example_bool0() {
src := `
package main
import "fmt"
func main() {
fmt.Println(true)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_bool() {
src := `
package main
@@ -388,6 +425,20 @@ func main() {
// false true
}
func Example_bool0() {
src := `
package main
import "fmt"
func main() {
fmt.Println(true)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_chan0() {
src := `
package main
@@ -630,6 +681,30 @@ func main() { println(a, b, c) }
// 1 2 3
}
func Example_cont() {
src := `
package main
func main() {
for i := 0; i < 10; i++ {
if i < 5 {
continue
}
println(i)
}
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 5
// 6
// 7
// 8
// 9
}
func Example_cont0() {
src := `
package main
@@ -692,30 +767,6 @@ func main() {
// 10
}
func Example_cont() {
src := `
package main
func main() {
for i := 0; i < 10; i++ {
if i < 5 {
continue
}
println(i)
}
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 5
// 6
// 7
// 8
// 9
}
func Example_export0() {
src := `
package main
@@ -742,6 +793,27 @@ func (s *Sample) Test() {
}
func Example_fib() {
src := `
package main
// Compute fibonacci numbers, no memoization
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-2) + fib(n-1)
}
func main() {
println(fib(35))
//println(fib(10))
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_fib0() {
src := `
package main
@@ -765,27 +837,6 @@ func main() {
// 3
}
func Example_fib() {
src := `
package main
// Compute fibonacci numbers, no memoization
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-2) + fib(n-1)
}
func main() {
println(fib(35))
//println(fib(10))
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_for0() {
src := `
package main
@@ -862,6 +913,23 @@ func main() {
// 4
}
func Example_fun() {
src := `
package main
func f(i int) int { return i + 15 }
func main() {
println(f(4))
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 19
}
func Example_fun2() {
src := `
package main
@@ -920,23 +988,6 @@ func main() {
// ok
}
func Example_fun() {
src := `
package main
func f(i int) int { return i + 15 }
func main() {
println(f(4))
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 19
}
func Example_goroutine() {
src := `
package main
@@ -1181,38 +1232,6 @@ func main() {
}
func Example_iota0() {
src := `
package main
import "fmt"
func main() {
const (
Foo = iota
Bar
Baz
)
const (
Asm = iota
C
Java
Go
)
fmt.Println(Foo, Bar, Baz)
fmt.Println(Asm, C, Java, Go)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0 1 2
// 0 1 2 3
}
func Example_iota() {
src := `
package main
@@ -1245,6 +1264,38 @@ func main() {
// 0 1 2 3
}
func Example_iota0() {
src := `
package main
import "fmt"
func main() {
const (
Foo = iota
Bar
Baz
)
const (
Asm = iota
C
Java
Go
)
fmt.Println(Foo, Bar, Baz)
fmt.Println(Asm, C, Java, Go)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0 1 2
// 0 1 2 3
}
func Example_ioutil() {
src := `
package main
@@ -1288,7 +1339,7 @@ func Example_l3() {
src := `
package main
func myprint(i int) { println(i) }
//func myprint(i int) { println(i) }
func main() {
for a := 0; a < 20000000; a++ {
@@ -1317,6 +1368,44 @@ func f(i int) int { return i + 1 }
// 6
}
func Example_l5() {
src := `
package main
//func myprint(i int) { println(i) }
func main() {
for a := 0; a < 20000000; {
if a&0x8ffff == 0x80000 {
println(a)
}
a = a + 1
}
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_map() {
src := `
package main
type Dict map[string]string
func main() {
dict := make(Dict)
dict["truc"] = "machin"
println(dict["truc"])
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// machin
}
func Example_map2() {
src := `
package main
@@ -1339,8 +1428,11 @@ func Example_map3() {
package main
func main() {
dict := map[string]string{}
dict["truc"] = "machin"
//dict := map[string]string{}
dict := map[string]string{"bidule": "machin", "truc": "bidule"}
//println(dict)
//dict["truc"] = "machin"
//println(dict)
println(dict["truc"])
}
`
@@ -1389,23 +1481,23 @@ func main() {
// false
}
func Example_map() {
func Example_map6() {
src := `
package main
type Dict map[string]string
func main() {
dict := make(Dict)
dict["truc"] = "machin"
println(dict["truc"])
dict := map[string]string{"bidule": "machin", "truc": "chouette"}
for k, v := range dict {
println(k, v)
}
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// machin
// bidule machin
// truc chouette
}
func Example_math0() {
@@ -1428,6 +1520,28 @@ func main() {
// -1
}
func Example_method() {
src := `
package main
type Coord struct {
x, y int
}
func (c Coord) dist() int { return c.x*c.x + c.y*c.y }
func main() {
o := Coord{3, 4}
println(o.dist())
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 25
}
func Example_method0() {
src := `
package main
@@ -1468,6 +1582,31 @@ func main() {
// Baz Called
}
func Example_method1() {
src := `
package main
type Sample struct {
Name string
}
func (s *Sample) foo(i int) {
println("in foo", s.Name, i)
}
func main() {
sample := Sample{"hello"}
s := &sample
s.foo(3)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// in foo hello 3
}
func Example_method10() {
src := `
package main
@@ -1512,31 +1651,6 @@ type Coord struct {
// 25
}
func Example_method1() {
src := `
package main
type Sample struct {
Name string
}
func (s *Sample) foo(i int) {
println("in foo", s.Name, i)
}
func main() {
sample := Sample{"hello"}
s := &sample
s.foo(3)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// in foo hello 3
}
func Example_method2() {
src := `
package main
@@ -1773,28 +1887,6 @@ func (c Coord) dist() int { return c.x*c.x + c.y*c.y }
// 25
}
func Example_method() {
src := `
package main
type Coord struct {
x, y int
}
func (c Coord) dist() int { return c.x*c.x + c.y*c.y }
func main() {
o := Coord{3, 4}
println(o.dist())
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 25
}
func Example_neg0() {
src := `
package main
@@ -2018,6 +2110,26 @@ func main() {
// 5
}
func Example_ptr5() {
src := `
package main
type Foo struct {
val int
}
func main() {
var a = &Foo{3}
println(a.val)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 3
}
func Example_ptr5a() {
src := `
package main
@@ -2039,26 +2151,6 @@ func main() {
// 3
}
func Example_ptr5() {
src := `
package main
type Foo struct {
val int
}
func main() {
var a = &Foo{3}
println(a.val)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 3
}
func Example_ptr6() {
src := `
package main
@@ -2146,6 +2238,25 @@ func main() {
// 2 3
}
func Example_run1() {
src := `
package main
func f() (int, int) { return 2, 3 }
func g(i, j int) int { return i + j }
func main() {
println(g(f()))
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 5
}
func Example_run10() {
src := `
package main
@@ -2218,25 +2329,6 @@ func f(a int) (int, int) {
// 4 5
}
func Example_run1() {
src := `
package main
func f() (int, int) { return 2, 3 }
func g(i, j int) int { return i + j }
func main() {
println(g(f()))
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 5
}
func Example_run4() {
src := `
package main
@@ -2530,6 +2622,30 @@ func main() {
// [6 7]
}
func Example_server() {
src := `
package main
import (
"fmt"
"net/http"
)
var v string = "v1.0"
func main() {
a := "hello "
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Welcome to my website! ", a, v)
})
http.ListenAndServe(":8080", nil)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_server0() {
src := `
package main
@@ -2555,6 +2671,33 @@ func main() {
}
func Example_server1() {
src := `
package main
import (
"fmt"
"net/http"
)
type Middleware struct {
Name string
}
func (m *Middleware) Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", m.Name)
}
func main() {
m := &Middleware{"Test"}
http.HandleFunc("/", m.Handler)
http.ListenAndServe(":8080", nil)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_server1a() {
src := `
package main
@@ -2588,33 +2731,6 @@ func main() {
}
func Example_server1() {
src := `
package main
import (
"fmt"
"net/http"
)
type Middleware struct {
Name string
}
func (m *Middleware) Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Welcome to my website", m.Name)
}
func main() {
m := &Middleware{"Test"}
http.HandleFunc("/", m.Handler)
http.ListenAndServe(":8080", nil)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_server2() {
src := `
package main
@@ -2737,30 +2853,6 @@ func main() {
}
func Example_server() {
src := `
package main
import (
"fmt"
"net/http"
)
var v string = "v1.0"
func main() {
a := "hello "
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Welcome to my website! ", a, v)
})
http.ListenAndServe(":8080", nil)
}`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
}
func Example_sieve() {
src := `
// A concurrent prime sieve
@@ -2913,27 +3005,25 @@ func main() {
// hello world
}
func Example_struct0a() {
func Example_struct() {
src := `
package main
type T struct {
f int
g int
}
func main() {
a := T{}
println(a.f)
a.f = 8
println(a.f)
a := T{7, 8}
println(a.f, a.g)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0
// 8
// 7 8
}
func Example_struct0() {
@@ -2957,6 +3047,29 @@ func main() {
// 0 0
}
func Example_struct0a() {
src := `
package main
type T struct {
f int
}
func main() {
a := T{}
println(a.f)
a.f = 8
println(a.f)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0
// 8
}
func Example_struct1() {
src := `
package main
@@ -3127,25 +3240,39 @@ func main() {
}
func Example_struct() {
func Example_struct8() {
src := `
package main
type T3 struct {
k int
}
type T2 struct {
h int
T3
}
type T struct {
f int
g int
T2
}
func f(i int) int { return i * i }
func main() {
a := T{7, 8}
println(a.f, a.g)
a := T{5, 7, T2{8, T3{9}}}
//println(a.f, a.g, a.T2.h, a.T2.T3.k)
//fmt.Println(a.T2)
println(a.h)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 7 8
// 5 7 8 9
}
func Example_switch() {
@@ -3438,6 +3565,22 @@ type T int
// int
}
func Example_var() {
src := `
package main
func main() {
var a, b, c int
println(a, b, c)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0 0 0
}
func Example_var2() {
src := `
package main
@@ -3486,20 +3629,25 @@ func main() {
// 2 3
}
func Example_var() {
func Example_variadic() {
src := `
package main
import "fmt"
func f(a ...int) {
fmt.Println(a)
}
func main() {
var a, b, c int
println(a, b, c)
f(1, 2, 3, 4)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// 0 0 0
// [1 2 3 4]
}
func Example_variadic0() {
@@ -3522,24 +3670,3 @@ func main() {
// Output:
// hello []
}
func Example_variadic() {
src := `
package main
import "fmt"
func f(a ...int) {
fmt.Println(a)
}
func main() {
f(1, 2, 3, 4)
}
`
i := NewInterpreter(Opt{Entry: "main"})
i.Eval(src)
// Output:
// [1 2 3 4]
}

View File

@@ -65,6 +65,7 @@ func (interp *Interpreter) run(n *Node, cf *Frame) {
runCfg(n.start, f)
}
/*
func Run(def *Node, cf *Frame, recv *Node, rseq []int, args []*Node, rets []int, fork bool, goroutine bool) {
//log.Println("run", def.index, def.child[1].ident, "allocate", def.flen)
// Allocate a new Frame to store local variables
@@ -132,6 +133,7 @@ func Run(def *Node, cf *Frame, recv *Node, rseq []int, args []*Node, rets []int,
}
}
}
*/
// Functions set to run during execution of CFG
@@ -456,17 +458,9 @@ func (n *Node) wrapNode(in []reflect.Value) []reflect.Value {
func call(n *Node) {
//var recv *Node
//var rseq []int
//var forkFrame bool
//forkFrame := n.action == CallF // add a frame indirection for closure
goroutine := n.anc.kind == GoStmt
//if n.action == CallF {
// forkFrame = true
//}
//if n.anc.kind == GoStmt {
// goroutine = true
//}
//if n.child[0].kind == SelectorExpr && n.child[0].typ.cat != SrcPkgT && n.child[0].typ.cat != BinPkgT {
// recv = n.child[0].recv
// rseq = n.child[0].child[1].val.([]int)
@@ -487,8 +481,15 @@ func call(n *Node) {
ret[i] = n.findex + i
}
//log.Println(n.index, "call", forkFrame)
n.exec = func(f *Frame) Builtin {
def := value(f).Interface().(*Node)
//anc := f.anc
//if forkFrame {
// anc = f
//}
//nf := Frame{anc: anc, data: make([]reflect.Value, def.flen)}
nf := Frame{anc: f, data: make([]reflect.Value, def.flen)}
// Init local frame values
@@ -507,7 +508,6 @@ func call(n *Node) {
if goroutine {
go runCfg(def.child[3].start, &nf)
} else {
runCfg(def.child[3].start, &nf)
// Propagate return values to caller frame
for i, r := range ret {

View File

@@ -300,21 +300,6 @@ func (t *Type) zero() reflect.Value {
case AliasT:
return t.val.zero()
//case ArrayT:
// //a := make([]interface{}, t.size)
// //z := t.val.zero()
// //for i := 0; i < t.size; i++ {
// // a[i] = z
// //}
// //return a
// if t.size > 0 {
// log.Println("#1 zero array", t.size)
// return reflect.New(t.TypeOf()).Elem()
// //return reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(t.val.zero())), t.size, t.size)
// } else {
// return reflect.Zero(reflect.SliceOf(reflect.TypeOf(t.val.zero())))
// }
case ArrayT, StructT:
return reflect.New(t.TypeOf()).Elem()
@@ -457,7 +442,6 @@ func (t *Type) TypeOf() reflect.Type {
return t.rtype
default:
//return reflect.TypeOf(t.zero())
return t.zero().Type()
}
}