Skip to content

Commit

Permalink
interp: improve internal handling of functions
Browse files Browse the repository at this point in the history
Up to now functions could be stored as node values in frame
(as for interpreter defined functions) or function values,
directly callable by the Go runtime. We now always store functions
in the later form, making the processing of functions, anonymous
closures and methods simpler and more robust. All functions, once
compiled are always directly callable, with no further wrapping
necessary.

Fixes traefik#1459.
  • Loading branch information
mvertes committed Oct 11, 2022
1 parent 143e4a4 commit 041ceb7
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 188 deletions.
41 changes: 41 additions & 0 deletions _test/cli8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"net/http"
"net/http/httptest"
)

type T struct {
name string
next http.Handler
}

func (t *T) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
println("in T.ServeHTTP")
if t.next != nil {
t.next.ServeHTTP(rw, req)
}
}

func New(name string, next http.Handler) (http.Handler, error) { return &T{name, next}, nil }

func main() {
next := func(rw http.ResponseWriter, req *http.Request) {
println("in next")
}

t, err := New("test", http.HandlerFunc(next))
if err != nil {
panic(err)
}

recorder := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/", nil)
t.ServeHTTP(recorder, req)
println(recorder.Result().Status)
}

// Output:
// in T.ServeHTTP
// in next
// 200 OK
18 changes: 18 additions & 0 deletions _test/convert3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"fmt"
"net/http"
)

func main() {
next := func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Cache-Control", "max-age=20")
rw.WriteHeader(http.StatusOK)
}
f := http.HandlerFunc(next)
fmt.Printf("%T\n", f.ServeHTTP)
}

// Output:
// func(http.ResponseWriter, *http.Request)
22 changes: 22 additions & 0 deletions _test/issue-1459.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import "fmt"

type funclistItem func()

type funclist struct {
list []funclistItem
}

func main() {
funcs := funclist{}

funcs.list = append(funcs.list, func() { fmt.Println("first") })

for _, f := range funcs.list {
f()
}
}

// Output:
// first
2 changes: 1 addition & 1 deletion _test/struct49.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func main() {
}
s.ts["test"] = append(s.ts["test"], &T{s: s})

t , ok:= s.getT("test")
t, ok := s.getT("test")
println(t != nil, ok)
}

Expand Down
1 change: 1 addition & 0 deletions generate.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package yaegi provides a Go interpreter.
package yaegi

//go:generate go generate github.com/traefik/yaegi/internal/cmd/extract
Expand Down
1 change: 1 addition & 0 deletions internal/unsafe2/unsafe.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package unsafe2 provides helpers to generate recursive struct types.
package unsafe2

import (
Expand Down
7 changes: 1 addition & 6 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -1700,12 +1700,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
}
if c.typ.cat == nilT {
// nil: Set node value to zero of return type
if typ.cat == funcT {
// Wrap the typed nil value in a node, as per other interpreter functions
c.rval = reflect.ValueOf(&node{kind: basicLit, rval: reflect.New(typ.TypeOf()).Elem()})
} else {
c.rval = reflect.New(typ.TypeOf()).Elem()
}
c.rval = reflect.New(typ.TypeOf()).Elem()
}
}

Expand Down
Loading

0 comments on commit 041ceb7

Please sign in to comment.