-
Notifications
You must be signed in to change notification settings - Fork 351
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
interp: improve the behaviour of interface{} function parameters
We finally address a long standing limitation of the interpreter: the capacity to generate the correct interface wrapper for an anonymous interface{} function parameter of a binary function. It allows for example fmt.Printf to invoke the String method of an object defined within the interpreter, or json.Marshal to invoke a textMarshaler method if it exists and if there is no Marshaler method already defined for the passed interpreter object. To achieve that, we add a new mapType part of the "Used" symbols to describe what not empty interfaces are expected and in which priority order. This information can not be guessed and is found in the related package documentation, then captured in stdlib/maptypes.go. Then, at compile time and/or during execution, a lookup on mapTypes is performed to allow the correct wrapper to be generated. This change adds a new MapType type to the stdlib package. Fixes #435.
- Loading branch information
Showing
6 changed files
with
170 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
) | ||
|
||
type Foo int | ||
|
||
func (f Foo) String() string { | ||
return "foo-" + strconv.Itoa(int(f)) | ||
} | ||
|
||
func print1(arg interface{}) { | ||
fmt.Println(arg) | ||
} | ||
|
||
func main() { | ||
var arg Foo = 3 | ||
var f = print1 | ||
f(arg) | ||
} | ||
|
||
// Output: | ||
// foo-3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package stdlib | ||
|
||
import ( | ||
"encoding" | ||
"encoding/json" | ||
"encoding/xml" | ||
"fmt" | ||
"log" | ||
"reflect" | ||
) | ||
|
||
func init() { | ||
mt := []reflect.Type{ | ||
reflect.TypeOf((*fmt.Formatter)(nil)).Elem(), | ||
reflect.TypeOf((*fmt.Stringer)(nil)).Elem(), | ||
} | ||
|
||
MapTypes[reflect.ValueOf(fmt.Errorf)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Fprint)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Fprintf)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Fprintln)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Print)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Printf)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Println)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Sprint)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Sprintf)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Sprintln)] = mt | ||
|
||
MapTypes[reflect.ValueOf(log.Fatal)] = mt | ||
MapTypes[reflect.ValueOf(log.Fatalf)] = mt | ||
MapTypes[reflect.ValueOf(log.Fatalln)] = mt | ||
MapTypes[reflect.ValueOf(log.Panic)] = mt | ||
MapTypes[reflect.ValueOf(log.Panicf)] = mt | ||
MapTypes[reflect.ValueOf(log.Panicln)] = mt | ||
|
||
mt = []reflect.Type{reflect.TypeOf((*fmt.Scanner)(nil)).Elem()} | ||
|
||
MapTypes[reflect.ValueOf(fmt.Scan)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Scanf)] = mt | ||
MapTypes[reflect.ValueOf(fmt.Scanln)] = mt | ||
|
||
MapTypes[reflect.ValueOf(json.Marshal)] = []reflect.Type{ | ||
reflect.TypeOf((*json.Marshaler)(nil)).Elem(), | ||
reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(), | ||
} | ||
MapTypes[reflect.ValueOf(json.Unmarshal)] = []reflect.Type{ | ||
reflect.TypeOf((*json.Unmarshaler)(nil)).Elem(), | ||
reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem(), | ||
} | ||
MapTypes[reflect.ValueOf(xml.Marshal)] = []reflect.Type{ | ||
reflect.TypeOf((*xml.Marshaler)(nil)).Elem(), | ||
reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem(), | ||
} | ||
MapTypes[reflect.ValueOf(xml.Unmarshal)] = []reflect.Type{ | ||
reflect.TypeOf((*xml.Unmarshaler)(nil)).Elem(), | ||
reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem(), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters