aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorPaul Chaignon <paul.chaignon@gmail.com>2023-11-09 19:20:07 +0100
committerAleksandr Nogikh <nogikh@google.com>2023-11-28 10:18:54 +0000
commitb2566dc325435823ffcfcef3c02016925556f81b (patch)
tree2ea69567f76d4dc7848b46ed4ff08480829b389c /pkg/compiler
parent9fe51b7c608bca7b80c06c30f78c7c60810d51f1 (diff)
compiler: support type args with mixed kinds
Type args can currently have only one type of kindInt, kindIdent, kindString, or kindAny. The descriptions are checked against expected type arg kinds, with kindAny meaning that anything is allowed (often restricted with custom checks). Concretely, it means that in a description as follows, arg1 and arg2 can each take a single kind of values. type[arg1, arg2] This is limiting if we want arg1 to be able to take both an int or flags. We thus need type args to support having mixed kinds. This commit achieves this by turning the kind constants into bit flags. This will be useful in a subsequent commit, but we can also already use it for one existing type arg, the first of string types: string[literal_or_flags, size] literal_or_flags changes from kindAny to kindIdent|kindString and we can remove the custom check that used to enforce this. Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/check.go26
-rw-r--r--pkg/compiler/consts.go4
-rw-r--r--pkg/compiler/testdata/errors.txt4
-rw-r--r--pkg/compiler/types.go9
4 files changed, 23 insertions, 20 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 44c354606..2a14b9cc0 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -1179,6 +1179,9 @@ func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {
comp.error(col.Pos, "unexpected ':'")
return
}
+ // We only want to perform this check if kindIdent is the only kind of
+ // this type. Otherwise, the token after the colon could legitimately
+ // be an int for example.
if desc.Kind == kindIdent {
if unexpected, expect, ok := checkTypeKind(col, kindIdent); !ok {
comp.error(arg.Pos, "unexpected %v after colon, expect %v", unexpected, expect)
@@ -1233,30 +1236,33 @@ func checkTypeKind(t *ast.Type, kind int) (unexpected, expect string, ok bool) {
case kind == kindAny:
ok = true
case t.HasString:
- ok = kind == kindString
+ ok = kind&kindString != 0
if !ok {
unexpected = fmt.Sprintf("string %q", t.String)
}
case t.Ident != "":
- ok = kind == kindIdent || kind == kindInt
+ ok = kind&(kindIdent|kindInt) != 0
if !ok {
unexpected = fmt.Sprintf("identifier %v", t.Ident)
}
default:
- ok = kind == kindInt
+ ok = kind&kindInt != 0
if !ok {
unexpected = fmt.Sprintf("int %v", t.Value)
}
}
if !ok {
- switch kind {
- case kindString:
- expect = "string"
- case kindIdent:
- expect = "identifier"
- case kindInt:
- expect = "int"
+ var expected []string
+ if kind&kindString != 0 {
+ expected = append(expected, "string")
}
+ if kind&kindIdent != 0 {
+ expected = append(expected, "identifier")
+ }
+ if kind&kindInt != 0 {
+ expected = append(expected, "int")
+ }
+ expect = strings.Join(expected, " or ")
}
return
}
diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go
index 6652a381c..e9f7227e7 100644
--- a/pkg/compiler/consts.go
+++ b/pkg/compiler/consts.go
@@ -105,7 +105,7 @@ func (comp *compiler) extractConsts() map[string]*ConstInfo {
func (comp *compiler) extractTypeConsts(infos map[string]*constInfo, n ast.Node) {
comp.foreachType(n, func(t *ast.Type, desc *typeDesc, args []*ast.Type, _ prog.IntTypeCommon) {
for i, arg := range args {
- if desc.Args[i].Type.Kind == kindInt {
+ if desc.Args[i].Type.Kind&kindInt != 0 {
if arg.Ident != "" {
comp.addConst(infos, arg.Pos, arg.Ident)
}
@@ -228,7 +228,7 @@ func (comp *compiler) patchConsts(consts0 map[string]uint64) {
comp.foreachType(decl, func(_ *ast.Type, desc *typeDesc,
args []*ast.Type, _ prog.IntTypeCommon) {
for i, arg := range args {
- if desc.Args[i].Type.Kind == kindInt {
+ if desc.Args[i].Type.Kind&kindInt != 0 {
comp.patchTypeConst(arg, consts, &missing)
}
}
diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt
index 83b62cfb6..87b9e5f68 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -110,7 +110,7 @@ foo$36(a const[1:2]) ### unexpected ':'
foo$39(a fileoff:1) ### type alias fileoff with ':'
foo$40(a len["a"]) ### unexpected string "a" for len target argument of len type, expect identifier
foo$41(a vma[C1:C2])
-foo$43(a ptr[in, string[1]]) ### unexpected int 1, string arg must be a string literal or string flags
+foo$43(a ptr[in, string[1]]) ### unexpected int 1 for literal or flags argument of string type, expect string or identifier
foo$44(a int32) len[a] ### len can't be syscall return
foo$45(a int32) len[b] ### len can't be syscall return
foo$46(a ptr[in, in]) ### unknown type in
@@ -369,7 +369,7 @@ type TT3[A] {
foo$213(a ptr[in, TT1[int8]])
-foo$glob001(a ptr[in, glob[1]]) ### unexpected int 1, string arg must be a string literal or string flags
+foo$glob001(a ptr[in, glob[1]]) ### unexpected int 1 for literal or flags argument of glob type, expect string or identifier
foo$glob002(a ptr[in, glob]) ### glob only accepts 1 arg, provided 0
foo$glob003(a ptr[in, glob["/sys", 5]]) ### glob only accepts 1 arg, provided 2
foo$glob004(a ptr[in, glob["/sys", 5, 2]]) ### wrong number of arguments for type glob, expect [literal or flags], [size], [opt]
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index a55a6c50d..b3feb796a 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -60,8 +60,8 @@ type namedArg struct {
}
const (
- kindAny = iota
- kindInt
+ kindAny = 0
+ kindInt = 1 << iota
kindIdent
kindString
)
@@ -748,11 +748,8 @@ func (comp *compiler) stringSize(t *ast.Type, args []*ast.Type) uint64 {
}
var typeArgStringFlags = &typeArg{
+ Kind: kindIdent | kindString,
Check: func(comp *compiler, t *ast.Type) {
- if !t.HasString && t.Ident == "" {
- comp.error(t.Pos, "unexpected int %v, string arg must be a string literal or string flags", t.Value)
- return
- }
if t.Ident != "" && comp.strFlags[t.Ident] == nil {
comp.error(t.Pos, "unknown string flags %v", t.Ident)
return