fix: correct array length computed from litteral array (#242)

This commit is contained in:
Marc Vertes
2019-07-11 12:33:05 +02:00
committed by Ludovic Fernandez
parent 3528b4539d
commit 7d5ed8a713
6 changed files with 77 additions and 8 deletions

11
_test/a27.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := [...]string{"hello", "world"}
fmt.Printf("%v %T\n", a, a)
}
// Output:
// [hello world] [2]string

11
_test/a28.go Normal file
View File

@@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
a := [...]string{9: "hello"}
fmt.Printf("%v %T\n", a, a)
}
// Output:
// [ hello] [10]string

21
_test/a29.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import "fmt"
const (
zero = iota
one
two
)
func main() {
a := [...]string{
zero: "zero",
one: "one",
two: "two",
}
fmt.Printf("%v %T\n", a, a)
}
// Output:
// [zero one two] [3]string

View File

@@ -353,6 +353,10 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
} else {
dest.typ = src.typ
}
if dest.typ.sizedef {
dest.typ.size = compositeArrayLen(src)
dest.typ.rtype = nil
}
if sc.global {
// Do not overload existings symbols (defined in GTA) in global scope
sym, _, _ = sc.lookup(dest.ident)
@@ -363,9 +367,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
dest.val = src.val
dest.recv = src.recv
dest.findex = sym.index
if src.kind == basicLit {
sym.rval = src.rval
}
sym.rval = src.rval
} else {
sym, level, _ = sc.lookup(dest.ident)
}
@@ -394,8 +396,7 @@ func (interp *Interpreter) cfg(root *node) ([]*node, error) {
}
}
n.findex = dest.findex
n.val = dest.val
n.rval = dest.rval
// Propagate type
// TODO: Check that existing destination type matches source type
switch {
@@ -1664,3 +1665,18 @@ func compositeGenerator(n *node) (gen bltnGenerator) {
}
return
}
// compositeArrayLen return the litteral array length, computed from definition
func compositeArrayLen(n *node) int {
max := -1
for i, c := range n.child[1:] {
r := i
if c.kind == keyValueExpr {
r = int(c.child[0].rval.Int())
}
if r > max {
max = r
}
}
return max + 1
}

View File

@@ -60,6 +60,7 @@ func (interp *Interpreter) gta(root *node, rpath string) error {
}
sc.sym[dest.ident] = &symbol{kind: varSym, global: true, index: index, typ: typ, rval: val}
if n.anc.kind == constDecl {
sc.sym[dest.ident].kind = constSym
iotaValue++
}
}

View File

@@ -115,6 +115,7 @@ type itype struct {
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
node *node // root AST node of type definition
scope *scope // type declaration scope (in case of re-parse incomplete type)
}
@@ -140,9 +141,14 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
case arrayType:
t.cat = arrayT
if len(n.child) > 1 {
if n.child[0].rval.IsValid() {
switch {
case n.child[0].rval.IsValid():
// constant size
t.size = int(n.child[0].rval.Int())
} else {
case n.child[0].kind == ellipsisExpr:
// [...]T expression
t.sizedef = true
default:
if sym, _, ok := sc.lookup(n.child[0].ident); ok {
// Resolve symbol to get size value
if sym.typ != nil && sym.typ.cat == intT {
@@ -672,7 +678,10 @@ func (t *itype) TypeOf() reflect.Type {
}
if t.incomplete {
t, _ = t.finalize()
var err error
if t, err = t.finalize(); err != nil {
panic(err)
}
}
switch t.cat {