feature: add Sizeof and Alignof to unsafe
This commit is contained in:
22
_test/unsafe5.go
Normal file
22
_test/unsafe5.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type S struct {
|
||||
X int
|
||||
Y int
|
||||
Z int
|
||||
}
|
||||
|
||||
func main() {
|
||||
size := unsafe.Sizeof(S{})
|
||||
align := unsafe.Alignof(S{})
|
||||
|
||||
fmt.Println(size, align)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// 24 8
|
||||
30
interp/hooks.go
Normal file
30
interp/hooks.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package interp
|
||||
|
||||
import "reflect"
|
||||
|
||||
const hooksPath = "github.com/containous/yaegi"
|
||||
|
||||
// convertFn is the signature of a symbol converter.
|
||||
type convertFn func(from, to reflect.Type) func(src, dest reflect.Value)
|
||||
|
||||
// hooks are external symbol bindings.
|
||||
type hooks struct {
|
||||
convert []convertFn
|
||||
}
|
||||
|
||||
func (h *hooks) Parse(m map[string]reflect.Value) {
|
||||
if con, ok := getConvertFn(m["convert"]); ok {
|
||||
h.convert = append(h.convert, con)
|
||||
}
|
||||
}
|
||||
|
||||
func getConvertFn(v reflect.Value) (convertFn, bool) {
|
||||
if !v.IsValid() {
|
||||
return nil, false
|
||||
}
|
||||
fn, ok := v.Interface().(func(from, to reflect.Type) func(src, dest reflect.Value))
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return fn, true
|
||||
}
|
||||
@@ -96,9 +96,6 @@ func (f *frame) clone() *frame {
|
||||
}
|
||||
}
|
||||
|
||||
// convertFn is the signature of a symbol converter.
|
||||
type convertFn func(from, to reflect.Type) func(src, dest reflect.Value)
|
||||
|
||||
// Exports stores the map of binary packages per package path.
|
||||
type Exports map[string]map[string]reflect.Value
|
||||
|
||||
@@ -142,7 +139,7 @@ type Interpreter struct {
|
||||
pkgNames map[string]string // package names, indexed by path
|
||||
done chan struct{} // for cancellation of channel operations
|
||||
|
||||
convert []convertFn // converters from symbols
|
||||
hooks *hooks // symbol hooks
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -221,6 +218,7 @@ func New(options Options) *Interpreter {
|
||||
srcPkg: imports{},
|
||||
pkgNames: map[string]string{},
|
||||
rdir: map[string]bool{},
|
||||
hooks: &hooks{},
|
||||
}
|
||||
|
||||
i.opt.context.GOPATH = options.GoPath
|
||||
@@ -471,28 +469,15 @@ func (interp *Interpreter) getWrapper(t reflect.Type) reflect.Type {
|
||||
// they can be used in interpreted code.
|
||||
func (interp *Interpreter) Use(values Exports) {
|
||||
for k, v := range values {
|
||||
if k != "github.com/containous/yaegi" {
|
||||
interp.binPkg[k] = v
|
||||
if k == hooksPath {
|
||||
interp.hooks.Parse(v)
|
||||
continue
|
||||
}
|
||||
|
||||
if con, ok := extractConverter(v["convert"]); ok {
|
||||
interp.convert = append(interp.convert, con)
|
||||
}
|
||||
interp.binPkg[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func extractConverter(v reflect.Value) (convertFn, bool) {
|
||||
if !v.IsValid() {
|
||||
return nil, false
|
||||
}
|
||||
fn, ok := v.Interface().(func(from, to reflect.Type) func(src, dest reflect.Value))
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return fn, true
|
||||
}
|
||||
|
||||
// REPL performs a Read-Eval-Print-Loop on input reader.
|
||||
// Results are printed on output writer.
|
||||
func (interp *Interpreter) REPL(in io.Reader, out io.Writer) {
|
||||
|
||||
@@ -329,7 +329,7 @@ func convert(n *node) {
|
||||
value = genValue(c)
|
||||
}
|
||||
|
||||
for _, con := range n.interp.convert {
|
||||
for _, con := range n.interp.hooks.convert {
|
||||
if c.typ.rtype == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ func init() {
|
||||
Symbols["github.com/containous/yaegi"] = map[string]reflect.Value{
|
||||
"convert": reflect.ValueOf(convert),
|
||||
}
|
||||
|
||||
// Add builtin functions to unsafe.
|
||||
Symbols["unsafe"]["Sizeof"] = reflect.ValueOf(sizeof)
|
||||
Symbols["unsafe"]["Alignof"] = reflect.ValueOf(alignof)
|
||||
}
|
||||
|
||||
func convert(from, to reflect.Type) func(src, dest reflect.Value) {
|
||||
@@ -46,4 +50,12 @@ func convert(from, to reflect.Type) func(src, dest reflect.Value) {
|
||||
}
|
||||
}
|
||||
|
||||
func sizeof(i interface{}) uintptr {
|
||||
return reflect.ValueOf(i).Type().Size()
|
||||
}
|
||||
|
||||
func alignof(i interface{}) uintptr {
|
||||
return uintptr(reflect.ValueOf(i).Type().Align())
|
||||
}
|
||||
|
||||
//go:generate ../../cmd/goexports/goexports unsafe
|
||||
|
||||
Reference in New Issue
Block a user