start example/test for components access
This commit is contained in:
@@ -56,12 +56,13 @@ func NewComponentFromVar(v *types.Var, offset int) Component {
|
||||
}
|
||||
|
||||
func (c *component) Resolve() (*Basic, error) {
|
||||
if !isprimitive(c.typ) {
|
||||
b := toprimitive(c.typ)
|
||||
if b == nil {
|
||||
return nil, errors.New("component is not primitive")
|
||||
}
|
||||
return &Basic{
|
||||
Addr: operand.NewParamAddr(c.name, c.offset),
|
||||
Type: c.typ.(*types.Basic),
|
||||
Type: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -181,8 +182,17 @@ func complextofloat(t types.Type) types.Type {
|
||||
panic("bad")
|
||||
}
|
||||
|
||||
// isprimitive returns true if the type cannot be broken into components.
|
||||
func isprimitive(t types.Type) bool {
|
||||
b, ok := t.(*types.Basic)
|
||||
return ok && (b.Info()&(types.IsString|types.IsComplex)) == 0
|
||||
// toprimitive determines whether t is primitive (cannot be reduced into
|
||||
// components). If it is, it returns the basic type for t, otherwise returns
|
||||
// nil.
|
||||
func toprimitive(t types.Type) *types.Basic {
|
||||
switch b := t.(type) {
|
||||
case *types.Basic:
|
||||
if (b.Info() & (types.IsString | types.IsComplex)) == 0 {
|
||||
return b
|
||||
}
|
||||
case *types.Pointer:
|
||||
return types.Typ[types.Uintptr]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
40
gotypes/components_test.go
Normal file
40
gotypes/components_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package gotypes
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBasicKindsArePrimitive(t *testing.T) {
|
||||
kinds := []types.BasicKind{
|
||||
types.Bool,
|
||||
types.Int,
|
||||
types.Int8,
|
||||
types.Int16,
|
||||
types.Int32,
|
||||
types.Int64,
|
||||
types.Uint,
|
||||
types.Uint8,
|
||||
types.Uint16,
|
||||
types.Uint32,
|
||||
types.Uint64,
|
||||
types.Uintptr,
|
||||
types.Float32,
|
||||
types.Float64,
|
||||
}
|
||||
for _, k := range kinds {
|
||||
AssertPrimitive(t, types.Typ[k])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointersArePrimitive(t *testing.T) {
|
||||
typ := types.NewPointer(types.Typ[types.Uint32])
|
||||
AssertPrimitive(t, typ)
|
||||
}
|
||||
|
||||
func AssertPrimitive(t *testing.T, typ types.Type) {
|
||||
c := NewComponent("primitive", typ, 0)
|
||||
if _, err := c.Resolve(); err != nil {
|
||||
t.Errorf("expected type %s to be primitive: got error '%s'", typ, err)
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,15 @@ import (
|
||||
)
|
||||
|
||||
type Signature struct {
|
||||
pkg *types.Package
|
||||
sig *types.Signature
|
||||
params *Tuple
|
||||
results *Tuple
|
||||
}
|
||||
|
||||
func NewSignature(sig *types.Signature) *Signature {
|
||||
func NewSignature(pkg *types.Package, sig *types.Signature) *Signature {
|
||||
s := &Signature{
|
||||
pkg: pkg,
|
||||
sig: sig,
|
||||
}
|
||||
s.init()
|
||||
@@ -24,11 +26,15 @@ func NewSignature(sig *types.Signature) *Signature {
|
||||
}
|
||||
|
||||
func NewSignatureVoid() *Signature {
|
||||
return NewSignature(types.NewSignature(nil, nil, nil, false))
|
||||
return NewSignature(nil, types.NewSignature(nil, nil, nil, false))
|
||||
}
|
||||
|
||||
func ParseSignature(expr string) (*Signature, error) {
|
||||
tv, err := types.Eval(token.NewFileSet(), nil, token.NoPos, expr)
|
||||
return ParseSignatureInPackage(nil, expr)
|
||||
}
|
||||
|
||||
func ParseSignatureInPackage(pkg *types.Package, expr string) (*Signature, error) {
|
||||
tv, err := types.Eval(token.NewFileSet(), pkg, token.NoPos, expr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -39,7 +45,7 @@ func ParseSignature(expr string) (*Signature, error) {
|
||||
if !ok {
|
||||
return nil, errors.New("provided type is not a function signature")
|
||||
}
|
||||
return NewSignature(s), nil
|
||||
return NewSignature(pkg, s), nil
|
||||
}
|
||||
|
||||
func (s *Signature) Params() *Tuple { return s.params }
|
||||
@@ -50,7 +56,7 @@ func (s *Signature) Bytes() int { return s.Params().Bytes() + s.Results().Bytes(
|
||||
|
||||
func (s *Signature) String() string {
|
||||
var buf bytes.Buffer
|
||||
types.WriteSignature(&buf, s.sig, nil)
|
||||
types.WriteSignature(&buf, s.sig, types.RelativeTo(s.pkg))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user