fix: implement variadic using a type category to avoid corruption
This commit is contained in:
committed by
Traefiker Bot
parent
2f0279f0f5
commit
82dd3f2953
10
_test/variadic4.go
Normal file
10
_test/variadic4.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
func variadic(s ...string) {}
|
||||
|
||||
func f(s string) { println(s + "bar") }
|
||||
|
||||
func main() { f("foo") }
|
||||
|
||||
// Output:
|
||||
// foobar
|
||||
@@ -89,7 +89,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
case stringT:
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = sc.getType("byte")
|
||||
case arrayT:
|
||||
case arrayT, variadicT:
|
||||
ktyp = sc.getType("int")
|
||||
vtyp = o.typ.val
|
||||
}
|
||||
@@ -260,9 +260,6 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
|
||||
if typ, err = nodeType(interp, sc, c.lastChild()); err != nil {
|
||||
return false
|
||||
}
|
||||
if typ.variadic {
|
||||
typ = &itype{cat: arrayT, val: typ}
|
||||
}
|
||||
for _, cc := range c.child[:len(c.child)-1] {
|
||||
sc.sym[cc.ident] = &symbol{index: sc.add(typ), kind: varSym, typ: typ}
|
||||
}
|
||||
@@ -1584,7 +1581,7 @@ func variadicPos(n *node) int {
|
||||
return -1
|
||||
}
|
||||
last := len(n.child[0].typ.arg) - 1
|
||||
if n.child[0].typ.arg[last].variadic {
|
||||
if n.child[0].typ.arg[last].cat == variadicT {
|
||||
return last
|
||||
}
|
||||
return -1
|
||||
|
||||
@@ -614,7 +614,7 @@ func call(n *node) {
|
||||
if c.kind == basicLit {
|
||||
var argType reflect.Type
|
||||
if variadic >= 0 && i >= variadic {
|
||||
argType = n.child[0].typ.arg[variadic].TypeOf()
|
||||
argType = n.child[0].typ.arg[variadic].val.TypeOf()
|
||||
} else {
|
||||
argType = n.child[0].typ.arg[i].TypeOf()
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ const (
|
||||
uint64T
|
||||
uintptrT
|
||||
valueT
|
||||
variadicT
|
||||
maxT
|
||||
)
|
||||
|
||||
@@ -82,6 +83,7 @@ var cats = [...]string{
|
||||
uint64T: "uint64T",
|
||||
uintptrT: "uintptrT",
|
||||
valueT: "valueT",
|
||||
variadicT: "variadicT",
|
||||
}
|
||||
|
||||
func (c tcat) String() string {
|
||||
@@ -102,17 +104,16 @@ type structField struct {
|
||||
// itype defines the internal representation of types in the interpreter
|
||||
type itype struct {
|
||||
cat tcat // Type category
|
||||
field []structField // Array of struct fields if StrucT or InterfaceT
|
||||
field []structField // Array of struct fields if structT or interfaceT
|
||||
key *itype // Type of key element if MapT or nil
|
||||
val *itype // Type of value element if ChanT, MapT, PtrT, AliasT or ArrayT
|
||||
arg []*itype // Argument types if FuncT or nil
|
||||
ret []*itype // Return types if FuncT or nil
|
||||
val *itype // Type of value element if chanT, mapT, ptrT, aliasT, arrayT or variadicT
|
||||
arg []*itype // Argument types if funcT or nil
|
||||
ret []*itype // Return types if funcT or nil
|
||||
method []*node // Associated methods or nil
|
||||
name string // name of type within its package for a defined type
|
||||
pkgPath string // for a defined type, the package import path
|
||||
size int // Size of array if ArrayT
|
||||
rtype reflect.Type // Reflection type if ValueT, or nil
|
||||
variadic bool // true if type is variadic
|
||||
incomplete bool // true if type must be parsed again (out of order declarations)
|
||||
untyped bool // true for a literal value (string or number)
|
||||
sizedef bool // true if array size is computed from type definition
|
||||
@@ -280,10 +281,11 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
|
||||
t.incomplete = t.val.incomplete
|
||||
|
||||
case ellipsisExpr:
|
||||
if t, err = nodeType(interp, sc, n.child[0]); err != nil {
|
||||
t.cat = variadicT
|
||||
if t.val, err = nodeType(interp, sc, n.child[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.variadic = true
|
||||
t.incomplete = t.val.incomplete
|
||||
|
||||
case funcLit:
|
||||
t, err = nodeType(interp, sc, n.child[2])
|
||||
@@ -720,7 +722,7 @@ func (t *itype) Type(name string) reflect.Type {
|
||||
}
|
||||
|
||||
switch t.cat {
|
||||
case arrayT:
|
||||
case arrayT, variadicT:
|
||||
if t.size > 0 {
|
||||
t.rtype = reflect.ArrayOf(t.size, t.val.Type(name))
|
||||
} else {
|
||||
@@ -774,7 +776,7 @@ func (t *itype) frameType() (r reflect.Type) {
|
||||
panic(err)
|
||||
}
|
||||
switch t.cat {
|
||||
case arrayT:
|
||||
case arrayT, variadicT:
|
||||
if t.size > 0 {
|
||||
r = reflect.ArrayOf(t.size, t.val.frameType())
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user