Reads a block of loop source into a score.
iex> {:ok, score} = TuningFork.Part.Source.parse("part(bpm: 120) |> play(:c3, 1)")
iex> %TuningFork.Score{} = score
iex> TuningFork.Part.Source.parse("part(bpm: 120) |> nonsense(")
{:error, "missing terminator: )"}
Summary
Functions
The source compiled once into a function that gives a fresh score every time it is called.
Why source will not read, in one line, or nil when it reads.
The score source describes, or why it will not read.
What a loop may be written with, as lines of text.
Source a new, empty loop opens on: a four-beat drum part that plays as it stands.
Functions
@spec compile(String.t()) :: {:ok, (-> {:ok, TuningFork.Score.t()} | {:error, String.t()})} | {:error, String.t()}
The source compiled once into a function that gives a fresh score every time it is called.
iex> {:ok, body} = TuningFork.Part.Source.compile("part(bpm: 120) |> play(:c3, 1)")
iex> {:ok, %TuningFork.Score{}} = body.()Compile once and call the function as often as needed: each call evaluates the source
again, so TuningFork.Tick counters advance and TuningFork.State values are read as they
stand at that call. TuningFork.Stage calls it once per round.
The function returns {:ok, score} or {:error, message}; source that compiles can still
fail on a later call.
Why source will not read, in one line, or nil when it reads.
parse/1 said the other way round, for a caller that only wants to report.
@spec parse(String.t()) :: {:ok, TuningFork.Score.t()} | {:error, String.t()}
The score source describes, or why it will not read.
Returns {:ok, %TuningFork.Score{}} or {:error, message}, the message trimmed to one line
so it fits under the loop it belongs to. Empty source is an empty score rather than an error,
so a loop being written from scratch reports nothing until there is something to report.
@spec reference() :: [String.t()]
What a loop may be written with, as lines of text.
The vocabulary parse/1 evaluates against. TuningFork.LoopsApp.reference/0 puts the
terminal's keys around it; the Livebook board shows it behind ?.
@spec template() :: String.t()
Source a new, empty loop opens on: a four-beat drum part that plays as it stands.
iex> {:ok, score} = TuningFork.Part.Source.parse(TuningFork.Part.Source.template())
iex> TuningFork.Score.duration(score)
2.0What mix tuning_fork.loops gives a loop made with Ctrl+N, and what the Livebook board's
+ loop gives a new one.