From f922d4435a79739a2abfdd4100f3eec10a5ef41b Mon Sep 17 00:00:00 2001 From: Paul Chaignon Date: Fri, 25 Oct 2019 19:14:52 +0200 Subject: pkg/compiler: special BASE argument in templates Signed-off-by: Paul Chaignon --- pkg/compiler/check.go | 19 ++++++++++++++++++- pkg/compiler/testdata/all.txt | 10 +++++++--- pkg/compiler/testdata/errors.txt | 18 ++++++++++++++---- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 24f0a13be..7f12d74a5 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -204,7 +204,10 @@ func (comp *compiler) checkTypedefs() { } else { // For templates we only do basic checks of arguments. names := make(map[string]bool) - for _, arg := range n.Args { + for i, arg := range n.Args { + if arg.Name == "BASE" && i != len(n.Args)-1 { + comp.error(arg.Pos, "type argument BASE must be the last argument") + } if names[arg.Name] { comp.error(arg.Pos, "duplicate type argument %v", arg.Name) } @@ -869,6 +872,17 @@ func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlag return } typedef := comp.typedefs[typedefName] + // Handling optional BASE argument. + if len(typedef.Args) > 0 && typedef.Args[len(typedef.Args)-1].Name == "BASE" { + if flags&checkIsArg != 0 && len(t.Args) == len(typedef.Args)-1 { + t.Args = append(t.Args, &ast.Type{ + Pos: t.Pos, + Ident: "intptr", + }) + } else if len(t.Args) == len(typedef.Args) { + comp.checkTypeArg(t, t.Args[len(t.Args)-1], typeArgBase) + } + } fullTypeName := ast.SerializeNode(t) for i, prev := range ctx.instantiationStack { if prev == fullTypeName { @@ -891,6 +905,9 @@ func (comp *compiler) replaceTypedef(ctx *checkCtx, t *ast.Type, flags checkFlag if nargs == 0 { comp.error(t.Pos, "type %v is not a template", typedefName) } else { + if flags&checkIsArg != 0 && typedef.Args[len(typedef.Args)-1].Name == "BASE" { + nargs-- + } comp.error(t.Pos, "template %v needs %v arguments instead of %v", typedefName, nargs, len(t.Args)) } diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt index 90d408915..7df52dd2f 100644 --- a/pkg/compiler/testdata/all.txt +++ b/pkg/compiler/testdata/all.txt @@ -213,9 +213,9 @@ type templ_base1[TYPE, CONST] { f1 TYPE } -type templ_templ[BASE, CONST] { - f1 BASE[int8, CONST] - f2 BASE[int32, 0] +type templ_templ[TMPL, CONST] { + f1 TMPL[int8, CONST] + f2 TMPL[int32, 0] } templ_templ_use { @@ -230,6 +230,8 @@ type templ_struct5 templ_struct0[C1, templ_struct0[C2, int8]] type templ_struct6 templ_struct0[C1, templ_struct2[C2]] type templ_union union_with_templ_struct type templ_base3[BASE] BASE +type templ_base4[BASE] const[0, BASE] +type templ_base5[VAL, BASE] const[VAL, BASE] foo$templ0(a templ0[42, int8]) foo$templ1(a ptr[in, templ_struct0[C2, int8]]) @@ -241,6 +243,8 @@ foo$templ6(a ptr[in, templ_struct4]) foo$templ7(a ptr[in, templ_struct5], b ptr[in, templ_struct6], c ptr[in, templ_union], d ptr[in, type3]) foo$templ8(a ptr[in, templ_templ_use]) foo$templ9(a ptr[in, templ_base3[int64]]) +foo$templ10(a ptr[in, templ_base4[int8]]) +foo$templ11(a ptr[in, templ_base5[42, int8]]) # Structs. diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt index d7d80151a..961de44b1 100644 --- a/pkg/compiler/testdata/errors.txt +++ b/pkg/compiler/testdata/errors.txt @@ -149,6 +149,7 @@ s3 { f6 int32:32 f7 int32:33 ### bitfield of size 33 is too large for base type of size 32 f8 const[0, int32:C1] ### literal const bitfield sizes are not supported + f9 const[0] ### wrong number of arguments for type const, expect value, base type } [packed, align_4] s4 { @@ -282,6 +283,10 @@ type templ4[A, A] ptr[in, A] ### duplicate type argument A type templ5[abc] ptr[in, abc] ### type argument abc must be ALL_CAPS type templ6[T] ptr[in, T] type templ7 templ0[templ6, int8] +type templ8[BASE, A] BASE[A] ### type argument BASE must be the last argument +type templ9[BASE] BASE +type templ10[A] templ9[A] +type templ11[VAL, BASE] const[VAL, BASE] # Note: here 42 is stripped as base type, so const ends up without arguments. foo$201(a templ1[42]) ### wrong number of arguments for type const, expect value @@ -306,12 +311,12 @@ type templ_base0[TYPE] { f1 TYPE } -type templ_templ0[BASE] { - f1 BASE +type templ_templ0[B] { + f1 B } -type templ_templ1[BASE] { - f1 BASE[int16] ### both template parameter BASE and its usage have sub-arguments +type templ_templ1[B] { + f1 B[int16] ### both template parameter B and its usage have sub-arguments } templ_templ_use0 { @@ -325,6 +330,11 @@ foo$203(a type0[42]) ### type type0 is not a template foo$204(a ptr[in, templ_struct0[42, int8]]) foo$205(a ptr[in, templ_struct0[int8, int8]]) foo$207(a ptr[in, templ_struct2[1]]) ### template argument A is not used +foo$208(a ptr[in, templ9[string["foo"]]]) ### unexpected value string for base type argument of templ9 type, expect [int8 int16 int32 int64 int16be int32be int64be intptr] +foo$209(a ptr[in, templ10[templ0[42, int8]]]) ### unexpected value templ0 for base type argument of templ9 type, expect [int8 int16 int32 int64 int16be int32be int64be intptr] +foo$210(a ptr[in, templ11[0, 1, int8]]) ### template templ11 needs 2 arguments instead of 3 +foo$211(a ptr[in, templ9]) ### template templ9 needs 1 arguments instead of 0 +foo$212(a ptr[in, templ11[1]]) ### template templ11 needs 2 arguments instead of 1 # fmt -- cgit mrf-deployment