@@ -75,19 +75,23 @@ The engine-supplied global values are:
7575- ` quantum ` - the beats per quantum (usually 4)
7676- ` delta ` - the difference between the current value of ` beat ` and the value
7777 at the last display frame
78- - ` time ` - the time that the current frame began execution (either the value
79- of the high-resolution Python ` perf_counter() ` timer or a counter beginning
80- at ` 0 ` and incrementing by exactly ` 1/fps ` on each frame in non-realtime
81- mode)
82- - ` clock ` - the current UTC time as a seconds-since-UNIX-epoch value
78+ - ` time ` - a monotonically increasing timer in seconds; in realtime mode this
79+ is the value of the high-resolution Python ` perf_counter() ` timer, in
80+ non-realtime mode it is a counter beginning at ` 0 ` on the first frame and
81+ incrementing by exactly ` 1/fps ` on each frame
82+ - ` clock ` - the current UTC time as a seconds-since-UNIX-epoch value; this
83+ value is not guaranteed to be monotonically increasing and will run fast
84+ from the program perspective in non-realtime mode
8385- ` frame ` - the current frame number, counting from 0 and increasing by one
84- for each rendered frame (this will increase by exactly 1 on each program
85- execution when running in non-realtime mode)
86- - ` fps ` - the current target frame-rate of the engine (the ` --fps ` option)
87- - ` performance ` - a value in the range [ 0.5 .. 2.0] that increases fractionally
88- if the engine has time to spare and decreases fractionally if it is missing
89- the target frame rate; this value can be multiplied into variable loads
90- in the code – e.g., number of things on screen – to maintain frame rate
86+ for each rendered frame
87+ - ` fps ` - the current target frame-rate of the engine (either set with the
88+ ` --fps ` option or ` %pragma fps ` )
89+ - ` performance ` - a value in the range $[ 0.5 .. 2.0] $ that increases
90+ fractionally if the engine has time to spare and decreases fractionally if
91+ it is missing the target frame rate; this value can be multiplied into
92+ variable loads in the code – e.g., number of things on screen – to
93+ dynamically increase or reduce the complexity of the scene to match the
94+ target frame rate; in non-realtime mode this value is always ` 2.0 ` .
9195- ` realtime ` - a ` true ` /` false ` value indicating whether the engine is running
9296 in realtime mode (the default) or not (with the ` --lockstep ` option)
9397- ` run_time ` - the number of seconds that the engine will run for before
@@ -148,21 +152,21 @@ general-purpose formatting and so `"Number ";1` is also a valid string.
148152` nan `
149153: The IEEE-754 floating-point "not a number" value
150154
151- ### SI Prefixes
155+ ### SI Metric Multipliers ###
152156
153- ** Flitter** supports adding an SI prefix to the end of a number. This is
154- confusing terminology, but an SI prefix is a prefix to a units suffix.
155- ** Flitter** does * not* support units, so you just end up with the SI prefix
156- as a suffix. (Confused yet?)
157+ ** Flitter** supports adding an SI metric multiplier prefix to the end of a
158+ number. This is slightly confusing terminology, but an SI metric prefix is a
159+ prefix to an SI units suffix. As ** Flitter** does * not* support units, you just
160+ end up with the bare SI multiplier as a suffix.
157161
158- The allowed SI prefixes are:
162+ The supported SI multipliers are:
159163
160164- ` T ` – $\times 10^{12}$
161165- ` G ` – $\times 10^{9}$
162166- ` M ` – $\times 10^{6}$
163167- ` k ` – $\times 10^{3}$
164168- ` m ` – $\times 10^{-3}$
165- - ` u ` – $\times 10^{-6}$ (also ` µ ` )
169+ - ` u ` – $\times 10^{-6}$ (also the Unicode ` µ ` symbol )
166170- ` n ` – $\times 10^{-9}$
167171- ` p ` – $\times 10^{-12}$
168172
@@ -242,8 +246,8 @@ has been used, then a symbol *cannot* be used to retrieve the value.
242246### Time codes
243247
244248In addition to normal literal numbers, as described above, ** Flitter** supports
245- literal * time codes* , which are given as a sequence of hours, minutes and
246- seconds separated with colon characters (` : ` ), with the hours being optional
249+ literal * time codes* , which are given as a sequence of integer hours, minutes
250+ and seconds separated with colon characters (` : ` ), with the hours being optional
247251and the seconds having an optional decimal fraction. For example:
248252
249253``` flitter
@@ -253,8 +257,9 @@ and the seconds having an optional decimal fraction. For example:
253257Time codes are converted by the parser into a single-item numeric vector
254258representing the total number of seconds (* 125.3* in the example above).
255259The hours component may be an arbitrarily large integer value, the minutes
256- and seconds must be in the range * [ 0,60)* . Time codes may not be combined with
257- exponents or SI prefixes, and do not support ` _ ` separators.
260+ and seconds must be in the range * [ 0,60)* . Leading zeroes are optional. Time
261+ codes may not be combined with exponents or [ SI
262+ multipliers] ( #si-metric-multipliers ) , and do not support ` _ ` separators.
258263
259264### Nodes
260265
@@ -306,6 +311,84 @@ appended to a `!window` node, which is the final value of this expression.
306311Running this program as-is will result in a red window with the title "Hello
307312world!".
308313
314+ #### Inline append
315+
316+ Although the usual, and most readable, way to indicate appending child nodes
317+ to a parent node is through indentation, there is also an inline append
318+ operator: ` << ` . This can be used in ` let ` bindings, arguments to function
319+ calls, and within parentheses.
320+
321+ For example:
322+
323+ ``` flitter
324+ let tree = !a << !b << !c
325+ ```
326+
327+ binds ` tree ` to an ` !a ` node containing a ` !b ` node containing a ` !c ` node
328+ (see [ Sequence lets] ( #sequence-let ) below for an alternative, probably more
329+ readable, way of achieving this).
330+
331+ Note that the ` << ` operator evaluates to the * parent* node. Therefore, the
332+ above example is equivalent to:
333+
334+ ``` flitter
335+ let tree = !a << (!b << !c)
336+ ```
337+
338+ By contrast, the following:
339+
340+ ``` flitter
341+ let tree = (!a << !b) << !c
342+ ```
343+
344+ results in the ` !c ` node being appended to the ` !a ` node, and is therefore
345+ equivalent to:
346+
347+ ``` flitter
348+ let tree = !a << (!b; !c)
349+ ```
350+
351+ The inline append operator may also be combined with an indented append block
352+ to collapse chains of nested nodes. The indented block will be appended to the
353+ final node in the chain.
354+
355+ For example:
356+
357+ ``` flitter
358+ !window size=1920;1080
359+ !adjust tonemap=:aces
360+ !bloom radius=20
361+ !canvas3d
362+ !light color=1 direction=0;0;-1
363+ …
364+ ```
365+
366+ could be collapsed to:
367+
368+ ``` flitter
369+ !window size=1920;1080
370+ !adjust tonemap=:aces << !bloom radius=20
371+ !canvas3d
372+ !light color=1 direction=0;0;-1
373+ …
374+ ```
375+
376+ which removes one level of indentation and helps to make clear that the
377+ ` !adjust ` and ` !bloom ` nodes are a pair of chained filter operations between the
378+ 3D canvas and the window. This is particularly useful where three or more
379+ filters are used together and the indentation begins to become unhelpful.
380+
381+ While this example * could* be collapsed even further to:
382+
383+ ``` flitter
384+ !window size=1920;1080 << !adjust tonemap=:aces << !bloom radius=20 << !canvas3d
385+ !light color=1 direction=0;0;-1
386+ …
387+ ```
388+
389+ this is not recommended usage, as it begins to obscure the structure rather than
390+ clarifying it.
391+
309392#### Vector Node Operations
310393
311394As nodes are values, and thus vectors, tag unary-postfix operations,
@@ -586,6 +669,8 @@ ignored. If the vector is shorter, then the the additional names will be bound
586669to items wrapped around from the start again. If the vector is ` null ` then all
587670names will be bound to ` null ` .
588671
672+ ### Sequence let
673+
589674A let binding may also bind one or more names to the result of evaluating an
590675indented "body" sequence of expressions. For example:
591676
@@ -598,8 +683,9 @@ let foo=
598683A let binding of this form may only have one name (or semicolon-separated list
599684of names for an unpacked vector binding) followed by an ` = ` , a newline and then
600685an indented sequence of expressions. This * sequence let* may contain any
601- multi-line sequence expressions, the same as the body of a function or a loop.
602- This is particularly useful for binding nested node structures to a name.
686+ multi-line sequence expressions, the same as the body of a function. This
687+ includes [ conditionals] ( #conditionals ) and [ for loops] ( #for-loops ) , and is
688+ particularly useful for binding complex nested node structures to a name.
603689
604690If a semicolon-separated name list is provided in a sequence let, then the
605691names will be bound to values following the unpacking logic described above,
@@ -629,9 +715,9 @@ be bound within a non-sequence expression, e.g.:
629715!foo x=(x*x where x=10)
630716```
631717
632- It is good practice, although not always necessary, to surround ` where `
633- expressions with parentheses to make the scope clear. However, note that ` where `
634- has higher precedence than ` ; ` vector composition and so ` (x;x*x where x=10) ` is
718+ It is good practice – although not always necessary – to surround ` where `
719+ expressions with parentheses to make the scope clear. Note that ` where ` has
720+ higher precedence than ` ; ` vector composition and so ` (x;x*x where x=10) ` is
635721equivalent to ` x;(x*x where x=10) ` .
636722
637723## Sequences
0 commit comments