diff --git a/p4-16/spec/P4-16-spec.adoc b/p4-16/spec/P4-16-spec.adoc index 37940fb20..e40a91246 100644 --- a/p4-16/spec/P4-16-spec.adoc +++ b/p4-16/spec/P4-16-spec.adoc @@ -1225,11 +1225,18 @@ 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 -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 +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. 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: @@ -1242,6 +1249,17 @@ Here are 3 examples of string literals: line terminator" ---- +Here is an example of concatenation expression and an equivalent string +literal: + +[source,p4] +---- +"one string \" with a quote inside;" ++ (" " ++ "another string") +// can be constant folded to +"one string \" with a quote inside; another string" +---- + + [#sec-trailing-commas] ==== Optional trailing commas @@ -1867,15 +1885,20 @@ Operations on values of type `match_kind` are described in ==== The Boolean 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-string-type] ==== Strings -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 -<>). +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 <>. + +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 @@ -3838,6 +3861,25 @@ 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 (<>). +[#sec-string-ops] +=== Operations on strings + +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 only be +performed at compile time. + +[source,p4] +---- +extern void log(string message); + +void foo(int<8> v) { + // ... + log("my log message " ++ + "continuation of the log message"); +} +---- + [#sec-casts] === Casts @@ -8892,9 +8934,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 known value of type `string` (typically a string literal). +In the following example, the fully-qualified name of the table is +`c_inst.t1`. [source,p4] ---- @@ -8997,12 +9040,14 @@ 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 must be a local +compile-time known value of type `string`. [source,p4] ---- -@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 */ } @@ -9014,7 +9059,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 must be a local +compile-time known value of type `string`. === Target-specific annotations