diff --git a/_test/time10.go b/_test/time10.go new file mode 100644 index 000000000..21b70a0dc --- /dev/null +++ b/_test/time10.go @@ -0,0 +1,13 @@ +package main + +import "time" + +var UnixTime func(int64, int64) time.Time + +func main() { + UnixTime = time.Unix + println(UnixTime(1e9, 0).In(time.UTC).Minute()) +} + +// Output: +// 46 diff --git a/cmd/goexports/goexports.go b/cmd/goexports/goexports.go index 09d45051f..bb2f65946 100644 --- a/cmd/goexports/goexports.go +++ b/cmd/goexports/goexports.go @@ -1,7 +1,7 @@ //go:generate go build /* -Goexports generates wrappers of package exported symbols +Goexports generates wrappers of package exported symbols. Output files are written in the current directory, and prefixed with the go version. diff --git a/interp/doc.go b/interp/doc.go index 421c35930..94d9cfe39 100644 --- a/interp/doc.go +++ b/interp/doc.go @@ -1,5 +1,5 @@ /* -Package interp provides a complete Go interpreter +Package interp provides a complete Go interpreter. For the Go language itself, refer to the official Go specification https://golang.org/ref/spec. @@ -32,4 +32,4 @@ And include files containing */ package interp -// BUG(marc): Type checking is not implemented yet +// BUG(marc): Type checking is not implemented yet. diff --git a/interp/run.go b/interp/run.go index f25fc5ece..ef8a285f3 100644 --- a/interp/run.go +++ b/interp/run.go @@ -227,6 +227,8 @@ func assign(n *node) { svalue[i] = genInterfaceWrapper(src, dest.typ.rtype) case dest.typ.cat == valueT && src.typ.cat == funcT: svalue[i] = genFunctionWrapper(src) + case dest.typ.cat == funcT && src.typ.cat == valueT: + svalue[i] = genValueNode(src) case src.kind == basicLit && src.val == nil: t := dest.typ.TypeOf() svalue[i] = func(*frame) reflect.Value { return reflect.New(t).Elem() } @@ -649,6 +651,29 @@ func call(n *node) { n.exec = func(f *frame) bltn { def := value(f).Interface().(*node) + + // Call bin func if defined + if def.rval.IsValid() { + in := make([]reflect.Value, len(values)) + for i, v := range values { + in[i] = v(f) + } + if goroutine { + go def.rval.Call(in) + return tnext + } + out := def.rval.Call(in) + for i, v := range rvalues { + if v != nil { + v(f).Set(out[i]) + } + } + if fnext != nil && !out[0].Bool() { + return fnext + } + return tnext + } + anc := f // Get closure frame context (if any) if def.frame != nil { diff --git a/interp/value.go b/interp/value.go index 417fdd4e9..d6d7c864e 100644 --- a/interp/value.go +++ b/interp/value.go @@ -161,6 +161,14 @@ func genValueInterfaceValue(n *node) func(*frame) reflect.Value { } } +func genValueNode(n *node) func(*frame) reflect.Value { + value := genValue(n) + + return func(f *frame) reflect.Value { + return reflect.ValueOf(&node{rval: value(f)}) + } +} + func vInt(v reflect.Value) (i int64) { switch v.Type().Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: