From a02da0106608841128c6f38a42bbe76346515b13 Mon Sep 17 00:00:00 2001 From: Vladimir Still Date: Sun, 15 Sep 2024 20:31:37 +0200 Subject: [PATCH 1/3] Add support for string concatenation Signed-off-by: Vladimir Still --- p4-16/spec/P4-16-spec.mdk | 52 +++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/p4-16/spec/P4-16-spec.mdk b/p4-16/spec/P4-16-spec.mdk index 24270a1be0..eb36a8ddb4 100644 --- a/p4-16/spec/P4-16-spec.mdk +++ b/p4-16/spec/P4-16-spec.mdk @@ -1304,8 +1304,8 @@ number of backslash characters (ASCII code 92). P4 does not make any validity checks on strings (i.e., it does not check that strings represent legal UTF-8 encodings). -Since P4 does not provide any operations on strings, -string literals are generally passed unchanged through the P4 compiler to +Since P4 does not allow strings to exist at runtime, string literals +are generally passed unchanged through the P4 compiler to other third-party tools or compiler-backends, including the terminating quotes. These tools can define their own handling of escape sequences (e.g., how to specify Unicode characters, or handle @@ -1906,13 +1906,18 @@ Operations on values of type `match_kind` are described in Section ### The Boolean type { #sec-bool-type } The Boolean type `bool` contains just two values, `false` and `true`. -Boolean values are not integers or bit-strings. +Boolean values are not integers or bit-strings. Operations that can +be performed on booleans are described in Section [#sec-bool-exprs]. ### Strings { #sec-string-type } -The type `string` represents strings. There are no operations on -string values; one cannot declare variables with a `string` type. -Parameters with type `string` can be only directionless (see Section +The type `string` represents strings. The values are either string +literals, or concatenations of multiple string literals. Operations +that can be performed on strings are described in Section +[#sec-string-ops]. + +One cannot declare variables with a `string` type. Parameters with +type `string` can be only directionless (see Section [#sec-calling-convention]). P4 does not support string manipulation in the dataplane; the `string` type is only allowed for describing compile-time known values (i.e., string literals, as discussed in @@ -3739,6 +3744,23 @@ finding this information in a section dedicated to type `varbit`. Additionally, the maximum size of a variable-length bit-string can be determined at compile-time (Section [#sec-minsizeinbits]). +## Operations on Strings { #sec-string-ops } + +The only operation allowed on strings is concatenation, denoted by +`++`. For string concatenation, both operands must be strings and +the result is also a string. String concatenation can be only +performed at compile time. + +~ Begin P4Example +extern void log(string message); + +void foo(int<8> v) { + // ... + log("my log message " ++ + "continuation of the log message"); +} +~ End P4Example + ## Casts { #sec-casts } P4 provides a limited set of casts between types. A cast is written @@ -8486,9 +8508,10 @@ table t { The `@name` annotation directs the compiler to use a different local name when generating the external APIs used to manipulate a -language element from the control plane. This annotation takes a string literal -body. In the -following example, the fully-qualified name of the table is `c_inst.t1`. +language element from the control plane. This annotation takes a local +compile-time know value of type `string` (typically a string literal). +In the followigng example, the fully-qualified name of the table is +`c_inst.t1`. ~ Begin P4Example control c( /* parameters omitted */ )() { @@ -8587,11 +8610,13 @@ absence), allowing architecture-independent analysis of P4 programs. The `deprecated` annotation has a required string argument that is a message that will be printed by a compiler when a program is using the -deprecated construct. This is mostly useful for annotating library -constructs, such as externs. +deprecated construct. This is mostly useful for annotating library +constructs, such as externs. The parameter needs to be local +compile-time known value of type `string`. ~ Begin P4Example -@deprecated("Please use the 'check' function instead") +#define DEPR_V1_2_2 "Deprecated in v1.2.2" +@deprecated("Please use the 'check' function instead." ++ DEPR_V1_2_2) extern Checker { /* body omitted */ } @@ -8602,7 +8627,8 @@ extern Checker { The `noWarn` annotation has a required string argument that indicates a compiler warning that will be inhibited. For example `@noWarn("unused")` on a declaration will prevent a compiler warning -if that declaration is not used. +if that declaration is not used. The parameter needs to be local +compile-time known value of type `string`. ## Target-specific annotations From 27fef741c9b77ca9334774c52532107cd940adb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C5=A0till?= Date: Mon, 9 Sep 2024 20:55:42 +0200 Subject: [PATCH 2/3] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Vladimír Štill --- p4-16/spec/P4-16-spec.mdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/p4-16/spec/P4-16-spec.mdk b/p4-16/spec/P4-16-spec.mdk index eb36a8ddb4..00505b6518 100644 --- a/p4-16/spec/P4-16-spec.mdk +++ b/p4-16/spec/P4-16-spec.mdk @@ -8510,7 +8510,7 @@ The `@name` annotation directs the compiler to use a different local name when generating the external APIs used to manipulate a language element from the control plane. This annotation takes a local compile-time know value of type `string` (typically a string literal). -In the followigng example, the fully-qualified name of the table is +In the following example, the fully-qualified name of the table is `c_inst.t1`. ~ Begin P4Example From 20e6cb4e53edeb95b9a2f562ec230e8bd2dfff0a Mon Sep 17 00:00:00 2001 From: Vladimir Still Date: Sun, 22 Sep 2024 20:33:08 +0200 Subject: [PATCH 3/3] Apply review suggestions Signed-off-by: Vladimir Still --- p4-16/spec/P4-16-spec.mdk | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/p4-16/spec/P4-16-spec.mdk b/p4-16/spec/P4-16-spec.mdk index 00505b6518..449258943f 100644 --- a/p4-16/spec/P4-16-spec.mdk +++ b/p4-16/spec/P4-16-spec.mdk @@ -1306,9 +1306,16 @@ represent legal UTF-8 encodings). Since P4 does not allow strings to exist at runtime, string literals are generally passed unchanged through the P4 compiler to -other third-party tools or compiler-backends, including the -terminating quotes. These tools can define their own handling of -escape sequences (e.g., how to specify Unicode characters, or handle +other third-party tools or compiler-backends. The compiler can, however, +perform compile-time concatenation (constant-folding) of concatenation +expressions into single literal. When such concatenation is performed, +the binary representation of the string literals (excluding the quotes) +is concatenated in the order they appears in the source code. There are +no escape sequences that would be treated specially when strings are +concatenated. + +The backends and other tools can define their own handling of escape +sequences (e.g., how to specify Unicode characters, or handle unprintable ASCII characters). Here are 3 examples of string literals: @@ -1319,6 +1326,16 @@ Here are 3 examples of string literals: line terminator" ~ End P4Example +Here is an example of concatenation expression and an equivalent string +literal: + +~ Begin P4Example +"one string \" with a quote inside;" ++ (" " ++ "another string") +// can be constant folded to +"one string \" with a quote inside; another string") +~ End P4Example + + ### Optional trailing commas { #sec-trailing-commas } The P4 grammar allows several kinds of comma-separated lists to end in @@ -1911,10 +1928,10 @@ be performed on booleans are described in Section [#sec-bool-exprs]. ### Strings { #sec-string-type } -The type `string` represents strings. The values are either string -literals, or concatenations of multiple string literals. Operations -that can be performed on strings are described in Section -[#sec-string-ops]. +The type `string` represents strings. The values of type `string` are +either string literals, or concatenations of multiple `string`-typed +expression. Operations that can be performed on strings are described in +Section [#sec-string-ops]. One cannot declare variables with a `string` type. Parameters with type `string` can be only directionless (see Section @@ -3748,7 +3765,7 @@ compile-time (Section [#sec-minsizeinbits]). The only operation allowed on strings is concatenation, denoted by `++`. For string concatenation, both operands must be strings and -the result is also a string. String concatenation can be only +the result is also a string. String concatenation can only be performed at compile time. ~ Begin P4Example @@ -8509,7 +8526,7 @@ table t { The `@name` annotation directs the compiler to use a different local name when generating the external APIs used to manipulate a language element from the control plane. This annotation takes a local -compile-time know value of type `string` (typically a string literal). +compile-time known value of type `string` (typically a string literal). In the following example, the fully-qualified name of the table is `c_inst.t1`. @@ -8611,7 +8628,7 @@ absence), allowing architecture-independent analysis of P4 programs. The `deprecated` annotation has a required string argument that is a message that will be printed by a compiler when a program is using the deprecated construct. This is mostly useful for annotating library -constructs, such as externs. The parameter needs to be local +constructs, such as externs. The parameter must be a local compile-time known value of type `string`. ~ Begin P4Example @@ -8627,7 +8644,7 @@ extern Checker { The `noWarn` annotation has a required string argument that indicates a compiler warning that will be inhibited. For example `@noWarn("unused")` on a declaration will prevent a compiler warning -if that declaration is not used. The parameter needs to be local +if that declaration is not used. The parameter must be a local compile-time known value of type `string`. ## Target-specific annotations