Less memory allocations at runtime

This commit is contained in:
2026-02-02 21:55:10 +01:00
parent cd8182425a
commit 74fe999496
9 changed files with 146 additions and 457 deletions

View File

@@ -1,3 +1,5 @@
use std::sync::Arc;
use super::ops::Op;
use super::types::{Dictionary, SourceSpan};
use super::words::compile_word;
@@ -118,7 +120,7 @@ fn compile(tokens: &[Token], dict: &Dictionary) -> Result<Vec<Op>, String> {
ops.push(Op::PushFloat(*f, Some(*span)));
}
}
Token::Str(s, span) => ops.push(Op::PushStr(s.clone(), Some(*span))),
Token::Str(s, span) => ops.push(Op::PushStr(Arc::from(s.as_str()), Some(*span))),
Token::Word(w, span) => {
let word = w.as_str();
if word == "{" {
@@ -129,7 +131,7 @@ fn compile(tokens: &[Token], dict: &Dictionary) -> Result<Vec<Op>, String> {
start: span.start,
end: end_span.end,
};
ops.push(Op::Quotation(quote_ops, Some(body_span)));
ops.push(Op::Quotation(Arc::from(quote_ops), Some(body_span)));
} else if word == "}" {
return Err("unexpected }".into());
} else if word == ":" {

View File

@@ -1,10 +1,12 @@
use std::sync::Arc;
use super::types::SourceSpan;
#[derive(Clone, Debug, PartialEq)]
pub enum Op {
PushInt(i64, Option<SourceSpan>),
PushFloat(f64, Option<SourceSpan>),
PushStr(String, Option<SourceSpan>),
PushStr(Arc<str>, Option<SourceSpan>),
Dup,
Dupn,
Drop,
@@ -71,7 +73,7 @@ pub enum Op {
Ftom,
SetTempo,
Every,
Quotation(Vec<Op>, Option<SourceSpan>),
Quotation(Arc<[Op]>, Option<SourceSpan>),
When,
Unless,
Adsr,

View File

@@ -60,9 +60,9 @@ pub(super) type CmdSnapshot<'a> = (Option<&'a Value>, &'a [(String, Value)]);
pub enum Value {
Int(i64, Option<SourceSpan>),
Float(f64, Option<SourceSpan>),
Str(String, Option<SourceSpan>),
Quotation(Vec<Op>, Option<SourceSpan>),
CycleList(Vec<Value>),
Str(Arc<str>, Option<SourceSpan>),
Quotation(Arc<[Op]>, Option<SourceSpan>),
CycleList(Arc<[Value]>),
}
impl PartialEq for Value {
@@ -116,7 +116,7 @@ impl Value {
match self {
Value::Int(i, _) => i.to_string(),
Value::Float(f, _) => f.to_string(),
Value::Str(s, _) => s.clone(),
Value::Str(s, _) => s.to_string(),
Value::Quotation(..) => String::new(),
Value::CycleList(_) => String::new(),
}

View File

@@ -1,6 +1,7 @@
use rand::rngs::StdRng;
use rand::{Rng as RngTrait, SeedableRng};
use std::borrow::Cow;
use std::sync::Arc;
use super::compiler::compile_script;
use super::ops::Op;
@@ -423,7 +424,7 @@ impl Forth {
let val = if values.len() == 1 {
values.into_iter().next().unwrap()
} else {
Value::CycleList(values)
Value::CycleList(Arc::from(values))
};
cmd.set_sound(val);
}
@@ -435,7 +436,7 @@ impl Forth {
let val = if values.len() == 1 {
values.into_iter().next().unwrap()
} else {
Value::CycleList(values)
Value::CycleList(Arc::from(values))
};
cmd.set_param(param.clone(), val);
}
@@ -735,7 +736,7 @@ impl Forth {
} else {
let key = format!("__chain_{}_{}__", ctx.bank, ctx.pattern);
let val = format!("{bank}:{pattern}");
self.vars.lock().unwrap().insert(key, Value::Str(val, None));
self.vars.lock().unwrap().insert(key, Value::Str(Arc::from(val), None));
}
}

View File

@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use std::sync::{Arc, LazyLock};
use super::ops::Op;
use super::theory;
@@ -3031,7 +3031,7 @@ pub(super) fn compile_word(
// @varname - fetch variable
if let Some(var_name) = name.strip_prefix('@') {
if !var_name.is_empty() {
ops.push(Op::PushStr(var_name.to_string(), span));
ops.push(Op::PushStr(Arc::from(var_name), span));
ops.push(Op::Get);
return true;
}
@@ -3040,7 +3040,7 @@ pub(super) fn compile_word(
// !varname - store into variable
if let Some(var_name) = name.strip_prefix('!') {
if !var_name.is_empty() {
ops.push(Op::PushStr(var_name.to_string(), span));
ops.push(Op::PushStr(Arc::from(var_name), span));
ops.push(Op::Set);
return true;
}
@@ -3073,6 +3073,6 @@ pub(super) fn compile_word(
}
// Unrecognized token becomes a string
ops.push(Op::PushStr(name.to_string(), span));
ops.push(Op::PushStr(Arc::from(name), span));
true
}