Loop
On this page

Loop()

Function in Authoring

Author a C-style for loop over the innermost active scope.

import { Loop } from 'typeshade'

The signature, the description and the examples come from the compiler's own source at commit 26de7be8.

Syntax

function Loop(count: number, body: (i: Node<'u32'>) => ReadonlyNode | void): void;
function Loop(
name: string,
count: number,
body: (i: Node<'u32'>) => ReadonlyNode | void,
): void;
function Loop<K extends string>(
init: ReadonlyNode<K>,
cond: (i: Node<K>) => ReadonlyNode<'bool'>,
body: (i: Node<K>) => ReadonlyNode | void,
step?: ReadonlyNode<ScalarKey> | number,
): void;
function Loop<K extends string>(
name: string,
init: ReadonlyNode<K>,
cond: (i: Node<K>) => ReadonlyNode<'bool'>,
body: (i: Node<K>) => ReadonlyNode | void,
step?: ReadonlyNode<ScalarKey> | number,
): void;

Parameters

count number
body (i: Node<'u32'>) => ReadonlyNode | void

the loop body, receiving the counter.

name

the emitted counter identifier. Omit it and one is generated.

init

the counter’s initial value, which also fixes its type. A plain number is the trip count instead: the counter runs 0u up to it, and no cond is written.

cond

the continue test, receiving the counter. Omitted by the trip-count form.

step

the per-iteration increment. Defaults to +1.

Return value

void

Description

The counter starts at init, runs while cond holds, and advances by step after each iteration.

A fixed trip count is the short form: Loop(96, (i) => { ... }) is the whole loop, and emits the same for (var i = 0u; i < 96u; i = i + 1u) the three-part call spells out. Use it wherever the bound is a constant, which is most loops; reach for the three-part form when the counter starts somewhere other than zero, counts down, or is tested against something that is not a literal.

The leading name is optional and pins the emitted counter identifier; omit it and the builder generates one. step is optional too and defaults to +1, so an ascending loop passes nothing. The counter is a mutable node, since reassigning a loop variable is legal on both targets.

Both callbacks receive the counter: cond as (i) => i.lt(...), and the body as (i) => { ... }. Declaring the parameter on the condition and omitting it on the body is the mistake worth knowing. A body written () => { ... } that mentions i is still valid JavaScript closure syntax, so nothing is wrong at the call site, but i is not in scope: tsc reports Cannot find name 'i', and a transpile-only runner reports it while the module is being built, as while building fn '…': in Loop body: i is not defined.

Break and Continue are the loop terminators. For a loop whose only job is to fold a value, reduce returns the accumulator and needs no Var.

Examples

Example

import { Loop, toF32, u32 } from 'typeshade'
Loop(64, (i) => {
acc.assign(acc.add(toF32(i)))
})
// the same loop, spelled out
Loop(
u32(0),
(i) => i.lt(u32(64)),
(i) => {
acc.assign(acc.add(toF32(i)))
},
)

In the guide

See also

Source

src/core/ir/builder.ts, line 1864, at commit 26de7be8

Edit this page Report a problem