10
_test/a29.go
10
_test/a29.go
@@ -6,16 +6,18 @@ const (
|
||||
zero = iota
|
||||
one
|
||||
two
|
||||
three
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := [...]string{
|
||||
zero: "zero",
|
||||
one: "one",
|
||||
two: "two",
|
||||
zero: "zero",
|
||||
one: "one",
|
||||
three: "three",
|
||||
three + 2: "five",
|
||||
}
|
||||
fmt.Printf("%v %T\n", a, a)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [zero one two] [3]string
|
||||
// [zero one three five] [6]string
|
||||
|
||||
@@ -286,11 +286,11 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
|
||||
|
||||
case compositeLitExpr:
|
||||
if len(n.child) > 0 && n.child[0].isType(sc) {
|
||||
// Get type from 1st child
|
||||
// Get type from 1st child.
|
||||
if n.typ, err = nodeType(interp, sc, n.child[0]); err != nil {
|
||||
return false
|
||||
}
|
||||
// Indicate that the first child is the type
|
||||
// Indicate that the first child is the type.
|
||||
n.nleft = 1
|
||||
} else {
|
||||
// Get type from ancestor (implicit type)
|
||||
@@ -2626,23 +2626,54 @@ func compositeGenerator(n *node, typ *itype, rtyp reflect.Type) (gen bltnGenerat
|
||||
// arrayTypeLen returns the node's array length. If the expression is an
|
||||
// array variable it is determined from the value's type, otherwise it is
|
||||
// computed from the source definition.
|
||||
func arrayTypeLen(n *node) int {
|
||||
func arrayTypeLen(n *node, sc *scope) (int, error) {
|
||||
if n.typ != nil && n.typ.cat == arrayT {
|
||||
return n.typ.length
|
||||
return n.typ.length, nil
|
||||
}
|
||||
max := -1
|
||||
for i, c := range n.child[1:] {
|
||||
r := i
|
||||
if c.kind == keyValueExpr {
|
||||
if v := c.child[0].rval; v.IsValid() {
|
||||
r = int(c.child[0].rval.Int())
|
||||
for _, c := range n.child[1:] {
|
||||
var r int
|
||||
|
||||
if c.kind != keyValueExpr {
|
||||
r = max + 1
|
||||
max = r
|
||||
continue
|
||||
}
|
||||
|
||||
c0 := c.child[0]
|
||||
v := c0.rval
|
||||
if v.IsValid() {
|
||||
r = int(v.Int())
|
||||
} else {
|
||||
// Resolve array key value as a constant.
|
||||
if c0.kind == identExpr {
|
||||
// Key is defined by a symbol which must be a constant integer.
|
||||
sym, _, ok := sc.lookup(c0.ident)
|
||||
if !ok {
|
||||
return 0, c0.cfgErrorf("undefined: %s", c0.ident)
|
||||
}
|
||||
if sym.kind != constSym {
|
||||
return 0, c0.cfgErrorf("non-constant array bound %q", c0.ident)
|
||||
}
|
||||
r = int(vInt(sym.rval))
|
||||
} else {
|
||||
// Key is defined by a numeric constant expression.
|
||||
if _, err := c0.interp.cfg(c0, sc, sc.pkgID, sc.pkgName); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cv, ok := c0.rval.Interface().(constant.Value)
|
||||
if !ok {
|
||||
return 0, c0.cfgErrorf("non-constant expression")
|
||||
}
|
||||
r = constToInt(cv)
|
||||
}
|
||||
}
|
||||
|
||||
if r > max {
|
||||
max = r
|
||||
}
|
||||
}
|
||||
return max + 1
|
||||
return max + 1, nil
|
||||
}
|
||||
|
||||
// isValueUntyped returns true if value is untyped.
|
||||
|
||||
@@ -445,6 +445,7 @@ func TestEvalCompositeArray(t *testing.T) {
|
||||
{src: `a := [1]int{1, 2}`, err: "1:43: index 1 is out of bounds (>= 1)"},
|
||||
{src: `b := [l]int{1, 2}`, res: "[1 2 0 0 0 0 0 0 0 0]"},
|
||||
{src: `i := 10; a := [i]int{1, 2}`, err: "1:43: non-constant array bound \"i\""},
|
||||
{src: `c := [...]float64{1, 3: 3.4, 5}`, res: "[1 0 0 3.4 5]"},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +438,10 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype,
|
||||
}
|
||||
case c0.kind == ellipsisExpr:
|
||||
// [...]T expression, get size from the length of composite array.
|
||||
length = arrayTypeLen(n.anc)
|
||||
length, err = arrayTypeLen(n.anc, sc)
|
||||
if err != nil {
|
||||
incomplete = true
|
||||
}
|
||||
case c0.kind == identExpr:
|
||||
sym, _, ok := sc.lookup(c0.ident)
|
||||
if !ok {
|
||||
|
||||
Reference in New Issue
Block a user