Feat: optimizations

This commit is contained in:
2026-02-05 23:15:46 +01:00
parent 2c98a915fa
commit 51f52be4ce
22 changed files with 175 additions and 215 deletions

View File

@@ -45,7 +45,7 @@ fn tokenize(input: &str) -> Vec<Token> {
}
s.push(ch);
}
tokens.push(Token::Str(s, SourceSpan { start, end }));
tokens.push(Token::Str(s, SourceSpan { start: start as u32, end: end as u32 }));
continue;
}
@@ -66,8 +66,8 @@ fn tokenize(input: &str) -> Vec<Token> {
tokens.push(Token::Word(
";".to_string(),
SourceSpan {
start: pos,
end: pos + 1,
start: pos as u32,
end: (pos + 1) as u32,
},
));
continue;
@@ -85,7 +85,7 @@ fn tokenize(input: &str) -> Vec<Token> {
chars.next();
}
let span = SourceSpan { start, end };
let span = SourceSpan { start: start as u32, end: end as u32 };
// Normalize shorthand float syntax: .25 -> 0.25, -.5 -> -0.5
let word_to_parse = if word.starts_with('.')

View File

@@ -60,11 +60,11 @@ pub enum Op {
BranchIfZero(usize, Option<SourceSpan>, Option<SourceSpan>),
Branch(usize),
NewCmd,
SetParam(String),
SetParam(&'static str),
Emit,
Get,
Set,
GetContext(String),
GetContext(&'static str),
Rand,
ExpRand,
LogRand,

View File

@@ -14,8 +14,8 @@ pub trait CcAccess: Send + Sync {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct SourceSpan {
pub start: usize,
pub end: usize,
pub start: u32,
pub end: u32,
}
#[derive(Clone, Debug, Default)]
@@ -37,7 +37,7 @@ pub struct StepContext<'a> {
pub speed: f64,
pub fill: bool,
pub nudge_secs: f64,
pub cc_access: Option<Arc<dyn CcAccess>>,
pub cc_access: Option<&'a dyn CcAccess>,
pub speed_key: &'a str,
pub chain_key: &'a str,
#[cfg(feature = "desktop")]
@@ -58,8 +58,8 @@ pub type VariablesMap = HashMap<String, Value>;
pub type Variables = Arc<ArcSwap<VariablesMap>>;
pub type Dictionary = Arc<Mutex<HashMap<String, Vec<Op>>>>;
pub type Rng = Arc<Mutex<StdRng>>;
pub type Stack = Arc<Mutex<Vec<Value>>>;
pub(super) type CmdSnapshot<'a> = (Option<&'a Value>, &'a [(String, Value)]);
pub type Stack = Mutex<Vec<Value>>;
pub(super) type CmdSnapshot<'a> = (Option<&'a Value>, &'a [(&'static str, Value)]);
#[derive(Clone, Debug)]
pub enum Value {
@@ -138,7 +138,7 @@ impl Value {
#[derive(Clone, Debug, Default)]
pub(super) struct CmdRegister {
sound: Option<Value>,
params: Vec<(String, Value)>,
params: Vec<(&'static str, Value)>,
deltas: Vec<Value>,
}
@@ -155,7 +155,7 @@ impl CmdRegister {
self.sound = Some(val);
}
pub(super) fn set_param(&mut self, key: String, val: Value) {
pub(super) fn set_param(&mut self, key: &'static str, val: Value) {
self.params.push((key, val));
}
@@ -171,7 +171,7 @@ impl CmdRegister {
self.sound.as_ref()
}
pub(super) fn params(&self) -> &[(String, Value)] {
pub(super) fn params(&self) -> &[(&'static str, Value)] {
&self.params
}

View File

@@ -22,7 +22,7 @@ pub struct Forth {
impl Forth {
pub fn new(vars: Variables, dict: Dictionary, rng: Rng) -> Self {
Self {
stack: Arc::new(Mutex::new(Vec::new())),
stack: Mutex::new(Vec::new()),
vars,
dict,
rng,
@@ -227,7 +227,7 @@ impl Forth {
Some(v) => Some(v.as_str()?.to_string()),
None => None,
};
let resolved_params: Vec<(String, String)> = params
let resolved_params: Vec<(&str, String)> = params
.iter()
.map(|(k, v)| {
let resolved = resolve_cycling(v, emit_idx);
@@ -238,7 +238,7 @@ impl Forth {
}
}
}
(k.clone(), resolved.to_param_string())
(*k, resolved.to_param_string())
})
.collect();
emit_output(
@@ -555,7 +555,7 @@ impl Forth {
} else {
Value::CycleList(Arc::from(values))
};
cmd.set_param(param.clone(), val);
cmd.set_param(param, val);
}
Op::Emit => {
@@ -613,7 +613,7 @@ impl Forth {
}
Op::GetContext(name) => {
let val = match name.as_str() {
let val = match *name {
"step" => Value::Int(ctx.step as i64, None),
"beat" => Value::Float(ctx.beat, None),
"bank" => Value::Int(ctx.bank as i64, None),
@@ -879,8 +879,8 @@ impl Forth {
return Err("tempo and speed must be non-zero".into());
}
let dur = beats * 60.0 / ctx.tempo / ctx.speed;
cmd.set_param("fit".into(), Value::Float(dur, None));
cmd.set_param("dur".into(), Value::Float(dur, None));
cmd.set_param("fit", Value::Float(dur, None));
cmd.set_param("dur", Value::Float(dur, None));
}
Op::At => {
@@ -896,18 +896,18 @@ impl Forth {
let s = stack.pop().ok_or("stack underflow")?;
let d = stack.pop().ok_or("stack underflow")?;
let a = stack.pop().ok_or("stack underflow")?;
cmd.set_param("attack".into(), a);
cmd.set_param("decay".into(), d);
cmd.set_param("sustain".into(), s);
cmd.set_param("release".into(), r);
cmd.set_param("attack", a);
cmd.set_param("decay", d);
cmd.set_param("sustain", s);
cmd.set_param("release", r);
}
Op::Ad => {
let d = stack.pop().ok_or("stack underflow")?;
let a = stack.pop().ok_or("stack underflow")?;
cmd.set_param("attack".into(), a);
cmd.set_param("decay".into(), d);
cmd.set_param("sustain".into(), Value::Int(0, None));
cmd.set_param("attack", a);
cmd.set_param("decay", d);
cmd.set_param("sustain", Value::Int(0, None));
}
Op::Apply => {
@@ -1055,14 +1055,14 @@ impl Forth {
params
.iter()
.rev()
.find(|(k, _)| k == name)
.find(|(k, _)| *k == name)
.and_then(|(_, v)| v.as_int().ok())
};
let get_float = |name: &str| -> Option<f64> {
params
.iter()
.rev()
.find(|(k, _)| k == name)
.find(|(k, _)| *k == name)
.and_then(|(_, v)| v.as_float().ok())
};
let chan = get_int("chan")
@@ -1140,11 +1140,11 @@ impl Forth {
}
}
fn extract_dev_param(params: &[(String, Value)]) -> u8 {
fn extract_dev_param(params: &[(&str, Value)]) -> u8 {
params
.iter()
.rev()
.find(|(k, _)| k == "dev")
.find(|(k, _)| *k == "dev")
.and_then(|(_, v)| v.as_int().ok())
.map(|d| d.clamp(0, 3) as u8)
.unwrap_or(0)
@@ -1181,7 +1181,7 @@ fn is_tempo_scaled_param(name: &str) -> bool {
fn emit_output(
sound: Option<&str>,
params: &[(String, String)],
params: &[(&str, String)],
step_duration: f64,
nudge_secs: f64,
outputs: &mut Vec<String>,
@@ -1190,8 +1190,8 @@ fn emit_output(
let mut out = String::with_capacity(128);
out.push('/');
let has_dur = params.iter().any(|(k, _)| k == "dur");
let delaytime_idx = params.iter().position(|(k, _)| k == "delaytime");
let has_dur = params.iter().any(|(k, _)| *k == "dur");
let delaytime_idx = params.iter().position(|(k, _)| *k == "delaytime");
if let Some(s) = sound {
let _ = write!(&mut out, "sound/{s}");

View File

@@ -216,8 +216,8 @@ pub(crate) fn compile_word(
ops.push(op);
}
}
Context(ctx) => ops.push(Op::GetContext((*ctx).into())),
Param => ops.push(Op::SetParam(word.name.into())),
Context(ctx) => ops.push(Op::GetContext(ctx)),
Param => ops.push(Op::SetParam(word.name)),
Probability(p) => {
ops.push(Op::PushFloat(*p, None));
ops.push(Op::ChanceExec);