cleaning
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
use cagire::forth::{Dictionary, EmissionCounter, Forth, Rng, StepContext, Value, Variables};
|
||||
use cagire::forth::{Dictionary, Forth, Rng, StepContext, Value, Variables};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@@ -46,14 +46,6 @@ pub fn forth_seeded(seed: u64) -> Forth {
|
||||
Forth::new(new_vars(), new_dict(), seeded_rng(seed))
|
||||
}
|
||||
|
||||
pub fn new_emission_counter() -> EmissionCounter {
|
||||
Arc::new(Mutex::new(0))
|
||||
}
|
||||
|
||||
pub fn forth_with_counter(counter: EmissionCounter) -> Forth {
|
||||
Forth::new_with_counter(new_vars(), new_dict(), seeded_rng(42), counter)
|
||||
}
|
||||
|
||||
pub fn run(script: &str) -> Forth {
|
||||
let f = forth();
|
||||
f.evaluate(script, &default_ctx()).unwrap();
|
||||
@@ -139,13 +131,3 @@ pub fn expect_outputs(script: &str, count: usize) -> Vec<String> {
|
||||
outputs
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn expect_output_contains(script: &str, substr: &str) {
|
||||
let outputs = expect_outputs(script, 1);
|
||||
assert!(
|
||||
outputs[0].contains(substr),
|
||||
"output '{}' does not contain '{}'",
|
||||
outputs[0],
|
||||
substr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use super::harness::*;
|
||||
#[allow(unused_imports)]
|
||||
use super::harness::{forth_with_counter, new_emission_counter};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn parse_params(output: &str) -> HashMap<String, f64> {
|
||||
@@ -245,51 +243,6 @@ fn dot_with_silence() {
|
||||
assert!(approx_eq(deltas[1], 2.0 * step));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_alternation_basic() {
|
||||
let outputs = expect_outputs(r#"| "kick" "snare" | s . . . ."#, 4);
|
||||
let sounds = get_sounds(&outputs);
|
||||
assert_eq!(sounds, vec!["kick", "snare", "kick", "snare"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_alternation_three_sounds() {
|
||||
let outputs = expect_outputs(r#"| "kick" "snare" "hat" | s . . . . . ."#, 6);
|
||||
let sounds = get_sounds(&outputs);
|
||||
assert_eq!(sounds, vec!["kick", "snare", "hat", "kick", "snare", "hat"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_alternation_single_item() {
|
||||
let outputs = expect_outputs(r#"| "kick" | s . . . ."#, 4);
|
||||
let sounds = get_sounds(&outputs);
|
||||
assert_eq!(sounds, vec!["kick", "kick", "kick", "kick"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_alternation_with_params() {
|
||||
let outputs = expect_outputs(r#"| 0.5 0.9 | gain "kick" s . ."#, 2);
|
||||
fn parse_gain(output: &str) -> f64 {
|
||||
let parts: Vec<&str> = output.trim_start_matches('/').split('/').collect();
|
||||
for i in 0..parts.len() - 1 {
|
||||
if parts[i] == "gain" {
|
||||
return parts[i + 1].parse().unwrap_or(0.0);
|
||||
}
|
||||
}
|
||||
0.0
|
||||
}
|
||||
let gains: Vec<f64> = outputs.iter().map(|o| parse_gain(o)).collect();
|
||||
assert!(approx_eq(gains[0], 0.5), "first gain should be 0.5, got {}", gains[0]);
|
||||
assert!(approx_eq(gains[1], 0.9), "second gain should be 0.9, got {}", gains[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_alternation_empty_error() {
|
||||
let f = forth();
|
||||
let result = f.evaluate(r#"| | . ."#, &default_ctx());
|
||||
assert!(result.is_err(), "empty internal cycle should error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn div_basic_subdivision() {
|
||||
let outputs = expect_outputs(r#"div "kick" s . "hat" s . ~"#, 2);
|
||||
@@ -355,40 +308,6 @@ fn unmatched_scope_terminator_error() {
|
||||
assert!(result.is_err(), "unmatched ~ should error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alternator_with_scale() {
|
||||
let outputs = expect_outputs(r#""sine" s | 0 1 2 3 | mixolydian note . . . ."#, 4);
|
||||
fn parse_note(output: &str) -> i64 {
|
||||
let parts: Vec<&str> = output.trim_start_matches('/').split('/').collect();
|
||||
for i in 0..parts.len() - 1 {
|
||||
if parts[i] == "note" {
|
||||
return parts[i + 1].parse().unwrap_or(0);
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
let notes: Vec<i64> = outputs.iter().map(|o| parse_note(o)).collect();
|
||||
// mixolydian from C4: 0->60, 1->62, 2->64, 3->65
|
||||
assert_eq!(notes, vec![60, 62, 64, 65]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alternator_with_arithmetic() {
|
||||
let outputs = expect_outputs(r#""sine" s | 100 200 | 2 * freq . ."#, 2);
|
||||
fn parse_freq(output: &str) -> f64 {
|
||||
let parts: Vec<&str> = output.trim_start_matches('/').split('/').collect();
|
||||
for i in 0..parts.len() - 1 {
|
||||
if parts[i] == "freq" {
|
||||
return parts[i + 1].parse().unwrap_or(0.0);
|
||||
}
|
||||
}
|
||||
0.0
|
||||
}
|
||||
let freqs: Vec<f64> = outputs.iter().map(|o| parse_freq(o)).collect();
|
||||
assert!(approx_eq(freqs[0], 200.0), "first freq: expected 200, got {}", freqs[0]);
|
||||
assert!(approx_eq(freqs[1], 400.0), "second freq: expected 400, got {}", freqs[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stack_superposes_sounds() {
|
||||
let outputs = expect_outputs(r#"stack "kick" s . "hat" s . ~"#, 2);
|
||||
@@ -452,13 +371,6 @@ fn emit_n_basic() {
|
||||
assert_eq!(sounds, vec!["kick", "kick", "kick", "kick"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_n_with_alternator() {
|
||||
let outputs = expect_outputs(r#"| "kick" "snare" | s 4 .!"#, 4);
|
||||
let sounds = get_sounds(&outputs);
|
||||
assert_eq!(sounds, vec!["kick", "snare", "kick", "snare"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_n_zero() {
|
||||
let outputs = expect_outputs(r#""kick" s 0 .!"#, 0);
|
||||
@@ -472,62 +384,3 @@ fn emit_n_negative_error() {
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persistent_counter_across_evaluations() {
|
||||
let counter = new_emission_counter();
|
||||
let ctx = default_ctx();
|
||||
|
||||
// First evaluation: kick, snare, kick, snare
|
||||
let f1 = forth_with_counter(counter.clone());
|
||||
let outputs1 = f1.evaluate(r#"| "kick" "snare" | s . ."#, &ctx).unwrap();
|
||||
let sounds1 = get_sounds(&outputs1);
|
||||
assert_eq!(sounds1, vec!["kick", "snare"]);
|
||||
|
||||
// Second evaluation: continues from where we left off
|
||||
let f2 = forth_with_counter(counter.clone());
|
||||
let outputs2 = f2.evaluate(r#"| "kick" "snare" | s . ."#, &ctx).unwrap();
|
||||
let sounds2 = get_sounds(&outputs2);
|
||||
assert_eq!(sounds2, vec!["kick", "snare"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn persistent_counter_three_item_cycle() {
|
||||
let counter = new_emission_counter();
|
||||
let ctx = default_ctx();
|
||||
|
||||
// First eval: kick, snare
|
||||
let f1 = forth_with_counter(counter.clone());
|
||||
let outputs1 = f1.evaluate(r#"| "kick" "snare" "hat" | s . ."#, &ctx).unwrap();
|
||||
let sounds1 = get_sounds(&outputs1);
|
||||
assert_eq!(sounds1, vec!["kick", "snare"]);
|
||||
|
||||
// Second eval: continues from hat (index 2)
|
||||
let f2 = forth_with_counter(counter.clone());
|
||||
let outputs2 = f2.evaluate(r#"| "kick" "snare" "hat" | s . ."#, &ctx).unwrap();
|
||||
let sounds2 = get_sounds(&outputs2);
|
||||
assert_eq!(sounds2, vec!["hat", "kick"]);
|
||||
|
||||
// Third eval: snare, hat
|
||||
let f3 = forth_with_counter(counter.clone());
|
||||
let outputs3 = f3.evaluate(r#"| "kick" "snare" "hat" | s . ."#, &ctx).unwrap();
|
||||
let sounds3 = get_sounds(&outputs3);
|
||||
assert_eq!(sounds3, vec!["snare", "hat"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_n_with_persistent_counter() {
|
||||
let counter = new_emission_counter();
|
||||
let ctx = default_ctx();
|
||||
|
||||
// First eval: 3 emits from a 4-item cycle
|
||||
let f1 = forth_with_counter(counter.clone());
|
||||
let outputs1 = f1.evaluate(r#"| "a" "b" "c" "d" | s 3 .!"#, &ctx).unwrap();
|
||||
let sounds1 = get_sounds(&outputs1);
|
||||
assert_eq!(sounds1, vec!["a", "b", "c"]);
|
||||
|
||||
// Second eval: continues from d
|
||||
let f2 = forth_with_counter(counter.clone());
|
||||
let outputs2 = f2.evaluate(r#"| "a" "b" "c" "d" | s 3 .!"#, &ctx).unwrap();
|
||||
let sounds2 = get_sounds(&outputs2);
|
||||
assert_eq!(sounds2, vec!["d", "a", "b"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user