Feat: WIP terse code documentation
This commit is contained in:
@@ -15,6 +15,7 @@ enum Token {
|
||||
Word(String, SourceSpan),
|
||||
}
|
||||
|
||||
/// Compile Forth source text into an executable Op sequence.
|
||||
pub(super) fn compile_script(input: &str, dict: &Dictionary) -> Result<Vec<Op>, String> {
|
||||
let tokens = tokenize(input);
|
||||
compile(&tokens, dict)
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::sync::Arc;
|
||||
|
||||
use super::types::SourceSpan;
|
||||
|
||||
/// Single VM instruction produced by the compiler.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Op {
|
||||
PushInt(i64, Option<SourceSpan>),
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
//! Chord definitions as semitone interval arrays.
|
||||
|
||||
/// Named chord with its interval pattern.
|
||||
pub struct Chord {
|
||||
pub name: &'static str,
|
||||
pub intervals: &'static [i64],
|
||||
}
|
||||
|
||||
/// All built-in chord types.
|
||||
pub static CHORDS: &[Chord] = &[
|
||||
// Triads
|
||||
Chord {
|
||||
@@ -169,6 +173,7 @@ pub static CHORDS: &[Chord] = &[
|
||||
},
|
||||
];
|
||||
|
||||
/// Find a chord's intervals by name.
|
||||
pub fn lookup(name: &str) -> Option<&'static [i64]> {
|
||||
CHORDS.iter().find(|c| c.name == name).map(|c| c.intervals)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Music theory data — chord and scale lookup tables.
|
||||
|
||||
pub mod chords;
|
||||
mod scales;
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
//! Scale definitions as semitone offset arrays.
|
||||
|
||||
/// Named scale with its semitone pattern.
|
||||
pub struct Scale {
|
||||
pub name: &'static str,
|
||||
pub pattern: &'static [i64],
|
||||
}
|
||||
|
||||
/// All built-in scale types.
|
||||
pub static SCALES: &[Scale] = &[
|
||||
Scale {
|
||||
name: "major",
|
||||
@@ -125,6 +129,7 @@ pub static SCALES: &[Scale] = &[
|
||||
},
|
||||
];
|
||||
|
||||
/// Find a scale's pattern by name.
|
||||
pub fn lookup(name: &str) -> Option<&'static [i64]> {
|
||||
SCALES.iter().find(|s| s.name == name).map(|s| s.pattern)
|
||||
}
|
||||
|
||||
@@ -14,12 +14,14 @@ pub trait CcAccess: Send + Sync {
|
||||
fn get_cc(&self, device: usize, channel: usize, cc: usize) -> u8;
|
||||
}
|
||||
|
||||
/// Byte range in source text.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct SourceSpan {
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
}
|
||||
|
||||
/// Concrete value resolved from a nondeterministic op, used for trace annotations.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ResolvedValue {
|
||||
Int(i64),
|
||||
@@ -39,6 +41,7 @@ impl ResolvedValue {
|
||||
}
|
||||
}
|
||||
|
||||
/// Spans and resolved values collected during a single evaluation, used for UI highlighting.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ExecutionTrace {
|
||||
pub executed_spans: Vec<SourceSpan>,
|
||||
@@ -46,6 +49,7 @@ pub struct ExecutionTrace {
|
||||
pub resolved: Vec<(SourceSpan, ResolvedValue)>,
|
||||
}
|
||||
|
||||
/// Per-step sequencer state passed into the VM.
|
||||
pub struct StepContext<'a> {
|
||||
pub step: usize,
|
||||
pub beat: f64,
|
||||
@@ -72,13 +76,18 @@ impl StepContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Underlying map for user-defined variables.
|
||||
pub type VariablesMap = HashMap<String, Value>;
|
||||
/// Shared variable store, swapped atomically after each step.
|
||||
pub type Variables = Arc<ArcSwap<VariablesMap>>;
|
||||
/// Shared user-defined word dictionary.
|
||||
pub type Dictionary = Arc<Mutex<HashMap<String, Vec<Op>>>>;
|
||||
/// Shared random number generator.
|
||||
pub type Rng = Arc<Mutex<StdRng>>;
|
||||
pub type Stack = Mutex<Vec<Value>>;
|
||||
pub(super) type CmdSnapshot<'a> = (Option<&'a Value>, &'a [(&'static str, Value)]);
|
||||
|
||||
/// Stack value in the Forth VM.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Value {
|
||||
Int(i64, Option<SourceSpan>),
|
||||
|
||||
@@ -14,6 +14,7 @@ use super::types::{
|
||||
Value, Variables, VariablesMap,
|
||||
};
|
||||
|
||||
/// Forth VM instance. Holds the stack, variables, dictionary, and RNG.
|
||||
pub struct Forth {
|
||||
stack: Stack,
|
||||
vars: Variables,
|
||||
@@ -45,12 +46,14 @@ impl Forth {
|
||||
self.global_params.lock().clear();
|
||||
}
|
||||
|
||||
/// Evaluate a Forth script and return audio command strings.
|
||||
pub fn evaluate(&self, script: &str, ctx: &StepContext) -> Result<Vec<String>, String> {
|
||||
let (outputs, var_writes) = self.evaluate_impl(script, ctx, None)?;
|
||||
self.apply_var_writes(var_writes);
|
||||
Ok(outputs)
|
||||
}
|
||||
|
||||
/// Evaluate and collect an execution trace for UI highlighting.
|
||||
pub fn evaluate_with_trace(
|
||||
&self,
|
||||
script: &str,
|
||||
@@ -62,6 +65,7 @@ impl Forth {
|
||||
Ok(outputs)
|
||||
}
|
||||
|
||||
/// Evaluate and return both outputs and pending variable writes (without applying them).
|
||||
pub fn evaluate_raw(
|
||||
&self,
|
||||
script: &str,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Word-to-Op translation: maps Forth word names to compiled instructions.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::ops::Op;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{Word, WordCompile::*};
|
||||
//! Word metadata for core language primitives (stack, arithmetic, logic, variables, definitions).
|
||||
|
||||
// Stack, Arithmetic, Comparison, Logic, Control, Variables, Definitions
|
||||
use super::{Word, WordCompile::*};
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
// Stack manipulation
|
||||
Word {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{Word, WordCompile::*};
|
||||
//! Word metadata for audio effect parameters (filter, envelope, reverb, delay, lo-fi, stereo, mod FX).
|
||||
|
||||
// Filter, Envelope, Reverb, Delay, Lo-fi, Stereo, Mod FX
|
||||
use super::{Word, WordCompile::*};
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
// Envelope
|
||||
Word {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! MIDI word definitions: channel, CC, pitch bend, transport, and device routing.
|
||||
|
||||
use super::{Word, WordCompile::*};
|
||||
|
||||
// MIDI
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
Word {
|
||||
name: "chan",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//! Built-in word definitions and lookup for the Forth VM.
|
||||
|
||||
mod compile;
|
||||
mod core;
|
||||
mod effects;
|
||||
@@ -11,6 +13,7 @@ use std::sync::LazyLock;
|
||||
|
||||
pub(crate) use compile::compile_word;
|
||||
|
||||
/// How a word is compiled into ops.
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum WordCompile {
|
||||
Simple,
|
||||
@@ -19,6 +22,7 @@ pub enum WordCompile {
|
||||
Probability(f64),
|
||||
}
|
||||
|
||||
/// Metadata for a built-in Forth word.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Word {
|
||||
pub name: &'static str,
|
||||
@@ -31,6 +35,7 @@ pub struct Word {
|
||||
pub varargs: bool,
|
||||
}
|
||||
|
||||
/// All built-in words, aggregated from every category module.
|
||||
pub static WORDS: LazyLock<Vec<Word>> = LazyLock::new(|| {
|
||||
let mut words = Vec::new();
|
||||
words.extend_from_slice(self::core::WORDS);
|
||||
@@ -42,6 +47,7 @@ pub static WORDS: LazyLock<Vec<Word>> = LazyLock::new(|| {
|
||||
words
|
||||
});
|
||||
|
||||
/// Index mapping word names and aliases to their definitions.
|
||||
static WORD_MAP: LazyLock<HashMap<&'static str, &'static Word>> = LazyLock::new(|| {
|
||||
let mut map = HashMap::with_capacity(WORDS.len() * 2);
|
||||
for word in WORDS.iter() {
|
||||
@@ -53,6 +59,7 @@ static WORD_MAP: LazyLock<HashMap<&'static str, &'static Word>> = LazyLock::new(
|
||||
map
|
||||
});
|
||||
|
||||
/// Find a word by name or alias.
|
||||
pub fn lookup_word(name: &str) -> Option<&'static Word> {
|
||||
WORD_MAP.get(name).copied()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Word definitions for music theory, harmony, and chord construction.
|
||||
|
||||
use super::{Word, WordCompile::*};
|
||||
|
||||
// Music, Chord
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
// Music
|
||||
Word {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Word metadata for sequencing: probability, timing, context queries, generators.
|
||||
|
||||
use super::{Word, WordCompile::*};
|
||||
|
||||
// Time, Context, Probability, Generator, Desktop
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
// Probability
|
||||
Word {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Word metadata for sound commands, sample/oscillator params, FM, modulation, and LFO.
|
||||
|
||||
use super::{Word, WordCompile::*};
|
||||
|
||||
// Sound, Oscillator, Sample, Wavetable, FM, Modulation, LFO
|
||||
pub(super) const WORDS: &[Word] = &[
|
||||
// Sound
|
||||
Word {
|
||||
|
||||
Reference in New Issue
Block a user