aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-04 19:52:42 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-04 20:25:22 +0200
commit8094a4202f10d59457a2a33d4e276b32c0ca16bf (patch)
tree433f87a6376e637c0ec1aae185f67343024220d1 /pkg/compiler
parentf29b943c0b672ff7f02c1046416f1b85d7344bfb (diff)
pkg/compiler: move checking code to a separate file
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/check.go403
-rw-r--r--pkg/compiler/compiler.go390
2 files changed, 403 insertions, 390 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
new file mode 100644
index 000000000..d6db087c7
--- /dev/null
+++ b/pkg/compiler/check.go
@@ -0,0 +1,403 @@
+// Copyright 2017 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// Package compiler generates sys descriptions of syscalls, types and resources
+// from textual descriptions.
+package compiler
+
+import (
+ "fmt"
+
+ "github.com/google/syzkaller/pkg/ast"
+ "github.com/google/syzkaller/sys"
+)
+
+func (comp *compiler) check() {
+ // TODO: check len in syscall arguments referring to parent.
+ // TODO: incorrect name is referenced in len type
+ // TODO: no constructor for a resource
+
+ comp.checkNames()
+ comp.checkFields()
+ comp.checkTypes()
+ comp.checkRecursion()
+}
+
+func (comp *compiler) checkNames() {
+ calls := make(map[string]*ast.Call)
+ for _, decl := range comp.desc.Nodes {
+ switch decl.(type) {
+ case *ast.Resource, *ast.Struct:
+ pos, typ, name := decl.Info()
+ if builtinTypes[name] != nil {
+ comp.error(pos, "%v name %v conflicts with builtin type", typ, name)
+ continue
+ }
+ if prev := comp.resources[name]; prev != nil {
+ comp.error(pos, "type %v redeclared, previously declared as resource at %v",
+ name, prev.Pos)
+ continue
+ }
+ if prev := comp.structs[name]; prev != nil {
+ _, typ, _ := prev.Info()
+ comp.error(pos, "type %v redeclared, previously declared as %v at %v",
+ name, typ, prev.Pos)
+ continue
+ }
+ if res, ok := decl.(*ast.Resource); ok {
+ comp.resources[name] = res
+ } else if str, ok := decl.(*ast.Struct); ok {
+ comp.structs[name] = str
+ }
+ case *ast.IntFlags:
+ n := decl.(*ast.IntFlags)
+ name := n.Name.Name
+ if prev := comp.intFlags[name]; prev != nil {
+ comp.error(n.Pos, "flags %v redeclared, previously declared at %v",
+ name, prev.Pos)
+ continue
+ }
+ comp.intFlags[name] = n
+ case *ast.StrFlags:
+ n := decl.(*ast.StrFlags)
+ name := n.Name.Name
+ if prev := comp.strFlags[name]; prev != nil {
+ comp.error(n.Pos, "string flags %v redeclared, previously declared at %v",
+ name, prev.Pos)
+ continue
+ }
+ comp.strFlags[name] = n
+ case *ast.Call:
+ c := decl.(*ast.Call)
+ name := c.Name.Name
+ if prev := calls[name]; prev != nil {
+ comp.error(c.Pos, "syscall %v redeclared, previously declared at %v",
+ name, prev.Pos)
+ }
+ calls[name] = c
+ }
+ }
+}
+
+func (comp *compiler) checkFields() {
+ const maxArgs = 9 // executor does not support more
+ for _, decl := range comp.desc.Nodes {
+ switch n := decl.(type) {
+ case *ast.Struct:
+ _, typ, name := n.Info()
+ fields := make(map[string]bool)
+ for _, f := range n.Fields {
+ fn := f.Name.Name
+ if fn == "parent" {
+ comp.error(f.Pos, "reserved field name %v in %v %v", fn, typ, name)
+ }
+ if fields[fn] {
+ comp.error(f.Pos, "duplicate field %v in %v %v", fn, typ, name)
+ }
+ fields[fn] = true
+ }
+ if !n.IsUnion && len(n.Fields) < 1 {
+ comp.error(n.Pos, "struct %v has no fields, need at least 1 field", name)
+ }
+ if n.IsUnion && len(n.Fields) < 2 {
+ comp.error(n.Pos, "union %v has only %v field, need at least 2 fields",
+ name, len(n.Fields))
+ }
+ case *ast.Call:
+ name := n.Name.Name
+ args := make(map[string]bool)
+ for _, a := range n.Args {
+ an := a.Name.Name
+ if an == "parent" {
+ comp.error(a.Pos, "reserved argument name %v in syscall %v",
+ an, name)
+ }
+ if args[an] {
+ comp.error(a.Pos, "duplicate argument %v in syscall %v",
+ an, name)
+ }
+ args[an] = true
+ }
+ if len(n.Args) > maxArgs {
+ comp.error(n.Pos, "syscall %v has %v arguments, allowed maximum is %v",
+ name, len(n.Args), maxArgs)
+ }
+ }
+ }
+}
+
+func (comp *compiler) checkTypes() {
+ for _, decl := range comp.desc.Nodes {
+ switch n := decl.(type) {
+ case *ast.Resource:
+ comp.checkType(n.Base, false, true)
+ case *ast.Struct:
+ for _, f := range n.Fields {
+ comp.checkType(f.Type, false, false)
+ }
+ comp.checkStruct(n)
+ case *ast.Call:
+ for _, a := range n.Args {
+ comp.checkType(a.Type, true, false)
+ }
+ if n.Ret != nil {
+ comp.checkType(n.Ret, true, false)
+ }
+ }
+ }
+}
+
+func (comp *compiler) checkRecursion() {
+ checked := make(map[string]bool)
+ for _, decl := range comp.desc.Nodes {
+ switch n := decl.(type) {
+ case *ast.Resource:
+ comp.checkResourceRecursion(n)
+ case *ast.Struct:
+ comp.checkStructRecursion(checked, n)
+ }
+ }
+}
+
+func (comp *compiler) checkResourceRecursion(n *ast.Resource) {
+ var seen []string
+ for n != nil {
+ if arrayContains(seen, n.Name.Name) {
+ chain := ""
+ for _, r := range seen {
+ chain += r + "->"
+ }
+ chain += n.Name.Name
+ comp.error(n.Pos, "recursive resource %v", chain)
+ return
+ }
+ seen = append(seen, n.Name.Name)
+ n = comp.resources[n.Base.Ident]
+ }
+}
+
+type pathElem struct {
+ Pos ast.Pos
+ Struct string
+ Field string
+}
+
+func (comp *compiler) checkStructRecursion(checked map[string]bool, n *ast.Struct) {
+ var path []pathElem
+ comp.checkStructRecursion1(checked, n, path)
+}
+
+func (comp *compiler) checkStructRecursion1(checked map[string]bool, n *ast.Struct, path []pathElem) {
+ name := n.Name.Name
+ if checked[name] {
+ return
+ }
+ for i, elem := range path {
+ if elem.Struct != name {
+ continue
+ }
+ path = path[i:]
+ str := ""
+ for _, elem := range path {
+ str += fmt.Sprintf("%v.%v -> ", elem.Struct, elem.Field)
+ }
+ str += name
+ comp.error(path[0].Pos, "recursive declaration: %v (mark some pointers as opt)", str)
+ checked[name] = true
+ return
+ }
+ for _, f := range n.Fields {
+ path = append(path, pathElem{
+ Pos: f.Pos,
+ Struct: name,
+ Field: f.Name.Name,
+ })
+ comp.recurseField(checked, f.Type, path)
+ path = path[:len(path)-1]
+ }
+ checked[name] = true
+}
+
+func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []pathElem) {
+ desc := comp.getTypeDesc(t)
+ if desc == typeStruct {
+ comp.checkStructRecursion1(checked, comp.structs[t.Ident], path)
+ return
+ }
+ _, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
+ if desc == typePtr && base.IsOptional {
+ return // optional pointers prune recursion
+ }
+ for i, arg := range args {
+ if desc.Args[i].Type == typeArgType {
+ comp.recurseField(checked, arg, path)
+ }
+ }
+}
+
+func (comp *compiler) checkStruct(n *ast.Struct) {
+ if n.IsUnion {
+ comp.parseUnionAttrs(n)
+ } else {
+ comp.parseStructAttrs(n)
+ }
+}
+
+func (comp *compiler) checkType(t *ast.Type, isArg, isResourceBase bool) {
+ if unexpected, _, ok := checkTypeKind(t, kindIdent); !ok {
+ comp.error(t.Pos, "unexpected %v, expect type", unexpected)
+ return
+ }
+ desc := comp.getTypeDesc(t)
+ if desc == nil {
+ comp.error(t.Pos, "unknown type %v", t.Ident)
+ return
+ }
+ if !desc.AllowColon && t.HasColon {
+ comp.error(t.Pos2, "unexpected ':'")
+ return
+ }
+ if isArg && !desc.CanBeArg {
+ comp.error(t.Pos, "%v can't be syscall argument/return", t.Ident)
+ return
+ }
+ if isResourceBase && !desc.ResourceBase {
+ comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident)
+ return
+ }
+ args, opt := removeOpt(t)
+ if opt && (desc.CantBeOpt || isResourceBase) {
+ what := "resource base"
+ if desc.CantBeOpt {
+ what = t.Ident
+ }
+ pos := t.Args[len(t.Args)-1].Pos
+ comp.error(pos, "%v can't be marked as opt", what)
+ return
+ }
+ addArgs := 0
+ needBase := !isArg && desc.NeedBase
+ if needBase {
+ addArgs++ // last arg must be base type, e.g. const[0, int32]
+ }
+ if len(args) > len(desc.Args)+addArgs || len(args) < len(desc.Args)-desc.OptArgs+addArgs {
+ comp.error(t.Pos, "wrong number of arguments for type %v, expect %v",
+ t.Ident, expectedTypeArgs(desc, needBase))
+ return
+ }
+ if needBase {
+ base := args[len(args)-1]
+ args = args[:len(args)-1]
+ comp.checkTypeArg(t, base, typeArgBase)
+ }
+ err0 := comp.errors
+ for i, arg := range args {
+ if desc.Args[i].Type == typeArgType {
+ comp.checkType(arg, false, false)
+ } else {
+ comp.checkTypeArg(t, arg, desc.Args[i])
+ }
+ }
+ if err0 != comp.errors {
+ return
+ }
+ if desc.Check != nil {
+ _, args, base := comp.getArgsBase(t, "", sys.DirIn, isArg)
+ desc.Check(comp, t, args, base)
+ }
+}
+
+func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {
+ desc := argDesc.Type
+ if len(desc.Names) != 0 {
+ if unexpected, _, ok := checkTypeKind(arg, kindIdent); !ok {
+ comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %+v",
+ unexpected, argDesc.Name, t.Ident, desc.Names)
+ return
+ }
+ if !arrayContains(desc.Names, arg.Ident) {
+ comp.error(arg.Pos, "unexpected value %v for %v argument of %v type, expect %+v",
+ arg.Ident, argDesc.Name, t.Ident, desc.Names)
+ return
+ }
+ } else {
+ if unexpected, expect, ok := checkTypeKind(arg, desc.Kind); !ok {
+ comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %v",
+ unexpected, argDesc.Name, t.Ident, expect)
+ return
+ }
+ }
+ if !desc.AllowColon && arg.HasColon {
+ comp.error(arg.Pos2, "unexpected ':'")
+ return
+ }
+ if desc.Check != nil {
+ desc.Check(comp, arg)
+ }
+}
+
+func expectedTypeArgs(desc *typeDesc, needBase bool) string {
+ expect := ""
+ for i, arg := range desc.Args {
+ if expect != "" {
+ expect += ", "
+ }
+ opt := i >= len(desc.Args)-desc.OptArgs
+ if opt {
+ expect += "["
+ }
+ expect += arg.Name
+ if opt {
+ expect += "]"
+ }
+ }
+ if needBase {
+ if expect != "" {
+ expect += ", "
+ }
+ expect += typeArgBase.Name
+ }
+ if !desc.CantBeOpt {
+ if expect != "" {
+ expect += ", "
+ }
+ expect += "[opt]"
+ }
+ if expect == "" {
+ expect = "no arguments"
+ }
+ return expect
+}
+
+func checkTypeKind(t *ast.Type, kind int) (unexpected string, expect string, ok bool) {
+ switch {
+ case kind == kindAny:
+ ok = true
+ case t.String != "":
+ ok = kind == kindString
+ if !ok {
+ unexpected = fmt.Sprintf("string %q", t.String)
+ }
+ case t.Ident != "":
+ ok = kind == kindIdent
+ if !ok {
+ unexpected = fmt.Sprintf("identifier %v", t.Ident)
+ }
+ default:
+ ok = kind == kindInt
+ 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"
+ }
+ }
+ return
+}
diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go
index a192ed8d7..fe3f28d77 100644
--- a/pkg/compiler/compiler.go
+++ b/pkg/compiler/compiler.go
@@ -105,237 +105,6 @@ func (comp *compiler) warning(pos ast.Pos, msg string, args ...interface{}) {
comp.warnings = append(comp.warnings, warn{pos, fmt.Sprintf(msg, args...)})
}
-func (comp *compiler) check() {
- // TODO: check len in syscall arguments referring to parent.
- // TODO: incorrect name is referenced in len type
- // TODO: no constructor for a resource
-
- comp.checkNames()
- comp.checkFields()
- comp.checkTypes()
- comp.checkRecursion()
-}
-
-func (comp *compiler) checkNames() {
- calls := make(map[string]*ast.Call)
- for _, decl := range comp.desc.Nodes {
- switch decl.(type) {
- case *ast.Resource, *ast.Struct:
- pos, typ, name := decl.Info()
- if builtinTypes[name] != nil {
- comp.error(pos, "%v name %v conflicts with builtin type", typ, name)
- continue
- }
- if prev := comp.resources[name]; prev != nil {
- comp.error(pos, "type %v redeclared, previously declared as resource at %v",
- name, prev.Pos)
- continue
- }
- if prev := comp.structs[name]; prev != nil {
- _, typ, _ := prev.Info()
- comp.error(pos, "type %v redeclared, previously declared as %v at %v",
- name, typ, prev.Pos)
- continue
- }
- if res, ok := decl.(*ast.Resource); ok {
- comp.resources[name] = res
- } else if str, ok := decl.(*ast.Struct); ok {
- comp.structs[name] = str
- }
- case *ast.IntFlags:
- n := decl.(*ast.IntFlags)
- name := n.Name.Name
- if prev := comp.intFlags[name]; prev != nil {
- comp.error(n.Pos, "flags %v redeclared, previously declared at %v",
- name, prev.Pos)
- continue
- }
- comp.intFlags[name] = n
- case *ast.StrFlags:
- n := decl.(*ast.StrFlags)
- name := n.Name.Name
- if prev := comp.strFlags[name]; prev != nil {
- comp.error(n.Pos, "string flags %v redeclared, previously declared at %v",
- name, prev.Pos)
- continue
- }
- comp.strFlags[name] = n
- case *ast.Call:
- c := decl.(*ast.Call)
- name := c.Name.Name
- if prev := calls[name]; prev != nil {
- comp.error(c.Pos, "syscall %v redeclared, previously declared at %v",
- name, prev.Pos)
- }
- calls[name] = c
- }
- }
-}
-
-func (comp *compiler) checkFields() {
- const maxArgs = 9 // executor does not support more
- for _, decl := range comp.desc.Nodes {
- switch n := decl.(type) {
- case *ast.Struct:
- _, typ, name := n.Info()
- fields := make(map[string]bool)
- for _, f := range n.Fields {
- fn := f.Name.Name
- if fn == "parent" {
- comp.error(f.Pos, "reserved field name %v in %v %v", fn, typ, name)
- }
- if fields[fn] {
- comp.error(f.Pos, "duplicate field %v in %v %v", fn, typ, name)
- }
- fields[fn] = true
- }
- if !n.IsUnion && len(n.Fields) < 1 {
- comp.error(n.Pos, "struct %v has no fields, need at least 1 field", name)
- }
- if n.IsUnion && len(n.Fields) < 2 {
- comp.error(n.Pos, "union %v has only %v field, need at least 2 fields",
- name, len(n.Fields))
- }
- case *ast.Call:
- name := n.Name.Name
- args := make(map[string]bool)
- for _, a := range n.Args {
- an := a.Name.Name
- if an == "parent" {
- comp.error(a.Pos, "reserved argument name %v in syscall %v",
- an, name)
- }
- if args[an] {
- comp.error(a.Pos, "duplicate argument %v in syscall %v",
- an, name)
- }
- args[an] = true
- }
- if len(n.Args) > maxArgs {
- comp.error(n.Pos, "syscall %v has %v arguments, allowed maximum is %v",
- name, len(n.Args), maxArgs)
- }
- }
- }
-}
-
-func (comp *compiler) checkTypes() {
- for _, decl := range comp.desc.Nodes {
- switch n := decl.(type) {
- case *ast.Resource:
- comp.checkType(n.Base, false, true)
- case *ast.Struct:
- for _, f := range n.Fields {
- comp.checkType(f.Type, false, false)
- }
- comp.checkStruct(n)
- case *ast.Call:
- for _, a := range n.Args {
- comp.checkType(a.Type, true, false)
- }
- if n.Ret != nil {
- comp.checkType(n.Ret, true, false)
- }
- }
- }
-}
-
-func (comp *compiler) checkRecursion() {
- checked := make(map[string]bool)
- for _, decl := range comp.desc.Nodes {
- switch n := decl.(type) {
- case *ast.Resource:
- comp.checkResourceRecursion(n)
- case *ast.Struct:
- comp.checkStructRecursion(checked, n)
- }
- }
-}
-
-func (comp *compiler) checkResourceRecursion(n *ast.Resource) {
- var seen []string
- for n != nil {
- if arrayContains(seen, n.Name.Name) {
- chain := ""
- for _, r := range seen {
- chain += r + "->"
- }
- chain += n.Name.Name
- comp.error(n.Pos, "recursive resource %v", chain)
- return
- }
- seen = append(seen, n.Name.Name)
- n = comp.resources[n.Base.Ident]
- }
-}
-
-type pathElem struct {
- Pos ast.Pos
- Struct string
- Field string
-}
-
-func (comp *compiler) checkStructRecursion(checked map[string]bool, n *ast.Struct) {
- var path []pathElem
- comp.checkStructRecursion1(checked, n, path)
-}
-
-func (comp *compiler) checkStructRecursion1(checked map[string]bool, n *ast.Struct, path []pathElem) {
- name := n.Name.Name
- if checked[name] {
- return
- }
- for i, elem := range path {
- if elem.Struct != name {
- continue
- }
- path = path[i:]
- str := ""
- for _, elem := range path {
- str += fmt.Sprintf("%v.%v -> ", elem.Struct, elem.Field)
- }
- str += name
- comp.error(path[0].Pos, "recursive declaration: %v (mark some pointers as opt)", str)
- checked[name] = true
- return
- }
- for _, f := range n.Fields {
- path = append(path, pathElem{
- Pos: f.Pos,
- Struct: name,
- Field: f.Name.Name,
- })
- comp.recurseField(checked, f.Type, path)
- path = path[:len(path)-1]
- }
- checked[name] = true
-}
-
-func (comp *compiler) recurseField(checked map[string]bool, t *ast.Type, path []pathElem) {
- desc := comp.getTypeDesc(t)
- if desc == typeStruct {
- comp.checkStructRecursion1(checked, comp.structs[t.Ident], path)
- return
- }
- _, args, base := comp.getArgsBase(t, "", sys.DirIn, false)
- if desc == typePtr && base.IsOptional {
- return // optional pointers prune recursion
- }
- for i, arg := range args {
- if desc.Args[i].Type == typeArgType {
- comp.recurseField(checked, arg, path)
- }
- }
-}
-
-func (comp *compiler) checkStruct(n *ast.Struct) {
- if n.IsUnion {
- comp.parseUnionAttrs(n)
- } else {
- comp.parseStructAttrs(n)
- }
-}
-
func (comp *compiler) parseUnionAttrs(n *ast.Struct) (varlen bool) {
for _, attr := range n.Attrs {
switch attr.Name {
@@ -389,99 +158,6 @@ func (comp *compiler) getTypeDesc(t *ast.Type) *typeDesc {
return nil
}
-func (comp *compiler) checkType(t *ast.Type, isArg, isResourceBase bool) {
- if unexpected, _, ok := checkTypeKind(t, kindIdent); !ok {
- comp.error(t.Pos, "unexpected %v, expect type", unexpected)
- return
- }
- desc := comp.getTypeDesc(t)
- if desc == nil {
- comp.error(t.Pos, "unknown type %v", t.Ident)
- return
- }
- if !desc.AllowColon && t.HasColon {
- comp.error(t.Pos2, "unexpected ':'")
- return
- }
- if isArg && !desc.CanBeArg {
- comp.error(t.Pos, "%v can't be syscall argument/return", t.Ident)
- return
- }
- if isResourceBase && !desc.ResourceBase {
- comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident)
- return
- }
- args, opt := removeOpt(t)
- if opt && (desc.CantBeOpt || isResourceBase) {
- what := "resource base"
- if desc.CantBeOpt {
- what = t.Ident
- }
- pos := t.Args[len(t.Args)-1].Pos
- comp.error(pos, "%v can't be marked as opt", what)
- return
- }
- addArgs := 0
- needBase := !isArg && desc.NeedBase
- if needBase {
- addArgs++ // last arg must be base type, e.g. const[0, int32]
- }
- if len(args) > len(desc.Args)+addArgs || len(args) < len(desc.Args)-desc.OptArgs+addArgs {
- comp.error(t.Pos, "wrong number of arguments for type %v, expect %v",
- t.Ident, expectedTypeArgs(desc, needBase))
- return
- }
- if needBase {
- base := args[len(args)-1]
- args = args[:len(args)-1]
- comp.checkTypeArg(t, base, typeArgBase)
- }
- err0 := comp.errors
- for i, arg := range args {
- if desc.Args[i].Type == typeArgType {
- comp.checkType(arg, false, false)
- } else {
- comp.checkTypeArg(t, arg, desc.Args[i])
- }
- }
- if err0 != comp.errors {
- return
- }
- if desc.Check != nil {
- _, args, base := comp.getArgsBase(t, "", sys.DirIn, isArg)
- desc.Check(comp, t, args, base)
- }
-}
-
-func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {
- desc := argDesc.Type
- if len(desc.Names) != 0 {
- if unexpected, _, ok := checkTypeKind(arg, kindIdent); !ok {
- comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %+v",
- unexpected, argDesc.Name, t.Ident, desc.Names)
- return
- }
- if !arrayContains(desc.Names, arg.Ident) {
- comp.error(arg.Pos, "unexpected value %v for %v argument of %v type, expect %+v",
- arg.Ident, argDesc.Name, t.Ident, desc.Names)
- return
- }
- } else {
- if unexpected, expect, ok := checkTypeKind(arg, desc.Kind); !ok {
- comp.error(arg.Pos, "unexpected %v for %v argument of %v type, expect %v",
- unexpected, argDesc.Name, t.Ident, expect)
- return
- }
- }
- if !desc.AllowColon && arg.HasColon {
- comp.error(arg.Pos2, "unexpected ':'")
- return
- }
- if desc.Check != nil {
- desc.Check(comp, arg)
- }
-}
-
func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg bool) (
*typeDesc, []*ast.Type, sys.IntTypeCommon) {
desc := comp.getTypeDesc(t)
@@ -496,72 +172,6 @@ func (comp *compiler) getArgsBase(t *ast.Type, field string, dir sys.Dir, isArg
return desc, args, base
}
-func expectedTypeArgs(desc *typeDesc, needBase bool) string {
- expect := ""
- for i, arg := range desc.Args {
- if expect != "" {
- expect += ", "
- }
- opt := i >= len(desc.Args)-desc.OptArgs
- if opt {
- expect += "["
- }
- expect += arg.Name
- if opt {
- expect += "]"
- }
- }
- if needBase {
- if expect != "" {
- expect += ", "
- }
- expect += typeArgBase.Name
- }
- if !desc.CantBeOpt {
- if expect != "" {
- expect += ", "
- }
- expect += "[opt]"
- }
- if expect == "" {
- expect = "no arguments"
- }
- return expect
-}
-
-func checkTypeKind(t *ast.Type, kind int) (unexpected string, expect string, ok bool) {
- switch {
- case kind == kindAny:
- ok = true
- case t.String != "":
- ok = kind == kindString
- if !ok {
- unexpected = fmt.Sprintf("string %q", t.String)
- }
- case t.Ident != "":
- ok = kind == kindIdent
- if !ok {
- unexpected = fmt.Sprintf("identifier %v", t.Ident)
- }
- default:
- ok = kind == kindInt
- 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"
- }
- }
- return
-}
-
func removeOpt(t *ast.Type) ([]*ast.Type, bool) {
args := t.Args
if len(args) != 0 && args[len(args)-1].Ident == "opt" {