aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
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
parenta08436c97370fa1df802728683ca2429af93b841 (diff)
pkg/compiler: support template template arguments
Can be useful for netfilter descriptions.
Diffstat (limited to 'pkg')
-rw-r--r--pkg/compiler/check.go23
-rw-r--r--pkg/compiler/testdata/all.txt20
-rw-r--r--pkg/compiler/testdata/errors.txt17
3 files changed, 56 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) {
diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt
index 2bf76c28b..dd2a90ba3 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -133,6 +133,26 @@ struct0 {
f2 int16
}
+type templ_base0[TYPE, CONST] {
+ f1 TYPE
+ f2 const[CONST, int32]
+}
+
+type templ_base1[TYPE, CONST] {
+ f2 const[CONST, int8]
+ f1 TYPE
+}
+
+type templ_templ[BASE, CONST] {
+ f1 BASE[int8, CONST]
+ f2 BASE[int32, 0]
+}
+
+templ_templ_use {
+ f1 templ_templ[templ_base0, 0]
+ f2 templ_templ[templ_base1, 1]
+}
+
type templ_struct2[A] templ_struct0[A, int8]
type templ_struct3 templ_struct2[C1]
type templ_struct4 templ_struct3
diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt
index 2be2e65ad..f4c9cf69a 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -260,6 +260,23 @@ type templ_struct2[A] {
f B ### unknown type B
}
+type templ_base0[TYPE] {
+ f1 TYPE
+}
+
+type templ_templ0[BASE] {
+ f1 BASE
+}
+
+type templ_templ1[BASE] {
+ f1 BASE[int16] ### both template parameter BASE and its usage have sub-arguments
+}
+
+templ_templ_use0 {
+ f1 templ_templ0[templ_base0] ### template templ_base0 needs 1 arguments instead of 0
+ f2 templ_templ1[templ_base0[int32]]
+}
+
foo$200(a templ0[42, int8])
foo$202(a templ0) ### template templ0 needs 2 arguments instead of 0
foo$203(a type0[42]) ### type type0 is not a template