aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-05-10 17:15:29 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-05-14 19:28:01 +0200
commit1886b2a4811a4d9adbfc509505a095848cc655eb (patch)
tree8ab666c6f9ea59912d911abd5639480eae534eda /pkg
parent354b388e08761dabb99236aa73a24e9b861b6e5f (diff)
pkg/ast: refactor COLON handling
This prepared for handling of bytesize[parent:foo:bar] expressions by allowing multiple identifiers after colon. No functional changes for now, just preparation for storing more than one identifier after colon.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/ast/ast.go11
-rw-r--r--pkg/ast/clone.go6
-rw-r--r--pkg/ast/format.go9
-rw-r--r--pkg/ast/parser.go10
-rw-r--r--pkg/ast/testdata/all.txt1
-rw-r--r--pkg/compiler/check.go31
-rw-r--r--pkg/compiler/compiler.go2
-rw-r--r--pkg/compiler/consts.go14
-rw-r--r--pkg/compiler/types.go88
9 files changed, 93 insertions, 79 deletions
diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go
index 1e1e97221..b692f8633 100644
--- a/pkg/ast/ast.go
+++ b/pkg/ast/ast.go
@@ -199,13 +199,10 @@ type Type struct {
Ident string
String string
HasString bool
- // Part after COLON (for ranges and bitfields).
- HasColon bool
- Pos2 Pos
- Value2 uint64
- Value2Fmt IntFmt
- Ident2 string
- Args []*Type
+ // Parts after COLON (for ranges and bitfields).
+ Colon []*Type
+ // Sub-types in [].
+ Args []*Type
}
func (n *Type) Info() (Pos, string, string) {
diff --git a/pkg/ast/clone.go b/pkg/ast/clone.go
index 13a603ba8..a594e41f6 100644
--- a/pkg/ast/clone.go
+++ b/pkg/ast/clone.go
@@ -155,11 +155,7 @@ func (n *Type) Clone() Node {
Ident: n.Ident,
String: n.String,
HasString: n.HasString,
- HasColon: n.HasColon,
- Pos2: n.Pos2,
- Value2: n.Value2,
- Value2Fmt: n.Value2Fmt,
- Ident2: n.Ident2,
+ Colon: cloneTypes(n.Colon),
Args: cloneTypes(n.Args),
}
}
diff --git a/pkg/ast/format.go b/pkg/ast/format.go
index 13cd26e2c..c3d931706 100644
--- a/pkg/ast/format.go
+++ b/pkg/ast/format.go
@@ -176,13 +176,8 @@ func fmtType(t *Type) string {
default:
v = FormatInt(t.Value, t.ValueFmt)
}
- if t.HasColon {
- switch {
- case t.Ident2 != "":
- v += fmt.Sprintf(":%v", t.Ident2)
- default:
- v += fmt.Sprintf(":%v", FormatInt(t.Value2, t.Value2Fmt))
- }
+ for _, c := range t.Colon {
+ v += ":" + fmtType(c)
}
v += fmtTypeList(t.Args)
return v
diff --git a/pkg/ast/parser.go b/pkg/ast/parser.go
index bd9d33657..b68a1a8a2 100644
--- a/pkg/ast/parser.go
+++ b/pkg/ast/parser.go
@@ -425,16 +425,18 @@ func (p *parser) parseType() *Type {
}
p.next()
if allowColon && p.tryConsume(tokColon) {
- arg.HasColon = true
- arg.Pos2 = p.pos
+ col := &Type{
+ Pos: p.pos,
+ }
switch p.tok {
case tokInt:
- arg.Value2, arg.Value2Fmt = p.parseIntValue()
+ col.Value, col.ValueFmt = p.parseIntValue()
case tokIdent:
- arg.Ident2 = p.lit
+ col.Ident = p.lit
default:
p.expect(tokInt, tokIdent)
}
+ arg.Colon = append(arg.Colon, col)
p.next()
}
arg.Args = p.parseTypeList()
diff --git a/pkg/ast/testdata/all.txt b/pkg/ast/testdata/all.txt
index 6e4e72d2c..e5a1839dd 100644
--- a/pkg/ast/testdata/all.txt
+++ b/pkg/ast/testdata/all.txt
@@ -27,6 +27,7 @@ define FOO `bar`
define FOO `bar ### C expression is not terminated
foo(x int32[1:2:3, opt]) ### unexpected ':', expecting ']'
+foo2(x int32[1[2]:2]) ### unexpected ':', expecting ']'
s0 {
f0 string[""]
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index e79a161b4..c5337a63b 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -669,8 +669,8 @@ func (comp *compiler) checkStruct(ctx checkCtx, n *ast.Struct) {
comp.error(attr.Pos, "unexpected %v, expect attribute", unexpected)
return
}
- if attr.HasColon {
- comp.error(attr.Pos2, "unexpected ':'")
+ if len(attr.Colon) != 0 {
+ comp.error(attr.Colon[0].Pos, "unexpected ':'")
return
}
}
@@ -745,13 +745,13 @@ func (comp *compiler) checkType(ctx checkCtx, t *ast.Type, flags checkFlags) {
}
func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFlags) {
- if t.HasColon {
- if !desc.AllowColon {
- comp.error(t.Pos2, "unexpected ':'")
+ for i, col := range t.Colon {
+ if i >= desc.MaxColon {
+ comp.error(col.Pos, "unexpected ':'")
return
}
if flags&checkIsStruct == 0 {
- comp.error(t.Pos2, "unexpected ':', only struct fields can be bitfields")
+ comp.error(col.Pos, "unexpected ':', only struct fields can be bitfields")
return
}
}
@@ -814,7 +814,7 @@ func (comp *compiler) checkTypeArgs(t *ast.Type, desc *typeDesc, flags checkFlag
func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlags) {
typedefName := t.Ident
comp.usedTypedefs[typedefName] = true
- if t.HasColon {
+ if len(t.Colon) != 0 {
comp.error(t.Pos, "type alias %v with ':'", t.Ident)
return
}
@@ -912,9 +912,12 @@ func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*a
// Need more checks here. E.g. that CONST_ARG does not have subargs.
// And if CONST_ARG is a value, then use concreteArg.Value.
// Also need to error if CONST_ARG is a string.
- if concreteArg := argMap[templArg.Ident2]; concreteArg != nil {
- templArg.Ident2 = concreteArg.Ident
- templArg.Pos2 = concreteArg.Pos
+ if len(templArg.Colon) != 0 {
+ col := templArg.Colon[0]
+ if concreteArg := argMap[col.Ident]; concreteArg != nil {
+ col.Ident = concreteArg.Ident
+ col.Pos = concreteArg.Pos
+ }
}
}))
return err0 == comp.errors
@@ -940,9 +943,11 @@ func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {
return
}
}
- if !desc.AllowColon && arg.HasColon {
- comp.error(arg.Pos2, "unexpected ':'")
- return
+ for i, col := range arg.Colon {
+ if i >= desc.MaxColon {
+ comp.error(col.Pos, "unexpected ':'")
+ return
+ }
}
if len(arg.Args) > desc.MaxArgs {
comp.error(arg.Pos, "%v argument has subargs", argDesc.Name)
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go
index 5abc8e2a8..508dc0f26 100644
--- a/pkg/compiler/compiler.go
+++ b/pkg/compiler/compiler.go
@@ -242,7 +242,7 @@ func (comp *compiler) parseSizeAttr(attr *ast.Type) uint64 {
comp.error(sz.Pos, "unexpected %v, expect int", unexpected)
return sizeUnassigned
}
- if sz.HasColon || len(sz.Args) != 0 {
+ if len(sz.Colon) != 0 || len(sz.Args) != 0 {
comp.error(sz.Pos, "size attribute has colon or args")
return sizeUnassigned
}
diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go
index d3556c047..1816bc1f6 100644
--- a/pkg/compiler/consts.go
+++ b/pkg/compiler/consts.go
@@ -73,9 +73,11 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo {
info := getConstInfo(infos, arg.Pos)
info.consts[arg.Ident] = true
}
- if arg.Ident2 != "" {
- info := getConstInfo(infos, arg.Pos2)
- info.consts[arg.Ident2] = true
+ for _, col := range arg.Colon {
+ if col.Ident != "" {
+ info := getConstInfo(infos, col.Pos)
+ info.consts[col.Ident] = true
+ }
}
}
}
@@ -183,9 +185,9 @@ func (comp *compiler) patchConsts(consts map[string]uint64) {
for i, arg := range args {
if desc.Args[i].Type.Kind == kindInt {
comp.patchIntConst(&arg.Value, &arg.Ident, consts, &missing)
- if arg.HasColon {
- comp.patchIntConst(&arg.Value2,
- &arg.Ident2, consts, &missing)
+ for _, col := range arg.Colon {
+ comp.patchIntConst(&col.Value,
+ &col.Ident, consts, &missing)
}
}
}
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index 1a230458d..17fb1b93a 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -17,7 +17,7 @@ type typeDesc struct {
CanBeTypedef bool // can be type alias target?
CantBeOpt bool // can't be marked as opt?
NeedBase bool // needs base type when used as field?
- AllowColon bool // allow colon (int8:2) on fields?
+ MaxColon int // max number of colons (int8:2) on fields
OptArgs int // number of optional arguments in Args array
Args []namedArg // type arguments
// CanBeArgRet returns if this type can be syscall argument/return (false if nil).
@@ -38,10 +38,10 @@ type typeDesc struct {
// typeArg describes a type argument.
type typeArg struct {
- Names []string
- Kind int // int/ident/string
- MaxArgs int // maxiumum number of subargs
- AllowColon bool // allow colon (2:3)?
+ Names []string
+ Kind int // int/ident/string
+ MaxArgs int // maxiumum number of subargs
+ MaxColon int // max number of colons (2:3)
// Check does custom verification of the arg (optional).
Check func(comp *compiler, t *ast.Type)
CheckConsts func(comp *compiler, t *ast.Type)
@@ -67,7 +67,7 @@ var typeInt = &typeDesc{
Names: typeArgBase.Type.Names,
CanBeArgRet: canBeArg,
CanBeTypedef: true,
- AllowColon: true,
+ MaxColon: 1,
OptArgs: 1,
Args: []namedArg{{Name: "range", Type: typeArgIntRange}},
CanBeResourceBase: func(comp *compiler, t *ast.Type) bool {
@@ -85,11 +85,19 @@ var typeInt = &typeDesc{
size, be := comp.parseIntType(t.Ident)
kind, rangeBegin, rangeEnd := prog.IntPlain, uint64(0), uint64(0)
if len(args) > 0 {
- kind, rangeBegin, rangeEnd = prog.IntRange, args[0].Value, args[0].Value2
+ rangeArg := args[0]
+ kind, rangeBegin, rangeEnd = prog.IntRange, rangeArg.Value, rangeArg.Value
+ if len(rangeArg.Colon) != 0 {
+ rangeEnd = rangeArg.Colon[0].Value
+ }
+ }
+ var bitLen uint64
+ if len(t.Colon) != 0 {
+ bitLen = t.Colon[0].Value
}
base.TypeSize = size
return &prog.IntType{
- IntTypeCommon: genIntCommon(base.TypeCommon, t.Value2, be),
+ IntTypeCommon: genIntCommon(base.TypeCommon, bitLen, be),
Kind: kind,
RangeBegin: rangeBegin,
RangeEnd: rangeEnd,
@@ -139,7 +147,7 @@ var typeArray = &typeDesc{
OptArgs: 1,
Args: []namedArg{{Name: "type", Type: typeArgType}, {Name: "size", Type: typeArgSizeRange}},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
- if len(args) > 1 && args[1].Value == 0 && args[1].Value2 == 0 {
+ if len(args) > 1 && args[1].Value == 0 && (len(args[1].Colon) == 0 || args[1].Colon[0].Value == 0) {
comp.error(args[1].Pos, "arrays of size 0 are not supported")
}
},
@@ -151,7 +159,7 @@ var typeArray = &typeDesc{
return true
}
if len(args) > 1 {
- return args[1].Value != args[1].Value2
+ return len(args[1].Colon) != 0 && args[1].Value != args[1].Colon[0].Value
}
return true
},
@@ -162,7 +170,10 @@ var typeArray = &typeDesc{
elemType := comp.genType(args[0], "", base.ArgDir, false)
kind, begin, end := prog.ArrayRandLen, uint64(0), uint64(0)
if len(args) > 1 {
- kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value2
+ kind, begin, end = prog.ArrayRangeLen, args[1].Value, args[1].Value
+ if len(args[1].Colon) != 0 {
+ end = args[1].Colon[0].Value
+ }
}
if it, ok := elemType.(*prog.IntType); ok && it.Kind == prog.IntPlain && it.TypeSize == 1 {
// Special case: buffer is better mutated.
@@ -301,9 +312,12 @@ var typeVMA = &typeDesc{
OptArgs: 1,
Args: []namedArg{{Name: "size range", Type: typeArgSizeRange}},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
- begin, end := uint64(0), uint64(0)
+ var begin, end uint64
if len(args) > 0 {
- begin, end = args[0].Value, args[0].Value2
+ begin, end = args[0].Value, args[0].Value
+ if len(args[0].Colon) != 0 {
+ end = args[0].Colon[0].Value
+ }
}
base.TypeSize = comp.ptrSize
if t.Ident == "vma64" {
@@ -762,30 +776,31 @@ var typeArgInt = &typeArg{
}
var typeArgIntRange = &typeArg{
- Kind: kindInt,
- AllowColon: true,
+ Kind: kindInt,
+ MaxColon: 1,
CheckConsts: func(comp *compiler, t *ast.Type) {
- if !t.HasColon {
- t.Value2 = t.Value
- t.Value2Fmt = t.ValueFmt
+ end := t.Value
+ if len(t.Colon) != 0 {
+ end = t.Colon[0].Value
}
- if t.Value2-t.Value > 1<<64-1<<32 {
- comp.error(t.Pos, "bad int range [%v:%v]", t.Value, t.Value2)
+ if end-t.Value > 1<<64-1<<32 {
+ comp.error(t.Pos, "bad int range [%v:%v]", t.Value, end)
}
},
}
// Size of array and vma's.
var typeArgSizeRange = &typeArg{
- Kind: kindInt,
- AllowColon: true,
+ Kind: kindInt,
+ MaxColon: 1,
CheckConsts: func(comp *compiler, t *ast.Type) {
- if !t.HasColon {
- t.Value2 = t.Value
+ end := t.Value
+ if len(t.Colon) != 0 {
+ end = t.Colon[0].Value
}
const maxVal = 1e6
- if t.Value > t.Value2 || t.Value > maxVal || t.Value2 > maxVal {
- comp.error(t.Pos, "bad size range [%v:%v]", t.Value, t.Value2)
+ if t.Value > end || t.Value > maxVal || end > maxVal {
+ comp.error(t.Pos, "bad size range [%v:%v]", t.Value, end)
}
},
}
@@ -794,25 +809,26 @@ var typeArgSizeRange = &typeArg{
var typeArgBase = namedArg{
Name: "base type",
Type: &typeArg{
- Names: []string{"int8", "int16", "int32", "int64", "int16be", "int32be", "int64be", "intptr"},
- AllowColon: true,
+ Names: []string{"int8", "int16", "int32", "int64", "int16be", "int32be", "int64be", "intptr"},
+ MaxColon: 1,
Check: func(comp *compiler, t *ast.Type) {
- if t.HasColon {
- if t.Ident2 != "" {
- comp.error(t.Pos2, "literal const bitfield sizes are not supported")
+ if len(t.Colon) != 0 {
+ col := t.Colon[0]
+ if col.Ident != "" {
+ comp.error(col.Pos, "literal const bitfield sizes are not supported")
return
}
- if t.Value2 == 0 {
+ if col.Value == 0 {
// This was not supported historically
// and does not work the way C bitfields of size 0 work.
// We could allow this, but then we need to make
// this work the way C bitfields work.
- comp.error(t.Pos2, "bitfields of size 0 are not supported")
+ comp.error(col.Pos, "bitfields of size 0 are not supported")
}
size, _ := comp.parseIntType(t.Ident)
- if t.Value2 > size*8 {
- comp.error(t.Pos2, "bitfield of size %v is too large for base type of size %v",
- t.Value2, size*8)
+ if col.Value > size*8 {
+ comp.error(col.Pos, "bitfield of size %v is too large for base type of size %v",
+ col.Value, size*8)
}
}
},