Rule 7.2
Chapter 7, Expressions and statements Test
Where TypeShade lowers a TypeScript form to a WGSL form, the mapping must be a rule with a recorded divergence; the mappings today are:
| TypeScript form | WGSL form | Divergence recorded in |
|---|---|---|
| whole-value parameter reassignment | a fresh mutable local initialized from the immutable parameter; body reads and writes use that local | Rule 8.8; surface §14 and §52 |
c ? a : b on a scalar or vector | select(b, a, c), WGSL’s own argument order | surface §10; CHANGELOG.md (ternary as select); select |
c ? a : b on a struct or an array | an if with a temporary, since WGSL has no select over a composite | surface §31 (#113) |
a ** b | pow(a, b), float-only | surface §10 |
atan(y, x) | atan2(y, x) | surface §10 |
switch | WGSL’s switch, which never falls through; a trailing break is dropped | surface §14; Switch Statement |
x << n, x >> n | the amount is a u32; an i32 amount is cast (x << u32(n)), binary and compound alike | surface §14, §22 and §52; Bit Expressions |
[a, b] in a typed position | array<T, 2>(a, b) | surface §18 and §28 |
{ field: value } in a typed position | a struct constructor | surface §16 |
obj.method() | Cls_method(obj, …), dispatched statically | surface §26 |
o.x, o.x = v on an accessor | Cls_get_x(o), Cls_set_x(&o, v); o.x += v goes through both | Rule 8.11; surface §26 |
a private name #x | x, private through the front end’s check alone | Rule 8.12; surface §26 |
| a static field the file writes | a var<private> Cls_f, as a top-level let is | Rule 8.13; surface §26 |
| a call that writes, in an expression | a let ahead of it, in source order; an if for ?:, && and || | Rule 7.9; surface §26 |
v.setX(1.).setY(2.) as a statement | V_setX(&v, 1.0); V_setY(&v, 2.0);, each call on the chain’s root | Rule 8.10; surface §26 |
D.f() on a static D inherits | D_f, the base’s body lowered again with this as D | Rule 8.13; surface §26 |
const v = new V(); v.bump() | var v: V = V_new(); V_bump(&v);, a var from the first write through it | Rule 6.10; surface §26 |
f = (x: f32): f32 => … in a class | Cls_f, a method under the field’s name | Rule 8.16; surface §26 |
a local function that reads n of the function around it | fs_f(n, …): n is a parameter of fs_f, which every call passes | Rule 8.17; surface §14 |
a local function that writes n of the function around it | fs_f(&n, …), n: ptr<function, T> in fs_f (inout in GLSL ES 3.00) | Rule 8.17; surface §14 |
apply(sq, x), f a parameter of function type | apply_sq(x): apply once for each function its calls hand it | Rule 8.18; surface §14 |
s.each(sq), each a method that takes a function | Swarm_each_sq(s), and &s where a function handed over writes s, the one reference both use | Rules 8.10 and 8.18; surface §26 |
| an arrow function written as an argument | a local function of the calling body, typed by the parameter | Rule 8.18; surface §14 |
| a function, a method or an accessor with no return type | the type of its first return with a value, -> f32; none without one | Rule 8.19; surface §14 |
() => n += k with no return type | the assignment as a statement, and the function returns nothing, where TypeScript returns the new n | Rule 8.19; surface §14 |
return g(), g returning nothing | g(); return; | Rule 8.19; surface §14 |
const w = v, let w = v on a struct | a copy, where TypeScript shares one object; a write through either name is not seen through the other | Rule 6.10; surface §26 |
for (const x of a) over an array | a counted for over a’s indices, x a copy of a[i] read at the top of each trip | Rule 7.5; surface §17 |
xs.map(f) and the other methods of an array | a call of a function made for the array’s type and f, a counted for: array_map_sq(xs) | Rule 8.18; surface §63 |
the index an array’s method passes its function | an i32, where TypeScript passes a number | Rule 7.5; surface §63 |
the value of xs.map(f) | an array<R, N> value that a const holds a copy of, where TypeScript builds a new array object | Rule 6.10; surface §63 |
s += x in a loop of a kernel function the proof accepts | a fold in the tree order on every tier, where TypeScript adds in iteration order; an f32 or f64 sum or product may differ from that reading in the last places, and the determinism report lists it as order | Rule 8.22; surface §65; src/core/kernel-tree.ts |
a[k] += e into an integer array in such a loop | an atomic* on a[k] over array<atomic<T>>, the same bytes; exact in any order, where TypeScript adds in iteration order | Rule 8.22; surface §65 |
The rule text and the parts under it are the compiler's own English, as the design document writes them.
Rationale
a TypeScript reader expects the TypeScript meaning, so every place the two languages differ has to be written down where the reader will look.
Derives from
the rows above.
How it is verified
Checked by a test. A test, a gate script or a CI workflow names this rule, and the traceability check fails when a file listed below stops naming it.
Where the rule says the compiler enforces it:
the emit goldens and the tests each row’s surface section names; the tree order of a kernel function’s reduction by src/core/kernel-tree.test.ts on the CPU backends, and by the import journey on WebGPU.
The files that verify it at commit 26de7be8, each at the first line that names the rule:
Explained in
The sections of the surface document that explain this rule, at commit 26de7be8:
- §10 Builtins, casts and
discard - §14 TypeScript shapes the parser already had
- §16 Object literals take the declared struct
- §17 What a
forloop may say, and what it is told - §18 A list as an array's initializer
- §26 Classes with methods, a constructor and static functions
- §31 A conditional on a struct or an array
- §38 What may differ by driver: the determinism report
- §63 An array's methods
- §65 A loop that runs as a kernel
See also
Source
The rule at commit 26de7be8:
docs/language-design.md:508(the design document)reqs/rules/RULE-0702.md(its traceability item)