ReadonlyNode
클래스, IR 분류
The read-only base of every value node: every literal, parameter, constRef and Let() binding is a ReadonlyNode.
import { ReadonlyNode } from 'typeshade'
시그니처, 설명, 예제는 커밋 c66579bf의 컴파일러 소스에서 그대로 가져온 영어 원문입니다.
구문
class ReadonlyNode<K extends string = string>예외
TypeShadeErrorSD0004from an arithmetic or comparison method whose two operands have incompatible types (vec3<f32>againstvec2<f32>, say). TheNode<K>phantom key catches most of these attsctime; this is the runtime check for an operand typedReadonlyNode<string>or built dynamically.
설명
The read-only base of every value node: every literal, parameter, constRef and Let()
binding is a ReadonlyNode. It carries the full chainable API, arithmetic (.add, .sub,
…), comparison, swizzles, .at() and .select(), and no .assign(); that method lives only
on the mutable Node subtype. Write a helper’s operand type as ReadonlyNode<K>
whenever the value is only read: it then accepts a Let, a parameter and a Var alike,
since Node is a subtype of this class.
생성자
new ReadonlyNode(readonly expr: Expr)
인스턴스 속성
__k선택 사항읽기 전용KPhantom type key. Optional and never assigned, so it carries
Kcovariantly at the type level (aNode<'vec3<f32>'>is not assignable where aNode<'vec2<f32>'>is wanted) at no runtime cost. It is a plain optional field and must stay one: Babel’s TypeScript transform rejectsdeclareclass fields.type읽기 전용ShaderTypex읽기 전용Node<ElemKey<K>>y읽기 전용Node<ElemKey<K>>z읽기 전용Node<ElemKey<K>>w읽기 전용Node<ElemKey<K>>r읽기 전용Node<ElemKey<K>>g읽기 전용Node<ElemKey<K>>b읽기 전용Node<ElemKey<K>>a읽기 전용Node<ElemKey<K>>rgb읽기 전용Node<SwizzleKey<K, 'rgb'>>xy읽기 전용Node<SwizzleKey<K, 'xy'>>xyz읽기 전용Node<SwizzleKey<K, 'xyz'>>zyx읽기 전용Node<SwizzleKey<K, 'zyx'>>zxy읽기 전용Node<SwizzleKey<K, 'zxy'>>yzx읽기 전용Node<SwizzleKey<K, 'yzx'>>bgr읽기 전용Node<SwizzleKey<K, 'bgr'>>bgra읽기 전용Node<SwizzleKey<K, 'bgra'>>
인스턴스 메서드
add<K2 extends `vec${number}<${K}>`>(this: ReadonlyNode<NonComposite<K>>, o: ReadonlyNode<K2>): Node<K2>add(this: ReadonlyNode<'f32'>, o: ReadonlyNode<'f64'>): Node<'f64'>add(o: ArithArg<K>): Node<K>add(o: NodeLike): Nodesub<K2 extends `vec${number}<${K}>`>(this: ReadonlyNode<NonComposite<K>>, o: ReadonlyNode<K2>): Node<K2>sub(this: ReadonlyNode<'f32'>, o: ReadonlyNode<'f64'>): Node<'f64'>sub(o: ArithArg<K>): Node<K>sub(o: NodeLike): Nodemul<K2 extends `vec${number}<${K}>`>(this: ReadonlyNode<NonComposite<K>>, o: ReadonlyNode<K2>): Node<K2>mul(this: ReadonlyNode<'f32'>, o: ReadonlyNode<'f64'>): Node<'f64'>mul(o: ArithArg<K>): Node<K>mul(o: NodeLike): Nodediv<K2 extends `vec${number}<${K}>`>(this: ReadonlyNode<NonComposite<K>>, o: ReadonlyNode<K2>): Node<K2>div(this: ReadonlyNode<'f32'>, o: ReadonlyNode<'f64'>): Node<'f64'>div(o: ArithArg<K>): Node<K>div(o: NodeLike): Nodemod<K2 extends `vec${number}<${K}>`>(this: ReadonlyNode<NonComposite<K>>, o: ReadonlyNode<K2>): Node<K2>mod(o: ArithArg<K>): Node<K>mod(o: NodeLike): Nodeneg(): Node<K>lt(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>gt(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>le(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>ge(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>eq(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>ne(this: ReadonlyNode<NonComposite<K>>, o: CmpArg<K>): Node<'bool'>and(o: ReadonlyNode<'bool'>): Node<'bool'>or(o: ReadonlyNode<'bool'>): Node<'bool'>not(this: ReadonlyNode<'bool'>): Node<'bool'>Logical negation, the
!of both targets. It completes the.and/.orset, which until now could say every boolean expression except the simplest one.The node it builds is
this == false, which is what the"use typeshade"compiler lowers a source-level!ato. That is the point: the two authoring surfaces meet in the IR, so a helper moved from one to the other keeps its emit. The emitted text is(a == false)rather than!a.bitAnd(o: ReadonlyNode<K & ('i32' | 'u32')> | number): Node<K>bitOr(o: ReadonlyNode<K & ('i32' | 'u32')> | number): Node<K>bitXor(o: ReadonlyNode<K & ('i32' | 'u32')> | number): Node<K>shl(o: ReadonlyNode<'u32'> | number): Node<K>shr(o: ReadonlyNode<'u32'> | number): Node<K>comp(field: 'x' | 'y' | 'z' | 'w'): Node<ElemKey<K>>Vector component access:
.x,.y,.zor.w, returning the element scalar.swizzle<S extends string>(comps: S): Node<SwizzleKey<K, S>>Vector swizzle:
.rgb,.xy,.a, and so on. One component gives a scalar;Ncomponents give avecNof the same element type. The result key is inferred from the components string, sov4.swizzle('yxz')isNode<'vec3<f32>'>for an f32 source and element-typed for u32 and i32 vectors too. The components are validated:xyzworrgba, one set per swizzle, each within the source’s component count.swizzle(comps: string): Nodef32(this: ReadonlyNode<NonComposite<K>>): Node<'f32'>Convert this scalar to
f32, the method form oftoF32. Emitsf32(x)on WGSL andfloat(x)on GLSL, and narrows an f64 exactly (the sum of its hi and lo halves).i32(this: ReadonlyNode<NonComposite<K>>): Node<'i32'>Convert this scalar to
i32, the method form oftoI32. Emitsi32(x)on WGSL andint(x)on GLSL.u32(this: ReadonlyNode<NonComposite<K>>): Node<'u32'>Convert this scalar to
u32, the method form oftoU32. Emitsu32(x)on WGSL anduint(x)on GLSL.f64(this: ReadonlyNode<'f32'>): Node<'f64'>Widen this f32 to the emulated double
f64, exactly — the result is the pair(x, 0.0). The method form oftoF64, and bounded to an f32 receiver for the same reason that is: no other scalar has an exact widening the fp64 lowering implements.at<T extends ShaderType>(idx: ReadonlyNode<ScalarKey> | number, elem: T): Node<KeyOf<T>>Array index,
base[idx]. A JS number index lifts to a u32 literal, since WGSL indices are integers.The element token is optional on an array-keyed node:
xs.at(i)reads the element from the array’s own key, so anarray<f32, 4>indexes toNode<'f32'>with nothing restated. It is the spelling astorageBufferhandle’s.at(i)already had, and the one the"use typeshade"surface’sxs[i]matches. Forgetting the token used to be a runtime TypeError rather than atscerror, since the elementShaderTypewas the only place the type came from.Pass the token for a node whose key does not carry the element — a widened
ReadonlyNode<string>, or a struct read the phantom key cannot see into.at(this: ReadonlyNode<`array<${string}>`>, idx: ReadonlyNode<ScalarKey> | number): Node<ArrayElemKey<K>>at(idx: ReadonlyNode<ScalarKey> | number, elem?: ShaderType): Nodeselect(this: ReadonlyNode<'bool'>, a: number, b: number): Node<'f32'>this ? a : b, valid only on a bool node (enforced through thethis:bound). Both branches must share a key. Emits WGSLselect(b, a, this).select<R extends string>(this: ReadonlyNode<'bool'>, a: ReadonlyNode<R> | number, b: ReadonlyNode<R> | number): Node<R>select<R extends string = 'f32'>(this: ReadonlyNode<'bool'>, a: ReadonlyNode<R> | number, b: ReadonlyNode<R> | number): Node<R>
함께 보기
소스
src/core/ir/node.ts, 346행, 커밋 c66579bf 기준