Skip to content

Commit

Permalink
Add support for binding the result of an indented sequence to a name
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanhogg committed Dec 27, 2024
1 parent 22a9ef7 commit 4d0d729
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 0 deletions.
19 changes: 19 additions & 0 deletions docs/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,25 @@ ignored. If the vector is shorter, then the the additional names will be bound
to items wrapped around from the start again. If the vector is `null` then all
names will be bound to `null`.

A let binding may also bind one or more names to the result of evaluating an
indented "body" sequence of expressions. For example:

```flitter
let foo=
!foo bar=12
!baz
```

A let binding of this form may only have one name (or semicolon-separated list
of names for an unpacked vector binding) followed by an `=`, a newline and then
an indented sequence of expressions. This *sequence let* may contain any
multi-line sequence expressions, the same as the body of a function or a loop.
This is particularly useful for binding nested node structures to a name.

If a semicolon-separated name list is provided in a sequence let, then the
names will be bound to values following the unpacking logic described above,
with the vector formed from the indented body being the source vector.

Names introduced with a `let` can redefine engine-supplied values, like `beat`,
and built-ins, like `sin`.

Expand Down
1 change: 1 addition & 0 deletions src/flitter/language/grammar.lark
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ sequence : expressions
expressions : expression* let_expression? -> tuple

let_expression : "let" multiline_bindings sequence -> let
| "let" name_list "=" _NL _INDENT sequence _DEDENT sequence -> sequence_let
| function sequence -> let_function
| "import" name_list "from" composition _NL sequence -> let_import

Expand Down
3 changes: 3 additions & 0 deletions src/flitter/language/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ def template_call(self, function, bindings, sequence):
def let_function(self, function, sequence):
return tree.Let((tree.PolyBinding((function.name,), function),), sequence)

def sequence_let(self, names, value, sequence):
return tree.Let((tree.PolyBinding(names, value),), sequence)

def anonymous_function(self, parameters, body):
return tree.Function('<anon>', parameters, body)

Expand Down
21 changes: 21 additions & 0 deletions tests/test_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,27 @@ def test_contains(self):
!foo x=1 y=1 z=0
""", x=Vector((4, 5, 6)), y=Vector.range(10))

def test_sequence_let(self):
self.assertCodeOutput(
"""
let foo;bar =
!foo x=1
!bar
!baz
!bar b=2
!frob
bar
foo
""",
"""
!frob
!bar b=2
!foo x=1
!bar
!baz
""")


class ScriptTest(utils.TestCase):
"""
Expand Down

0 comments on commit 4d0d729

Please sign in to comment.