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.
|
// Exports stores the map of binary packages per package path.
|
||||||
type Exports map[string]map[string]reflect.Value
|
type Exports map[string]map[string]reflect.Value
|
||||||
|
|
||||||
@@ -142,7 +139,7 @@ type Interpreter struct {
|
|||||||
pkgNames map[string]string // package names, indexed by path
|
pkgNames map[string]string // package names, indexed by path
|
||||||
done chan struct{} // for cancellation of channel operations
|
done chan struct{} // for cancellation of channel operations
|
||||||
|
|
||||||
convert []convertFn // converters from symbols
|
hooks *hooks // symbol hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -221,6 +218,7 @@ func New(options Options) *Interpreter {
|
|||||||
srcPkg: imports{},
|
srcPkg: imports{},
|
||||||
pkgNames: map[string]string{},
|
pkgNames: map[string]string{},
|
||||||
rdir: map[string]bool{},
|
rdir: map[string]bool{},
|
||||||
|
hooks: &hooks{},
|
||||||
}
|
}
|
||||||
|
|
||||||
i.opt.context.GOPATH = options.GoPath
|
i.opt.context.GOPATH = options.GoPath
|
||||||
@@ -471,27 +469,14 @@ func (interp *Interpreter) getWrapper(t reflect.Type) reflect.Type {
|
|||||||
// they can be used in interpreted code.
|
// they can be used in interpreted code.
|
||||||
func (interp *Interpreter) Use(values Exports) {
|
func (interp *Interpreter) Use(values Exports) {
|
||||||
for k, v := range values {
|
for k, v := range values {
|
||||||
if k != "github.com/containous/yaegi" {
|
if k == hooksPath {
|
||||||
interp.binPkg[k] = v
|
interp.hooks.Parse(v)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if con, ok := extractConverter(v["convert"]); ok {
|
interp.binPkg[k] = v
|
||||||
interp.convert = append(interp.convert, con)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// REPL performs a Read-Eval-Print-Loop on input reader.
|
||||||
// Results are printed on output writer.
|
// Results are printed on output writer.
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ func convert(n *node) {
|
|||||||
value = genValue(c)
|
value = genValue(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, con := range n.interp.convert {
|
for _, con := range n.interp.hooks.convert {
|
||||||
if c.typ.rtype == nil {
|
if c.typ.rtype == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ func init() {
|
|||||||
Symbols["github.com/containous/yaegi"] = map[string]reflect.Value{
|
Symbols["github.com/containous/yaegi"] = map[string]reflect.Value{
|
||||||
"convert": reflect.ValueOf(convert),
|
"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) {
|
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
|
//go:generate ../../cmd/goexports/goexports unsafe
|
||||||
|
|||||||
Reference in New Issue
Block a user