pkg/compiler: special BASE argument in templates
Signed-off-by: Paul Chaignon <paul.chaignon@orange.com>
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 24f0a13..7f12d74 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -204,7 +204,10 @@
} 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 @@
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 @@
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 90d4089..7df52dd 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -213,9 +213,9 @@
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_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$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 d7d8015..961de44 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -149,6 +149,7 @@
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 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 @@
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$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