Value Categories

Making it easier to work with shaders


Value Categories

Slang has two primary value categories:

  • An L-value has underlying mutable storage. Hence, an L-value can be on the left side of an assignment, and it can be used as an argument to an out/inout function parameter.
  • An R-value is a temporary or otherwise immutable value. It can only be used in contexts where a pure value is adequate. It cannot be used as an argument to an out/inout function parameter. An R-value is typically a result of a computation, a value passed as a copy, or a result of a function invocation.

The following expressions are L-values:

  1. Access to a mutable variable
  2. Access to an out/inout/__ref parameter
  3. Access to an in parameter that has been declared using the traditional variable declaration (C-style)
    • Note: the argument is still passed by value copy
  4. Pointer dereference when the pointer access type is Access.ReadWrite
  5. Access to a reference
  6. Access to a property when it has a setter accessor and the base is an L-value
  7. Applying a subscript operator when both:
    • The base is an L-value
    • The subscript operator is built-in, OR it is user-defined with a setter accessor
  8. Access to this in a mutating context
  9. Return value for a non-copyable return type
  10. Access to a member when the base is an L-value
  11. Swizzle expression when both:
    • The base is an L-value
    • The swizzle expression has no duplicate components
  12. Cast of an L-value object to a conforming type
  13. Access to an interface-typed mutable object (dynamic dispatch)
  14. Implicit casts that preserve the L-value category (e.g. for inout/out parameters)

Other expressions are R-value expressions.

Slang expressions are also categorized as addressable and non-addressable:

  • An addressable value has underlying storage that may be mutable, read-only, or immutable. Its address may be requested with __getAddress() on targets that support pointers.
  • A non-addressable value does not have underlying storage, and in that sense, it is a true temporary value.

📝 Remark: Pointer support in Slang is currently experimental. The details are subject to change.

Where L-values Are Required

L-values are required in the following places:

  • Argument to an out/inout/__ref parameter
  • Left-hand-side operand of an assignment operator, including compound assignment operators
  • Operand to pre-increment, pre-decrement, post-increment, and post-decrement operators
  • Object receiving a [mutating] or [ref] member function call
  • Object receiving a property setter call or a user-defined subscript operator setter call, unless the setter has been explicitly marked as [nonmutating].