Expr
Type in IR
Every expression shape the IR can hold: the closed set that Node and ReadonlyNode build and that the WGSL, GLSL and CPU backends walk to emit or evaluate.
import type { Expr } from 'typeshade'
The signature, the description and the examples come from the compiler's own source at commit 26de7be8.
Syntax
type Expr = | { readonly op: 'lit'; readonly type: ShaderType; readonly value: number | boolean } | { readonly op: 'constref'; readonly type: ShaderType; readonly name: string } | { readonly op: 'overrideref'; readonly type: ShaderType; readonly name: string } | { readonly op: 'externref'; readonly type: ShaderType; readonly name: string } | { readonly op: 'param'; readonly type: ShaderType; readonly name: string; /** Where this was written, when it is the TARGET of an assignment — the lvalue a * statement is about to write, so a debugger can highlight what changes rather than the * whole line. A read of the same name carries none in this increment. Read it with * {@link sourceSpanOf}. */ readonly span?: SourceSpan; } | { readonly op: 'varref'; readonly type: ShaderType; readonly name: string; /** Where this was written, when it is the TARGET of an assignment — the lvalue a * statement is about to write, so a debugger can highlight what changes rather than the * whole line. A read of the same name carries none in this increment. Read it with * {@link sourceSpanOf}. */ readonly span?: SourceSpan; } | { readonly op: 'binop'; readonly type: ShaderType; readonly bop: BinOp; readonly a: Expr; readonly b: Expr; } | { readonly op: 'unop'; readonly type: ShaderType; readonly a: Expr } | { readonly op: 'compare'; readonly type: ShaderType; readonly cop: CmpOp; readonly a: Expr; readonly b: Expr; } | { readonly op: 'logical'; readonly type: ShaderType; readonly lop: LogOp; readonly a: Expr; readonly b: Expr; } | { readonly op: 'call'; readonly type: ShaderType; readonly fn: string; readonly args: readonly Expr[]; readonly declRef?: FuncDecl; /** Where this call was written, when it is the outermost call node lowered from a * `ts.CallExpression`. Stepping into a helper has to tell two calls in one statement * apart, which is why this expression kind carries a span at all. A call the front end * synthesises while expanding one (the `random` hash, an array higher-order function, * a `Math.*` expansion, a numeric cast) carries none, because it was written nowhere. * Read it with {@link sourceSpanOf}. */ readonly span?: SourceSpan; /** On a `console.*` call whose author wrote a string literal among the arguments: every * argument in the order written, a string for a label and a number for the index of a * value in `args`. A label has no GPU representation and is never an `Expr`; it lives * here, on the host's side of the call (Rule 7.8, surface §66). Absent when every * argument is a value, which is then `args` in order. */ readonly labels?: readonly (string | number)[]; } | { readonly op: 'member'; readonly type: ShaderType; readonly base: Expr; readonly field: string; } | { readonly op: 'construct'; readonly type: ShaderType; readonly args: readonly Expr[] } | { readonly op: 'select'; readonly type: ShaderType; readonly cond: Expr; readonly ifTrue: Expr; readonly ifFalse: Expr; } | { readonly op: 'index'; readonly type: ShaderType; readonly base: Expr; readonly idx: Expr; /** Where this was written, when it is the TARGET of an assignment — the lvalue a * statement is about to write, so a debugger can highlight what changes rather than the * whole line. A read of the same name carries none in this increment. Read it with * {@link sourceSpanOf}. */ readonly span?: SourceSpan; } | { readonly op: 'matchExpr'; readonly type: ShaderType; readonly scrutinee: Expr; readonly cases: ReadonlyArray<readonly [number, Expr]>; readonly default: Expr; };Description
Every expression shape the IR can hold: the closed set that Node and
ReadonlyNode build and that the WGSL, GLSL and CPU backends walk to emit or
evaluate. It is a discriminated union on op with no methods, so a pass can
pattern-match it exhaustively (tsc reports a missing case in a backend’s switch) and
share subtrees freely. Every variant carries its own type: ShaderType: the IR is
fully typed when it is built, and a backend never re-infers a type while emitting. You
do not build these object literals by hand; the fluent methods on Node (.add(),
.mul(), …) and the free functions such as vec4 and mod fill in
type and validate the operands before the shape is constructed.
See also
Source
src/core/ir/nodes.ts, line 57, at commit 26de7be8