very wip
This commit is contained in:
@@ -17,7 +17,6 @@ pub struct ExecutionTrace {
|
||||
pub struct StepContext {
|
||||
pub step: usize,
|
||||
pub beat: f64,
|
||||
pub bank: usize,
|
||||
pub pattern: usize,
|
||||
pub tempo: f64,
|
||||
pub phase: f64,
|
||||
@@ -1751,7 +1750,7 @@ fn parse_interval(name: &str) -> Option<i64> {
|
||||
Some(simple)
|
||||
}
|
||||
|
||||
fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
||||
fn compile_word(name: &str, span: Option<SourceSpan>, ops: &mut Vec<Op>) -> bool {
|
||||
for word in WORDS {
|
||||
if word.name == name {
|
||||
match &word.compile {
|
||||
@@ -1762,7 +1761,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
||||
}
|
||||
Context(ctx) => ops.push(Op::GetContext((*ctx).into())),
|
||||
Param => ops.push(Op::SetParam(name.into())),
|
||||
Alias(target) => return compile_word(target, ops),
|
||||
Alias(target) => return compile_word(target, span, ops),
|
||||
Probability(p) => {
|
||||
ops.push(Op::PushFloat(*p, None));
|
||||
ops.push(Op::ChanceExec);
|
||||
@@ -1775,7 +1774,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
||||
// @varname - fetch variable
|
||||
if let Some(var_name) = name.strip_prefix('@') {
|
||||
if !var_name.is_empty() {
|
||||
ops.push(Op::PushStr(var_name.to_string(), None));
|
||||
ops.push(Op::PushStr(var_name.to_string(), span));
|
||||
ops.push(Op::Get);
|
||||
return true;
|
||||
}
|
||||
@@ -1784,7 +1783,7 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
||||
// !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(), None));
|
||||
ops.push(Op::PushStr(var_name.to_string(), span));
|
||||
ops.push(Op::Set);
|
||||
return true;
|
||||
}
|
||||
@@ -1792,14 +1791,14 @@ fn compile_word(name: &str, ops: &mut Vec<Op>) -> bool {
|
||||
|
||||
// Note names: c4, c#4, cs4, eb4, etc. -> MIDI number
|
||||
if let Some(midi) = parse_note_name(name) {
|
||||
ops.push(Op::PushInt(midi, None));
|
||||
ops.push(Op::PushInt(midi, span));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Intervals: m3, M3, P5, etc. -> dup top, add semitones (for chord building)
|
||||
if let Some(semitones) = parse_interval(name) {
|
||||
ops.push(Op::Dup);
|
||||
ops.push(Op::PushInt(semitones, None));
|
||||
ops.push(Op::PushInt(semitones, span));
|
||||
ops.push(Op::Add);
|
||||
return true;
|
||||
}
|
||||
@@ -1827,8 +1826,8 @@ enum Token {
|
||||
Float(f64, SourceSpan),
|
||||
Str(String, SourceSpan),
|
||||
Word(String, SourceSpan),
|
||||
QuoteStart(SourceSpan),
|
||||
QuoteEnd(SourceSpan),
|
||||
QuoteStart,
|
||||
QuoteEnd,
|
||||
}
|
||||
|
||||
fn tokenize(input: &str) -> Vec<Token> {
|
||||
@@ -1869,22 +1868,14 @@ fn tokenize(input: &str) -> Vec<Token> {
|
||||
}
|
||||
|
||||
if c == '{' {
|
||||
let start = pos;
|
||||
chars.next();
|
||||
tokens.push(Token::QuoteStart(SourceSpan {
|
||||
start,
|
||||
end: start + 1,
|
||||
}));
|
||||
tokens.push(Token::QuoteStart);
|
||||
continue;
|
||||
}
|
||||
|
||||
if c == '}' {
|
||||
let start = pos;
|
||||
chars.next();
|
||||
tokens.push(Token::QuoteEnd(SourceSpan {
|
||||
start,
|
||||
end: start + 1,
|
||||
}));
|
||||
tokens.push(Token::QuoteEnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1923,15 +1914,15 @@ fn compile(tokens: &[Token]) -> Result<Vec<Op>, String> {
|
||||
Token::Int(n, span) => ops.push(Op::PushInt(*n, Some(*span))),
|
||||
Token::Float(f, span) => ops.push(Op::PushFloat(*f, Some(*span))),
|
||||
Token::Str(s, span) => ops.push(Op::PushStr(s.clone(), Some(*span))),
|
||||
Token::QuoteStart(_) => {
|
||||
Token::QuoteStart => {
|
||||
let (quote_ops, consumed) = compile_quotation(&tokens[i + 1..])?;
|
||||
i += consumed;
|
||||
ops.push(Op::Quotation(quote_ops));
|
||||
}
|
||||
Token::QuoteEnd(_) => {
|
||||
Token::QuoteEnd => {
|
||||
return Err("unexpected }".into());
|
||||
}
|
||||
Token::Word(w, _) => {
|
||||
Token::Word(w, span) => {
|
||||
let word = w.as_str();
|
||||
if word == "|" {
|
||||
if pipe_parity {
|
||||
@@ -1952,7 +1943,7 @@ fn compile(tokens: &[Token]) -> Result<Vec<Op>, String> {
|
||||
ops.push(Op::Branch(else_ops.len()));
|
||||
ops.extend(else_ops);
|
||||
}
|
||||
} else if !compile_word(word, &mut ops) {
|
||||
} else if !compile_word(word, Some(*span), &mut ops) {
|
||||
return Err(format!("unknown word: {word}"));
|
||||
}
|
||||
}
|
||||
@@ -1969,8 +1960,8 @@ fn compile_quotation(tokens: &[Token]) -> Result<(Vec<Op>, usize), String> {
|
||||
|
||||
for (i, tok) in tokens.iter().enumerate() {
|
||||
match tok {
|
||||
Token::QuoteStart(_) => depth += 1,
|
||||
Token::QuoteEnd(_) => {
|
||||
Token::QuoteStart => depth += 1,
|
||||
Token::QuoteEnd => {
|
||||
depth -= 1;
|
||||
if depth == 0 {
|
||||
end_pos = Some(i);
|
||||
@@ -2039,10 +2030,12 @@ impl Forth {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn stack(&self) -> Vec<Value> {
|
||||
self.stack.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn clear_stack(&self) {
|
||||
self.stack.lock().unwrap().clear();
|
||||
}
|
||||
@@ -2104,6 +2097,7 @@ impl Forth {
|
||||
Ok(outputs)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn execute_ops(
|
||||
&self,
|
||||
ops: &[Op],
|
||||
|
||||
Reference in New Issue
Block a user