Syntax
Reference

References

References allow you to reuse values and can be used to create loops.

Multi-line Programs

When entering multi-line input in the interpreter, use :{ and :}. This is similar to Haskell's interpreter.

> :{
> 1 -> output
> 2 -> output
> :}
2
1
2
1.

Loading Programs from Files

Typing multiple lines in the interpreter repeatedly is sometimes troublesome. Flow allows loading programs from a file. Flow files are recommended to have the extension .~.

test.~
1 -> output
2 -> output

You can load the file using the :l command. This feature cannot be used in the browser; use a local runtime instead.

> :l test.~
1
2
1
2.

Basics of References

A reference acts like a "tunnel" node and is expressed as @ + name.

> :{
> 1 -> @a
> @a -> output
> :}
1.

References can send data to multiple downstream nodes. In this case, a reference acts like copy, sending upstream data to all downstream nodes.

> :{
> 1 -> @a
> @a + @a -> output
> :}
2.

References Cannot Have Multiple Upstreams

While references can have multiple downstream nodes, they cannot have multiple upstream nodes.

Note: This is similar to a wire in HDL. When synthesizing HDL such as Verilog, a wire assigned multiple times is called multi-driven, which is restricted for electrical reasons.

> :{
> 1 -> @a
> 2 -> @a
> :}
The ref a is multi-driven.

If you need multiple inputs, use a merge node. It has multiple upstream nodes and one downstream, sending all upstream data downstream.

> :{
> (1 ->) (2 ->) merge -> @a
> @a -> output
> :}
1
2
1
2.

Creating Loops with References

The following program continuously flows numbers while incrementing them:

> @a'0 -> trace -> + 1 -> @a
0
1
2
3
4
5
6.

Some new syntax appears here:

  • The '0 after @a specifies the initial data to send downstream. Without it, nothing would flow.
  • trace is similar to output but passes the upstream data downstream while displaying it. You could also write:
> @a'0 -> copy (-> output) (-> + 1 -> @a)

Practical Example: Calculating Factorial

Using loops, you can write recursive functions! Let's calculate a factorial.

We use an if node with two upstreams: one (condition) determines the condition, and the other (value) provides the data to send downstream (then or else). The then part works like a transistor with the condition.

> (2 ->:value) (1 == 1 ->:condition) if (then:-> output) (else:-> * 2 -> output)
2.

The following program calculates the factorial of a number specified by @x. It uses syntactic sugar extensively (explained in later chapters):

> :{
> 5 -> @x
> @next'1 * @current'1 -> @result
> @result -> if (@current'1 == @x) (then:-> output) (else:-> @next)
> @current'1 + 1 -> @current
> :}
120.

Without syntactic sugar, this is equivalent to:

> :{
> 5 -> @x
> (@next'1 ->) (@current'1 ->) * -> @result
> ((@current'1 ->) (@x ->) == ->:condition) (@result ->:value) if (then:-> output) (else:-> @next)
> (@current'1 ->) (1 ->) + -> @current
> :}
120.