yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Bruce Mitchenerdocs: Reduce typo count (#5671)c3557978c

master
12.9 KiB353 linesraw

Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate.

Expressions

Expressions are terms that can be evaluated to produce values. This section provides a list of the kinds of expressions that may be used in a Slang program.

In general, the order of evaluation of a Slang expression proceeds from left to right. Where specific expressions do not follow this order of evaluation, it will be noted.

Some expressions can yield l-values, which allows them to be used on the left-hand-side of assignment, or as arguments for out or in out parameters.

Literal Expressions

Literal expressions are never l-values.

Integer Literal Expressions

An integer literal expression consists of a single integer literal token:

123

An unsuffixed integer literal expression always has type int.

Floating-Point Literal Expressions

A floating-point literal expression consists of a single floating-point literal token:

1.23

A unsuffixed floating-point literal expression always has type float.

Boolean Literal Expressions

Boolean literal expressions use the keywords true and false.

String Literal Expressions

A string literal expressions consists of one or more string literal tokens in a row:

"This" "is one" "string"

Identifier Expression

An identifier expression consists of a single identifier:

someName

When evaluated, this expression looks up someName in the environment of the expression and yields the value of a declaration with a matching name.

An identifier expression is an l-value if the declaration it refers to is mutable.

Overloading

It is possible for an identifier expression to be overloaded, such that it refers to one or more candidate declarations with the same name. If the expression appears in a context where the correct declaration to use can be disambiguated, then that declaration is used as the result of the name expression; otherwise use of an overloaded name is an error at the use site.

Implicit Lookup

It is possible for a name expression to refer to nested declarations in two ways:

  • In the body of a method, a reference to someName may resolve to this.someName, using the implicit this parameter of the method

  • When a global-scope cbuffer or tbuffer declaration is used, someName may refer to a field declared inside the cbuffer or tbuffer

Member Expression

A member expression consists of a base expression followed by a dot (.) and an identifier naming a member to be accessed:

base.m

When base is a structure type, this expression looks up the field or other member named by m. Just as for an identifier expression, the result of a member expression may be overloaded, and might be disambiguated based on how it is used.

A member expression is an l-value if the base expression is an l-value and the member it refers to is mutable.

Implicit Dereference

If the base expression of a member reference is a pointer-like type such as ConstantBuffer<T>, then a member reference expression will implicitly dereference the base expression to refer to the pointed-to value (e.g., in the case of ConstantBuffer<T> this is the buffer contents of type T).

Vector Swizzles

When the base expression of a member expression is of a vector type vector<T,N> then a member expression is a vector swizzle expression. The member name must conform to these constraints:

  • The member name must comprise between one and four ASCII characters
  • The characters must be come either from the set (x, y, z, w) or (r, g, b, a), corresponding to element indics of (0, 1, 2, 3)
  • The element index corresponding to each character must be less than N

If the member name of a swizzle consists of a single character, then the expression has type T and is equivalent to a subscript expression with the corresponding element index.

If the member name of a swizzle consists of M characters, then the result is a vector<T,M> built from the elements of the base vector with the corresponding indices.

A vector swizzle expression is an l-value if the base expression was an l-value and the list of indices corresponding to the characters of the member name contains no duplicates.

Matrix Swizzles

Note: The Slang implementation currently doesn't support matrix swizzles.

Static Member Expressions

When the base expression of a member expression is a type instead of a value, the result is a static member expression. A static member expression can refer to a static field or static method of a structure type. A static member expression can also refer to a case of an enumeration type.

A static member expression (but not a member expression in general) may use the token :: instead of . to separate the base and member name:

// These are equivalent
Color.Red
Color::Red

This Expression

A this expression consists of the keyword this and refers to the implicit instance of the enclosing type that is being operated on in instance methods, subscripts, and initializers.

The type of this is This.

Parenthesized Expression

An expression wrapped in parentheses () is a parenthesized expression and evaluates to the same value as the wrapped expression.

Call Expression

A call expression consists of a base expression and a list of argument expressions, separated by commas and enclosed in ():

myFunction( 1.0f, 20 )

When the base expression (e.g., myFunction) is overloaded, a call expression can disambiguate the overloaded expression based on the number and type or arguments present.

The base expression of a call may be a member reference expression:

myObject.myFunc( 1.0f )

In this case the base expression of the member reference (e.g., myObject in this case) is used as the argument for the implicit this parameter of the callee.

Mutability

If a [mutating] instance is being called, the argument for the implicit this parameter must be an l-value.

The argument expressions corresponding to any out or in out parameters of the callee must be l-values.

A call expression is never an l-value.

Initializer Expressions

When the base expression of a call is a type instead of a value, the expression is an initializer expression:

float2(1.0f, 2.0f)

An initializer expression initialized an instance of the specified type using the given arguments.

An initializer expression with only a single argument is treated as a cast expression:

// these are equivalent
int(1.0f)
(int) 1.0f

Subscript Expression

A subscript expression consists of a base expression and a list of argument expressions, separated by commas and enclosed in []:

myVector[someIndex]

A subscript expression invokes one of the subscript declarations in the type of the base expression. Which subscript declaration is invoked is resolved based on the number and types of the arguments.

A subscript expression is an l-value if the base expression is an l-value and if the subscript declaration it refers to has a setter or by-reference accessor.

Subscripts may be formed on the built-in vector, matrix, and array types.

Initializer List Expression

An initializer list expression comprises zero or more expressions, separated by commas, enclosed in {}:

{ 1, "hello", 2.0f }

An initialier list expression may only be used directly as the initial-value expression of a variable or parameter declaration; initializer lists are not allowed as arbitrary sub-expressions.

Note: This section will need to be updated with the detailed rules for how expressions in the initializer list are used to initialize values of each kind of type.

Cast Expression

A cast expression attempt to coerce a single value (the base expression) to a desired type (the target type):

(int) 1.0f

A cast expression can perform both built-in type conversions and invoke any single-argument initializers of the target type.

Compatibility Feature

As a compatibility feature for older code, Slang supports using a cast where the base expression is an integer literal zero and the target type is a user-defined structure type:

MyStruct s = (MyStruct) 0;

The semantics of such a cast are equivalent to initialization from an empty initializer list:

MyStruct s = {};

Assignment Expression

An assignment expression consists of a left-hand side expression, an equals sign (=), and a right-hand-side expressions:

myVar = someValue

The semantics of an assignment expression are to:

  • Evaluate the left-hand side to produce an l-value,
  • Evaluate the right-hand side to produce a value
  • Store the value of the right-hand side to the l-value of the left-hand side
  • Yield the l-value of the left-hand-side

Operator Expressions

Prefix Operator Expressions

The following prefix operators are supported:

OperatorDescription
+identity
-arithmetic negation
~bit-wise Boolean negation
!Boolean negation
++increment in place
--decrement in place

A prefix operator expression like +val is equivalent to a call expression to a function of the matching name operator+(val), except that lookup for the function only considers functions marked with the __prefix keyword.

The built-in prefix ++ and -- operators require that their operand is an l-value, and work as follows:

  • Evaluate the operand to produce an l-value
  • Read from the l-value to yield an old value
  • Increment or decrement the value to yield a new value
  • Write the new value to the l-value
  • Yield the new value

Postfix Operator Expressions

The following postfix operators are supported:

OperatorDescription
++increment in place
--decrement in place

A postfix operator expression like val++ is equivalent to a call expression to a function of the matching name operator++(val), except that lookup for the function only considers functions marked with the __postfix keyword.

The built-in prefix ++ and -- operators require that their operand is an l-value, and work as follows:

  • Evaluate the operand to produce an l-value
  • Read from the l-value to yield an old value
  • Increment or decrement the value to yield a new value
  • Write the new value to the l-value
  • Yield the old value

Infix Operator Expressions

The follow infix binary operators are supported:

OperatorKindDescription
*Multiplicativemultiplication
/Multiplicativedivision
%Multiplicativeremainder of division
+Additiveaddition
-Additivesubtraction
<<Shiftleft shift
>>Shiftright shift
<Relationalless than
>Relationalgreater than
<=Relationalless than or equal to
>=Relationalgreater than or equal to
==Equalityequal to
!=Equalitynot equal to
&BitAndbitwise and
^BitXorbitwise exclusive or
|BitOrbitwise or
&&Andlogical and
||Orlogical or
+=Assignmentcompound add/assign
-=Assignmentcompound subtract/assign
*=Assignmentcompound multiply/assign
/=Assignmentcompound divide/assign
%=Assignmentcompound remainder/assign
<<=Assignmentcompound left shift/assign
>>=Assignmentcompound right shift/assign
&=Assignmentcompound bitwise and/assign
|=Assignmentcompound bitwise or/assign
^=Assignmentcompound bitwise xor/assign
=Assignmentassignment
,Sequencingsequence

With the exception of the assignment operator (=), an infix operator expression like left + right is equivalent to a call expression to a function of the matching name operator+(left, right).

Conditional Expression

The conditional operator, ?:, is used to select between two expressions based on the value of a condition:

useNegative ? -1.0f : 1.0f

The condition may be either a single value of type bool, or a vector of bool. When a vector of bool is used, the two values being selected between must be vectors, and selection is performed component-wise.

Note: Unlike C, C++, GLSL, and most other C-family languages, Slang currently follows the precedent of HLSL where ?: does not short-circuit.

This decision may change (for the scalar case) in a future version of the language. Programmer are encouraged to write code that does not depend on whether or not ?: short-circuits.

1> Note: This document is a work in progress. It is both incomplete and, in many cases, inaccurate.
2
3Expressions
4===========
5
6Expressions are terms that can be _evaluated_ to produce values.
7This section provides a list of the kinds of expressions that may be used in a Slang program.
8
9In general, the order of evaluation of a Slang expression proceeds from left to right.
10Where specific expressions do not follow this order of evaluation, it will be noted.
11
12Some expressions can yield _l-values_, which allows them to be used on the left-hand-side of assignment, or as arguments for `out` or `in out` parameters.
13
14Literal Expressions
15-------------------
16
17Literal expressions are never l-values.
18
19### Integer Literal Expressions
20
21An integer literal expression consists of a single integer literal token:
22
23```hlsl
24123
25```
26
27An unsuffixed integer literal expression always has type `int`.
28
29### Floating-Point Literal Expressions
30
31A floating-point literal expression consists of a single floating-point literal token:
32
33```hlsl
341.23
35```
36
37A unsuffixed floating-point literal expression always has type `float`.
38
39### Boolean Literal Expressions
40
41Boolean literal expressions use the keywords `true` and `false`.
42
43### String Literal Expressions
44
45A string literal expressions consists of one or more string literal tokens in a row:
46
47```hlsl
48"This" "is one" "string"
49```
50
51Identifier Expression
52---------------------
53
54An _identifier expression_ consists of a single identifier:
55
56```hlsl
57someName
58```
59
60When evaluated, this expression looks up `someName` in the environment of the expression and yields the value of a declaration with a matching name.
61
62An identifier expression is an l-value if the declaration it refers to is mutable.
63
64### Overloading
65
66It is possible for an identifier expression to be _overloaded_, such that it refers to one or more candidate declarations with the same name.
67If the expression appears in a context where the correct declaration to use can be disambiguated, then that declaration is used as the result of  the name expression; otherwise use of an overloaded name is an error at the use site.
68
69### Implicit Lookup
70
71It is possible for a name expression to refer to nested declarations in two ways:
72
73* In the body of a method, a reference to `someName` may resolve to `this.someName`, using the implicit `this` parameter of the method
74
75* When a global-scope `cbuffer` or `tbuffer` declaration is used, `someName` may refer to a field declared inside the `cbuffer` or `tbuffer`
76
77Member Expression
78-----------------
79
80A _member expression_ consists of a base expression followed by a dot (`.`) and an identifier naming a member to be accessed:
81
82```hlsl
83base.m
84```
85
86When `base` is a structure type, this expression looks up the field or other member named by `m`.
87Just as for an identifier expression, the result of a member expression may be overloaded, and might be disambiguated based on how it is used.
88
89A member expression is an l-value if the base expression is an l-value and the member it refers to is mutable.
90
91### Implicit Dereference
92
93If the base expression of a member reference is a _pointer-like type_ such as `ConstantBuffer<T>`, then a member reference expression will implicitly dereference the base expression to refer to the pointed-to value (e.g., in the case of `ConstantBuffer<T>` this is the buffer contents of type `T`).
94
95### Vector Swizzles
96
97When the base expression of a member expression is of a vector type `vector<T,N>` then a member expression is a _vector swizzle expression_.
98The member name must conform to these constraints:
99
100* The member name must comprise between one and four ASCII characters
101* The characters must be come either from the set (`x`, `y`, `z`, `w`) or (`r`, `g`, `b`, `a`), corresponding to element indics of (0, 1, 2, 3)
102* The element index corresponding to each character must be less than `N`
103
104If the member name of a swizzle consists of a single character, then the expression has type `T` and is equivalent to a subscript expression with the corresponding element index.
105
106If the member name of a swizzle consists of `M` characters, then the result is a `vector<T,M>` built from the elements of the base vector with the corresponding indices.
107
108A vector swizzle expression is an l-value if the base expression was an l-value and the list of indices corresponding to the characters of the member name contains no duplicates.
109
110### Matrix Swizzles
111
112> Note: The Slang implementation currently doesn't support matrix swizzles.
113
114### Static Member Expressions
115
116When the base expression of a member expression is a type instead of a value, the result is a _static member expression_.
117A static member expression can refer to a static field or static method of a structure type.
118A static member expression can also refer to a case of an enumeration type.
119
120A static member expression (but not a member expression in general) may use the token `::` instead of `.` to separate the base and member name:
121
122```hlsl
123// These are equivalent
124Color.Red
125Color::Red
126```
127
128This Expression
129---------------
130
131A _this expression_ consists of the keyword `this` and refers to the implicit instance of the enclosing type that is being operated on in instance methods, subscripts, and initializers.
132
133The type of `this` is `This`.
134
135Parenthesized Expression
136----------------------
137
138An expression wrapped in parentheses `()` is a _parenthesized expression_ and evaluates to the same value as the wrapped expression.
139
140Call Expression
141---------------
142
143A _call expression_ consists of a base expression and a list of argument expressions, separated by commas and enclosed in `()`:
144
145```hlsl
146myFunction( 1.0f, 20 )
147```
148
149When the base expression (e.g., `myFunction`) is overloaded, a call expression can disambiguate the overloaded expression based on the number and type or arguments present.
150
151The base expression of a call may be a member reference expression:
152
153```hlsl
154myObject.myFunc( 1.0f )
155```
156
157In this case the base expression of the member reference (e.g., `myObject` in this case) is used as the argument for the implicit `this` parameter of the callee.
158
159### Mutability
160
161If a `[mutating]` instance is being called, the argument for the implicit `this` parameter must be an l-value.
162
163The argument expressions corresponding to any `out` or `in out` parameters of the callee must be l-values.
164
165A call expression is never an l-value.
166
167### Initializer Expressions
168
169When the base expression of a call is a type instead of a value, the expression is an initializer expression:
170
171```hlsl
172float2(1.0f, 2.0f)
173```
174
175An initializer expression initialized an instance of the specified type using the given arguments.
176
177An initializer expression with only a single argument is treated as a cast expression:
178
179```hlsl
180// these are equivalent
181int(1.0f)
182(int) 1.0f
183```
184
185Subscript Expression
186--------------------
187
188A _subscript expression_ consists of a base expression and a list of argument expressions, separated by commas and enclosed in `[]`:
189
190```hlsl
191myVector[someIndex]
192```
193
194A subscript expression invokes one of the subscript declarations in the type of the base expression. Which subscript declaration is invoked is resolved based on the number and types of the arguments.
195
196A subscript expression is an l-value if the base expression is an l-value and if the subscript declaration it refers to has a setter or by-reference accessor.
197
198Subscripts may be formed on the built-in vector, matrix, and array types.
199
200
201Initializer List Expression
202---------------------------
203
204An _initializer list expression_ comprises zero or more expressions, separated by commas, enclosed in `{}`:
205
206```
207{ 1, "hello", 2.0f }
208```
209
210An initialier list expression may only be used directly as the initial-value expression of a variable or parameter declaration; initializer lists are not allowed as arbitrary sub-expressions.
211
212> Note: This section will need to be updated with the detailed rules for how expressions in the initializer list are used to initialize values of each kind of type.
213
214Cast Expression
215---------------
216
217A _cast expression_ attempt to coerce a single value (the base expression) to a desired type (the target type):
218
219```hlsl
220(int) 1.0f
221```
222
223A cast expression can perform both built-in type conversions and invoke any single-argument initializers of the target type.
224
225### Compatibility Feature
226
227As a compatibility feature for older code, Slang supports using a cast where the base expression is an integer literal zero and the target type is a user-defined structure type:
228
229```hlsl
230MyStruct s = (MyStruct) 0;
231```
232
233The semantics of such a cast are equivalent to initialization from an empty initializer list:
234
235```hlsl
236MyStruct s = {};
237```
238
239Assignment Expression
240---------------------
241
242An _assignment expression_ consists of a left-hand side expression, an equals sign (`=`), and a right-hand-side expressions:
243
244```hlsl
245myVar = someValue
246```
247
248The semantics of an assignment expression are to:
249
250* Evaluate the left-hand side to produce an l-value,
251* Evaluate the right-hand side to produce a value
252* Store the value of the right-hand side to the l-value of the left-hand side
253* Yield the l-value of the left-hand-side
254
255Operator Expressions
256--------------------
257
258### Prefix Operator Expressions
259
260The following prefix operators are supported:
261
262| Operator 	| Description |
263|-----------|-------------|
264| `+`		| identity |
265| `-`		| arithmetic negation |
266| `~` 		| bit-wise Boolean negation |
267| `!`		| Boolean negation |
268| `++`		| increment in place |
269| `--`		| decrement in place |
270
271A prefix operator expression like `+val` is equivalent to a call expression to a function of the matching name `operator+(val)`, except that lookup for the function only considers functions marked with the `__prefix` keyword.
272
273The built-in prefix `++` and `--` operators require that their operand is an l-value, and work as follows:
274
275* Evaluate the operand to produce an l-value
276* Read from the l-value to yield an _old value_
277* Increment or decrement the value to yield a _new value_
278* Write the new value to the l-value
279* Yield the new value
280
281### Postfix Operator Expressions
282
283The following postfix operators are supported:
284
285| Operator 	| Description |
286|-----------|-------------|
287| `++`		| increment in place |
288| `--`		| decrement in place |
289
290A postfix operator expression like `val++` is equivalent to a call expression to a function of the matching name `operator++(val)`, except that lookup for the function only considers functions marked with the `__postfix` keyword.
291
292The built-in prefix `++` and `--` operators require that their operand is an l-value, and work as follows:
293
294* Evaluate the operand to produce an l-value
295* Read from the l-value to yield an _old value_
296* Increment or decrement the value to yield a _new value_
297* Write the new value to the l-value
298* Yield the old value
299
300### Infix Operator Expressions
301
302The follow infix binary operators are supported:
303
304| Operator 	| Kind        | Description |
305|-----------|-------------|-------------|
306| `*`		| Multiplicative 	| multiplication |
307| `/`		| Multiplicative 	| division |
308| `%`		| Multiplicative 	| remainder of division |
309| `+`		| Additive 			| addition |
310| `-`		| Additive 			| subtraction |
311| `<<`		| Shift 			| left shift |
312| `>>`		| Shift 			| right shift |
313| `<` 		| Relational 		| less than |
314| `>`		| Relational 		| greater than |
315| `<=`		| Relational 		| less than or equal to |
316| `>=`		| Relational 		| greater than or equal to |
317| `==`		| Equality 			| equal to |
318| `!=`		| Equality 			| not equal to |
319| `&`		| BitAnd 			| bitwise and |
320| `^`		| BitXor			| bitwise exclusive or |
321| `\|`		| BitOr 			| bitwise or |
322| `&&`		| And 				| logical and |
323| `\|\|`	| Or 				| logical or |
324| `+=`		| Assignment  		| compound add/assign |
325| `-=`      | Assignment  		| compound subtract/assign |
326| `*=`      | Assignment  		| compound multiply/assign |
327| `/=`      | Assignment  		| compound divide/assign |
328| `%=`      | Assignment  		| compound remainder/assign |
329| `<<=`     | Assignment  		| compound left shift/assign |
330| `>>=`     | Assignment  		| compound right shift/assign |
331| `&=`      | Assignment  		| compound bitwise and/assign |
332| `\|=`     | Assignment  		| compound bitwise or/assign |
333| `^=`      | Assignment  		| compound bitwise xor/assign |
334| `=`       | Assignment  		| assignment |
335| `,`		| Sequencing  		| sequence |
336
337With the exception of the assignment operator (`=`), an infix operator expression like `left + right` is equivalent to a call expression to a function of the matching name `operator+(left, right)`.
338
339### Conditional Expression
340
341The conditional operator, `?:`, is used to select between two expressions based on the value of a condition:
342
343```hlsl
344useNegative ? -1.0f : 1.0f
345```
346
347The condition may be either a single value of type `bool`, or a vector of `bool`.
348When a vector of `bool` is used, the two values being selected between must be vectors, and selection is performed component-wise.
349
350> Note: Unlike C, C++, GLSL, and most other C-family languages, Slang currently follows the precedent of HLSL where `?:` does not short-circuit.
351>
352> This decision may change (for the scalar case) in a future version of the language.
353> Programmer are encouraged to write code that does not depend on whether or not `?:` short-circuits.