-
Notifications
You must be signed in to change notification settings - Fork 0
Language Basics
Flow is a statically-typed, interpreted language. Every variable has a type, statements are separated by newlines or semicolons, and comments use either Note: or //.
Flow accepts two comment styles. Both run from their marker to the end of the line:
Note: This is a comment
// This is also a comment
Int x = 5 Note: inline comment
Int y = 7 // inline comment
Note: must start at the beginning of a line's content. // works anywhere.
Variables are declared with a type annotation:
Int x = 5
Float pi = 3.14
String name = "Flow"
Bool active = true
A variable declared without an initializer takes a type-appropriate default (0, "", false, empty array, etc.):
Int count Note: count = 0
String message Note: message = ""
Bool flag Note: flag = false
Int[] nums Note: nums = []
Variables can be reassigned after declaration:
Int x = 10
x = 20
x = x + 5
(print (str x)) Note: prints 25
Statements are separated by newlines. Semicolons allow multiple statements on one line:
Int a = 1; Int b = 2; Int c = 3
(print (str a)); (print (str b)); (print (str c))
| Type | Description | Example |
|---|---|---|
Int |
32-bit integer | 42 |
Long |
64-bit integer | - |
Float |
32-bit float | 3.14 |
Double |
64-bit float | 3.14 |
String |
Text | "hello" |
Bool |
Boolean |
true, false
|
Number |
Arbitrary precision | - |
Flow supports implicit numeric widening:
Int → Long → Float → Double → Number
An Int can be used wherever a Double is expected, for example.
| Type | Description | Example |
|---|---|---|
Note |
Musical pitch |
C4, F4+ (F sharp) |
Chord |
Harmonic chord |
Cmaj7, Dm
|
Sequence |
Ordered bars | | C4 D4 E4 F4 | |
Bar |
Musical measure | - |
Section |
Named song part | section intro { ... } |
Song |
Arrangement | [intro verse chorus] |
Buffer |
Audio samples | - |
Semitone |
Pitch offset | +2st |
Cent |
Microtonal offset | +50c |
Millisecond |
Time in ms | 100ms |
Second |
Time in seconds | 2.5s |
Decibel |
Gain in dB | +6dB |
Beat |
Musical beat | - |
NoteValue |
Note duration | - |
TimeSignature |
Meter | - |
MusicalNote |
Note with duration | - |
Voice |
Positioned audio | - |
Track |
Voice collection | - |
Envelope |
Amplitude shape | - |
OscillatorState |
Running oscillator | - |
Notes use [A-G][octave][alteration]:
| Syntax | Meaning |
|---|---|
C4 |
C natural, octave 4 (middle C) |
C4+ |
C sharp, octave 4 |
C4- |
C flat, octave 4 |
C4++ |
C double sharp |
C4-- |
C double flat |
Chord-symbol accidentals use s and f instead (for example, Csmaj7, Bfm). See Chords and Harmony.
Arrays are typed collections:
use "@std"
Int[] nums = (list 1 2 3 4 5)
String[] names = (list "Alice" "Bob" "Charlie")
Array indexing uses @:
Int first = nums@0
Int second = nums@1
Plural type names are shorthand for arrays: Ints = Int[], Notes = Note[], etc.
See Collections for full array operations.
Int sum = 3 + 4 Note: 7
Int diff = 10 - 3 Note: 7
Int prod = 5 * 6 Note: 30
Int quot = 15 / 4 Note: 3 (integer division)
Flow has no negative number literal: write (sub 0 5) to get -5.
use "@std"
Int sum = (add 3 4)
Int diff = (sub 10 3)
Int prod = (mul 5 6)
Int quot = (div 15 4)
Comparisons are function calls:
use "@std"
Bool eq = (equals 5 5) Note: true
Bool lt = (lt 3 5) Note: true
Bool gt = (gt 10 5) Note: true
Bool lte = (lte 3 3) Note: true
Bool gte = (gte 5 3) Note: true
Bool seq = (sequals 5 5) Note: strict equals (types must match)
use "@std"
Bool a = (and true false) Note: false
Bool b = (or true false) Note: true
Bool c = (not true) Note: false
and and or support lazy evaluation with Lazy arguments for short-circuiting.
use "@std"
String greeting = (concat "Hello, " "World!")
For dynamic labels, prefer string interpolation: $"x is {x}".
if is a function that takes a boolean and two lazy expressions. You must wrap both branches with lazy ():
use "@std"
Int x = 10
Note: returning a value
String result = (if (gt x 5) lazy ("big") lazy ("small"))
(print result) Note: "big"
Note: side-effect branches
(if (gt x 5) lazy ((print "big")) lazy ((print "small")))
Without lazy, arguments are eagerly evaluated and the overload won't match.
Flow supports for and while loops with break and continue:
use "@std"
Int sum = 0
for Int n in (list 1 2 3 4 5) {
sum = sum + n
}
Int count = 0
while (lt count 5) {
count = count + 1
}
See Loops for the full reference.
lazy (expr) creates a deferred value (a thunk) that is not evaluated until forced with eval:
use "@std"
Lazy<Void> deferred = lazy ((print "hello"))
Note: nothing printed yet
(eval deferred) Note: now prints "hello"
if, and, and or accept Lazy parameters to enable short-circuit evaluation.
Prefix a string with $ and wrap expressions in { }:
use "@std"
Int x = 42
(print $"x is {x}") Note: x is 42
Int a = 3
Int b = 4
(print $"sum is {a + b}") Note: sum is 7
See String Interpolation for details.
Function type annotations use parenthesized arrow syntax:
(Int => Int) doubler = fn Int n => (mul n 2)
(Int, Int => Int) adder = fn Int a, Int b => (add a b)
(Void => Int) constant = fn => 42
Any type name ending in s refers to the array form: Ints = Int[], Strings = String[], Voids = Void[], Notes = Note[], etc.
Variables declared inside blocks (functions, musical context blocks, sections, loops) are scoped to that block. Inner scopes can access variables from outer scopes.
- Functions - Procedures and lambdas
-
Flow Operator - The
->pipe - Collections - Arrays and list operations
-
Loops -
for,while,break,continue -
String Interpolation -
$"..."syntax - Musical Context - Musical context blocks