aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler/check.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-02-17 17:00:53 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-02-17 19:02:12 +0100
commit414c035582c39398ddd927b5e4fdfd7a6f3aefc5 (patch)
treeccc2277a5c8f233d376fb4117203c3bb7e14ce7a /pkg/compiler/check.go
parenta08436c97370fa1df802728683ca2429af93b841 (diff)
pkg/compiler: support template template arguments
Can be useful for netfilter descriptions.
Diffstat (limited to 'pkg/compiler/check.go')
-rw-r--r--pkg/compiler/check.go23
1 files changed, 19 insertions, 4 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 003fe424f..e7333b9ae 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -683,12 +683,16 @@ func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, desc *typeDesc,
}
if typedef.Type != nil {
*t = *typedef.Type.Clone().(*ast.Type)
- comp.instantiate(t, typedef.Args, args)
+ if !comp.instantiate(t, typedef.Args, args) {
+ return
+ }
} else {
if comp.structs[fullTypeName] == nil {
inst := typedef.Struct.Clone().(*ast.Struct)
inst.Name.Name = fullTypeName
- comp.instantiate(inst, typedef.Args, args)
+ if !comp.instantiate(inst, typedef.Args, args) {
+ return
+ }
comp.checkStruct(*ctx, inst)
comp.desc.Nodes = append(comp.desc.Nodes, inst)
comp.structs[fullTypeName] = inst
@@ -711,21 +715,31 @@ func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, desc *typeDesc,
}
}
-func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*ast.Type) {
+func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*ast.Type) bool {
if len(params) == 0 {
- return
+ return true
}
argMap := make(map[string]*ast.Type)
for i, param := range params {
argMap[param.Name] = args[i]
}
+ err0 := comp.errors
templ.Walk(ast.Recursive(func(n ast.Node) {
templArg, ok := n.(*ast.Type)
if !ok {
return
}
if concreteArg := argMap[templArg.Ident]; concreteArg != nil {
+ origArgs := templArg.Args
+ if len(origArgs) != 0 && len(concreteArg.Args) != 0 {
+ comp.error(templArg.Pos, "both template parameter %v and its usage"+
+ " have sub-arguments", templArg.Ident)
+ return
+ }
*templArg = *concreteArg.Clone().(*ast.Type)
+ if len(origArgs) != 0 {
+ templArg.Args = origArgs
+ }
}
// TODO(dvyukov): somewhat hacky, but required for int8[0:CONST_ARG]
// Need more checks here. E.g. that CONST_ARG does not have subargs.
@@ -736,6 +750,7 @@ func (comp *compiler) instantiate(templ ast.Node, params []*ast.Ident, args []*a
templArg.Pos2 = concreteArg.Pos
}
}))
+ return err0 == comp.errors
}
func (comp *compiler) checkTypeArg(t, arg *ast.Type, argDesc namedArg) {