1pub mod arg_extraction;
31pub mod builtins;
32
33use crate::ast::*;
34use crate::common::fraction::Fraction;
35use crate::core::*;
36use crate::errors::{AddSpan, CarmenError, CoreResult, ErrorSource, Result};
37use builtins::BuiltinRegistry;
38use std::collections::HashMap;
39use std::fmt;
40use std::str::FromStr;
41
42#[derive(Debug, Clone, PartialEq)]
48pub enum Value {
49 Number(f64),
51 String(String),
53 Boolean(bool),
55 Pitch(Pitch),
57 PitchClass(PitchClass),
59 PitchClassSet(PitchClassSet),
61 Duration(Duration),
63 Dynamic(Dynamic),
65 Attribute(Attribute),
67 Chord(Chord),
69 Rest,
71 List(Vec<Value>),
73 Tuple(Vec<Value>),
75 Set(Vec<Value>),
77 MusicalEvent(MusicalEvent),
79 Part(Part),
81 Staff(Staff),
83 Timeline(Timeline),
85 Movement(Movement),
87 Score(Score),
89 MetadataKey(MetadataKey),
91 MetadataValue(MetadataValue),
93 ContextChange(ContextChange),
95 Function {
97 name: String,
98 params: Vec<String>,
99 body: Vec<SpannedStatement>,
100 },
101 BuiltinFunction(String),
103 Nil,
105}
106
107impl fmt::Display for Value {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 match self {
110 Value::Number(n) => write!(f, "{n}"),
111 Value::String(s) => write!(f, "\"{s}\""),
112 Value::Boolean(b) => write!(f, "{b}"),
113 Value::Pitch(p) => write!(f, "{}", p.to_note_name()),
114 Value::PitchClass(pc) => write!(f, "{}", pc.to_note_name()),
115 Value::PitchClassSet(pcs) => {
116 let mut classes: Vec<_> = pcs.classes.iter().collect();
117 classes.sort_by_key(|pc| pc.0); let names: Vec<String> = classes.iter().map(|&pc| format!("{}", pc.0)).collect();
120 write!(f, "{{{}}}", names.join(", "))
121 }
122 Value::Duration(d) => write!(f, "{}", d.to_fractional_string()),
123 Value::Dynamic(d) => write!(f, "{d:?}"),
124 Value::Attribute(attr) => write!(f, "{attr:?}"),
125 Value::Rest => write!(f, "~"),
126 Value::Chord(chord) => {
127 let notes: Vec<String> = chord
128 .pitches
129 .iter()
130 .map(|pitch| pitch.to_note_name())
131 .collect();
132 write!(f, "({})", notes.join(", "))
133 }
134 Value::List(items) => {
135 let formatted: Vec<String> = items.iter().map(|v| format!("{v}")).collect();
136 write!(f, "[{}]", formatted.join(", "))
137 }
138 Value::Tuple(items) => {
139 let formatted: Vec<String> = items.iter().map(|v| format!("{v}")).collect();
140 write!(f, "({})", formatted.join(", "))
141 }
142 Value::Set(items) => {
143 let formatted: Vec<String> = items.iter().map(|v| format!("{v}")).collect();
144 write!(f, "{{{}}}", formatted.join(", "))
145 }
146 Value::MusicalEvent(event) => {
147 let duration_str = event.duration.to_fractional_string();
148 let content_str = match &event.content {
149 EventContent::Note(pitch) => pitch.to_note_name(),
150 EventContent::Chord(chord) => {
151 let notes: Vec<String> = chord
152 .pitches
153 .iter()
154 .map(|pitch| pitch.to_note_name())
155 .collect();
156 format!("({})", notes.join(", "))
157 }
158 EventContent::Rest => "~".to_string(),
159 EventContent::Sequence(events) => {
160 format!("[{} events]", events.len())
161 }
162 };
163
164 let mut parts = vec![duration_str, content_str];
165
166 if let Some(dynamic) = &event.dynamic {
167 parts.push(format!("{dynamic:?}").to_lowercase());
168 }
169
170 if !event.attributes.is_empty() {
171 let attrs: Vec<String> = event
172 .attributes
173 .iter()
174 .map(|a| format!("{a:?}").to_lowercase())
175 .collect();
176 parts.push(attrs.join(" "));
177 }
178
179 write!(f, "{}", parts.join(" "))
180 }
181 Value::Part(part) => {
182 let event_count = part.total_event_count();
183 let mut result = if let Some(name) = &part.name {
184 format!("Part \"{name}\"")
185 } else {
186 "Part".to_string()
187 };
188
189 if !part.staves.is_empty() {
190 result.push_str(&format!(
191 " ({} staves, {} events, {:.1}s)",
192 part.staves.len(),
193 event_count,
194 part.total_duration()
195 ));
196
197 let staff_info: Vec<String> = part
199 .staves
200 .iter()
201 .map(|s| {
202 let voices_count = s.voices.len();
203 let events_count: usize = s.voices.iter().map(|v| v.events.len()).sum();
204 let voice_str = if voices_count == 1 { "voice" } else { "voices" };
205 format!(
206 "S{}: {} {}, {} events",
207 s.number, voices_count, voice_str, events_count
208 )
209 })
210 .collect();
211
212 if staff_info.len() <= 4 {
213 result.push_str(&format!(" [{}]", staff_info.join(", ")));
214 } else {
215 result.push_str(&format!(
216 " [{}... +{}]",
217 staff_info[..3].join(", "),
218 staff_info.len() - 3
219 ));
220 }
221 } else {
222 result.push_str(&format!(
223 " ({} events, {:.1}s)",
224 event_count,
225 part.total_duration()
226 ));
227 }
228
229 write!(f, "{result}")
230 }
231
232 Value::Staff(staff) => {
233 let voices_count = staff.voices.len();
234 let events_count: usize = staff.voices.iter().map(|v| v.events.len()).sum();
235 let voice_str = if voices_count == 1 { "voice" } else { "voices" };
236 write!(
237 f,
238 "Staff {} ({} {}, {} events, {:.1}s)",
239 staff.number,
240 voices_count,
241 voice_str,
242 events_count,
243 staff.total_duration()
244 )
245 }
246 Value::Timeline(timeline) => {
247 let total_events: usize =
248 timeline.parts.iter().map(|p| p.total_event_count()).sum();
249 let total_staves: usize =
250 timeline.parts.iter().map(|p| p.staves.len().max(1)).sum();
251
252 let mut result = format!(
253 "Timeline ({} parts, {} staves, {} events, {:.1}s)",
254 timeline.parts.len(),
255 total_staves,
256 total_events,
257 timeline.total_duration()
258 );
259
260 let part_info: Vec<String> = timeline
262 .parts
263 .iter()
264 .map(|p| {
265 let name = if let Some(name) = &p.name {
266 format!("\"{name}\"")
267 } else {
268 "Unnamed".to_string()
269 };
270
271 if p.staves.is_empty() {
272 format!("{}: {}", name, p.events.len())
273 } else {
274 format!("{}: {}s+{}", name, p.staves.len(), p.events.len())
275 }
276 })
277 .collect();
278
279 if !part_info.is_empty() && part_info.len() <= 3 {
280 result.push_str(&format!(" [{}]", part_info.join(", ")));
281 } else if !part_info.is_empty() {
282 result.push_str(&format!(
283 " [{}... +{}]",
284 part_info[..2].join(", "),
285 part_info.len() - 2
286 ));
287 }
288
289 write!(f, "{result}")
290 }
291 Value::Movement(movement) => {
292 let mut result = if let Some(name) = &movement.name {
293 format!("Movement \"{name}\"")
294 } else {
295 "Movement".to_string()
296 };
297
298 let total_events: usize = movement
299 .timeline
300 .parts
301 .iter()
302 .map(|p| p.total_event_count())
303 .sum();
304 result.push_str(&format!(
305 " ({} parts, {} events, {:.1}s)",
306 movement.timeline.parts.len(),
307 total_events,
308 movement.total_duration()
309 ));
310
311 let part_info: Vec<String> = movement
313 .timeline
314 .parts
315 .iter()
316 .map(|p| {
317 if let Some(name) = &p.name {
318 format!("\"{name}\"")
319 } else {
320 "Unnamed".to_string()
321 }
322 })
323 .collect();
324
325 if !part_info.is_empty() {
326 if part_info.len() <= 3 {
327 result.push_str(&format!(" [{}]", part_info.join(", ")));
328 } else {
329 result.push_str(&format!(
330 " [{}... +{} more]",
331 part_info[..2].join(", "),
332 part_info.len() - 2
333 ));
334 }
335 }
336
337 write!(f, "{result}")
338 }
339 Value::Score(score) => {
340 let mut result = if let Some(name) = &score.name {
341 format!("Score \"{name}\"")
342 } else {
343 "Score".to_string()
344 };
345
346 if score.is_multi_movement() {
347 let total_parts: usize =
348 score.movements.iter().map(|m| m.timeline.parts.len()).sum();
349 let total_events: usize = score
350 .movements
351 .iter()
352 .map(|m| {
353 m.timeline
354 .parts
355 .iter()
356 .map(|p| p.total_event_count())
357 .sum::<usize>()
358 })
359 .sum();
360
361 result.push_str(&format!(
362 " ({} movements, {} parts total, {} events, {:.1}s)",
363 score.movements.len(),
364 total_parts,
365 total_events,
366 score.total_duration()
367 ));
368
369 let movement_names: Vec<String> = score
371 .movements
372 .iter()
373 .enumerate()
374 .map(|(i, m)| {
375 if let Some(name) = &m.name {
376 format!("\"{name}\"")
377 } else {
378 format!("Movement {}", i + 1)
379 }
380 })
381 .collect();
382
383 if movement_names.len() <= 3 {
384 result.push_str(&format!(" [{}]", movement_names.join(", ")));
385 } else {
386 result.push_str(&format!(
387 " [{}... +{} more]",
388 movement_names[..2].join(", "),
389 movement_names.len() - 2
390 ));
391 }
392 } else if let Some(timeline) = &score.timeline {
393 let total_events: usize =
394 timeline.parts.iter().map(|p| p.total_event_count()).sum();
395 result.push_str(&format!(
396 " ({} parts, {} events, {:.1}s)",
397 timeline.parts.len(),
398 total_events,
399 score.total_duration()
400 ));
401 }
402
403 write!(f, "{result}")
404 }
405 Value::Function { name, params, .. } => {
406 write!(f, "Function {}({})", name, params.join(", "))
407 }
408 Value::BuiltinFunction(name) => {
409 write!(f, "BuiltinFunction {name}")
410 }
411 Value::MetadataKey(key) => write!(f, "MetadataKey({key:?})"),
412 Value::MetadataValue(value) => write!(f, "MetadataValue({value:?})"),
413 Value::ContextChange(change) => write!(f, "ContextChange({change:?})"),
414 Value::Nil => write!(f, "nil"),
415 }
416 }
417}
418
419impl Value {
420 pub fn type_name(&self) -> &'static str {
424 match self {
425 Value::Number(_) => "number",
426 Value::String(_) => "string",
427 Value::Boolean(_) => "boolean",
428 Value::Pitch(_) => "pitch",
429 Value::PitchClass(_) => "pitch_class",
430 Value::PitchClassSet(_) => "pitch_class_set",
431 Value::Duration(_) => "duration",
432 Value::Dynamic(_) => "dynamic",
433 Value::Attribute(_) => "attribute",
434 Value::Chord(_) => "chord",
435 Value::Rest => "rest",
436 Value::List(_) => "list",
437 Value::Tuple(_) => "tuple",
438 Value::Set(_) => "set",
439 Value::MusicalEvent(_) => "musical_event",
440 Value::Part(_) => "part",
441 Value::Staff(_) => "staff",
442 Value::Timeline(_) => "timeline",
443 Value::Movement(_) => "movement",
444 Value::Score(_) => "score",
445 Value::MetadataKey(_) => "metadata_key",
446 Value::MetadataValue(_) => "metadata_value",
447 Value::ContextChange(_) => "context_change",
448 Value::Function { .. } => "function",
449 Value::BuiltinFunction(_) => "builtin_function",
450 Value::Nil => "nil",
451 }
452 }
453
454 pub fn is_truthy(&self) -> bool {
459 match self {
460 Value::Boolean(b) => *b,
461 Value::Nil => false,
462 Value::Number(n) => *n != 0.0,
463 Value::String(s) => !s.is_empty(),
464 Value::List(l) => !l.is_empty(),
465 _ => true,
466 }
467 }
468}
469
470impl From<f64> for Value {
471 fn from(value: f64) -> Self {
472 Value::Number(value)
473 }
474}
475
476impl From<Value> for Option<f64> {
477 fn from(value: Value) -> Self {
478 match value {
479 Value::Number(n) => Some(n),
480 _ => None,
481 }
482 }
483}
484
485impl From<Value> for Option<bool> {
486 fn from(value: Value) -> Self {
487 Some(value.is_truthy())
488 }
489}
490
491impl From<PitchClass> for Value {
492 fn from(pc: PitchClass) -> Self {
493 Value::PitchClass(pc)
494 }
495}
496
497impl From<Value> for Option<PitchClass> {
498 fn from(value: Value) -> Self {
499 match value {
500 Value::PitchClass(pc) => Some(pc),
501 Value::Number(n) if (0.0..=11.0).contains(&n) && n.fract() == 0.0 => {
502 Some(PitchClass::new(n as u8))
503 }
504 _ => None,
505 }
506 }
507}
508
509impl From<Pitch> for Value {
510 fn from(pitch: Pitch) -> Self {
511 Value::Pitch(pitch)
512 }
513}
514
515impl From<Value> for Option<Pitch> {
516 fn from(value: Value) -> Self {
517 match value {
518 Value::Pitch(p) => Some(p),
519 _ => None,
520 }
521 }
522}
523
524impl TryFrom<SpannedLiteral> for Value {
525 type Error = CarmenError;
526
527 fn try_from(literal: SpannedLiteral) -> Result<Self> {
528 match literal.node {
529 Literal::Number(value) => Ok(Value::Number(value)),
530 Literal::String(value) => Ok(Value::String(value)),
531 Literal::Boolean(value) => Ok(Value::Boolean(value)),
532 Literal::Pitch {
533 note,
534 accidentals,
535 octave,
536 } => {
537 if let Some(octave) = octave {
538 Pitch::from_note_name(¬e, accidentals, octave as i8)
539 .map(Value::Pitch)
540 .map_err(|e| e.with_span(literal.span))
541 } else {
542 PitchClass::from_note_name(¬e, accidentals)
544 .map(Value::PitchClass)
545 .map_err(|e| e.with_span(literal.span))
546 }
547 }
548 Literal::Duration {
549 numerator,
550 denominator,
551 dots,
552 } => {
553 let base_fraction = Fraction::new(numerator, denominator);
554 let final_fraction = base_fraction.with_dots(dots);
555 Ok(Value::Duration(Duration {
556 fraction: final_fraction,
557 }))
558 }
559 Literal::Dynamic(value) => Dynamic::from_str(&value)
560 .map(Value::Dynamic)
561 .map_err(|e| e.with_span(literal.span)),
562 Literal::Attribute(value) => Attribute::from_str(&value)
563 .map(Value::Attribute)
564 .map_err(|e| e.with_span(literal.span)),
565 Literal::Rest { .. } => Ok(Value::Rest),
566 }
567 }
568}
569
570impl TryFrom<Value> for MetadataKey {
571 type Error = ErrorSource;
572
573 fn try_from(value: Value) -> CoreResult<Self> {
574 if let Value::String(s) = value {
575 match s.as_str() {
576 "title" => Ok(MetadataKey::Title),
577 "composer" => Ok(MetadataKey::Composer),
578 "copyright" => Ok(MetadataKey::Copyright),
579 "tempo" => Ok(MetadataKey::Tempo),
580 "time_signature" => Ok(MetadataKey::TimeSignature),
581 "key_signature" => Ok(MetadataKey::KeySignature),
582 "clef" => Ok(MetadataKey::Clef),
583 "instrument" => Ok(MetadataKey::Instrument),
584 "channel" => Ok(MetadataKey::Channel),
585 "offset" => Ok(MetadataKey::Offset),
586 _ => Err(ErrorSource::Argument(format!("Invalid metadata key: {s}"))),
587 }
588 } else {
589 Err(ErrorSource::Type(
590 "Expected string for metadata key".to_string(),
591 ))
592 }
593 }
594}
595
596impl TryFrom<Value> for MetadataValue {
597 type Error = ErrorSource;
598
599 fn try_from(value: Value) -> CoreResult<Self> {
600 match value {
601 Value::String(s) => Ok(MetadataValue::String(s)),
602 Value::Number(n) => Ok(MetadataValue::Number(n)),
603 Value::List(l) => {
604 if l.len() == 2 {
605 if let (Value::Number(num), Value::Number(den)) = (&l[0], &l[1]) {
606 if num.fract() == 0.0 && den.fract() == 0.0 && *den != 0.0 {
607 return Ok(MetadataValue::TimeSignature(*num as u32, *den as u32));
608 }
609 }
610 }
611 Err(ErrorSource::Type(
612 "Expected [numerator, denominator] for TimeSignature".to_string(),
613 ))
614 }
615
616 _ => Err(ErrorSource::Type(format!(
617 "Unsupported value type for metadata: {}",
618 value.type_name()
619 ))),
620 }
621 }
622}
623
624pub struct Environment {
630 scopes: Vec<HashMap<String, Value>>,
632 builtins: BuiltinRegistry,
634}
635
636impl Default for Environment {
637 fn default() -> Self {
638 Self::new()
639 }
640}
641
642impl Environment {
643 pub fn new() -> Self {
645 let mut env = Self {
646 scopes: vec![HashMap::new()],
647 builtins: BuiltinRegistry::new(),
648 };
649 env.define_builtins();
650 env
651 }
652
653 pub fn push_scope(&mut self) {
657 self.scopes.push(HashMap::new());
658 }
659
660 pub fn pop_scope(&mut self) {
664 if self.scopes.len() > 1 {
665 self.scopes.pop();
666 }
667 }
668
669 pub fn define(&mut self, name: &str, value: Value) {
673 if let Some(scope) = self.scopes.last_mut() {
674 scope.insert(name.to_string(), value);
675 }
676 }
677
678 pub fn get(&self, name: &str) -> Option<&Value> {
682 for scope in self.scopes.iter().rev() {
683 if let Some(value) = scope.get(name) {
684 return Some(value);
685 }
686 }
687 None
688 }
689
690 fn define_builtins(&mut self) {
692 let function_names: Vec<String> = self
694 .builtins
695 .get_function_names()
696 .into_iter()
697 .map(|name| name.to_string())
698 .collect();
699 for name in &function_names {
700 self.define(name, Value::BuiltinFunction(name.clone()));
701 }
702
703 self.define("pi", Value::BuiltinFunction("pitch_interval".to_string()));
705 self.define("T", Value::BuiltinFunction("transpose".to_string()));
706 self.define(
707 "pci",
708 Value::BuiltinFunction("pitch_class_interval".to_string()),
709 );
710 self.define("I", Value::BuiltinFunction("invert".to_string()));
711 self.define("ic", Value::BuiltinFunction("interval_class".to_string()));
712 self.define(
713 "ic_vector",
714 Value::BuiltinFunction("interval_class_vector".to_string()),
715 )
716 }
717}
718
719#[allow(clippy::large_enum_variant)]
723#[derive(Debug, Clone, PartialEq)]
724pub enum ControlFlow {
725 None,
727 Return(Value),
729}
730
731#[derive(Debug, Clone, PartialEq)]
735pub enum ExecutionResult {
736 Value(Value),
738 Control(ControlFlow),
740}
741
742impl ExecutionResult {
743 pub fn into_value(self) -> Value {
748 match self {
749 ExecutionResult::Value(val) => val,
750 ExecutionResult::Control(ControlFlow::Return(val)) => val,
751 ExecutionResult::Control(ControlFlow::None) => Value::Nil,
752 }
753 }
754
755 pub fn is_return(&self) -> bool {
757 matches!(self, ExecutionResult::Control(ControlFlow::Return(_)))
758 }
759}
760
761pub struct Interpreter {
766 environment: Environment,
768 current_time_offset: Fraction,
770}
771
772impl Default for Interpreter {
773 fn default() -> Self {
774 Self::new()
775 }
776}
777
778impl Interpreter {
779 pub fn new() -> Self {
781 Self {
782 environment: Environment::new(),
783 current_time_offset: Fraction::new(0, 1),
784 }
785 }
786
787 pub fn get_all_symbols(&self) -> Vec<String> {
791 let mut symbols = Vec::new();
792 for scope in &self.environment.scopes {
793 symbols.extend(scope.keys().cloned());
794 }
795 symbols.extend(
796 self.environment
797 .builtins
798 .get_function_names()
799 .into_iter()
800 .map(String::from),
801 );
802 symbols.sort();
803 symbols.dedup();
804 symbols
805 }
806
807 pub fn get_variable(&self, name: &str) -> Option<Value> {
811 self.environment.get(name).cloned()
812 }
813
814 pub fn interpret(&mut self, program: &Program) -> Result<Value> {
819 let mut last_value = Value::Nil;
820
821 for statement in &program.statements {
822 match self.execute_statement(statement)? {
823 ExecutionResult::Value(val) => last_value = val,
824 ExecutionResult::Control(ControlFlow::Return(val)) => return Ok(val),
825 ExecutionResult::Control(ControlFlow::None) => {}
826 }
827 }
828
829 Ok(last_value)
830 }
831
832 fn create_metadata_value(
837 &self,
838 key: &MetadataKey,
839 value: Value,
840 span: &crate::errors::Span,
841 ) -> Result<MetadataValue> {
842 match key {
843 MetadataKey::Title
844 | MetadataKey::Composer
845 | MetadataKey::Copyright
846 | MetadataKey::Instrument => match value {
847 Value::String(s) => Ok(MetadataValue::String(s)),
848 _ => Err(
849 ErrorSource::Type(format!("Expected string for metadata key '{key}'"))
850 .with_span(*span),
851 ),
852 },
853 MetadataKey::Tempo | MetadataKey::Channel | MetadataKey::Offset => match value {
854 Value::Number(n) => Ok(MetadataValue::Number(n)),
855 _ => Err(
856 ErrorSource::Type(format!("Expected number for metadata key '{key}'"))
857 .with_span(*span),
858 ),
859 },
860 MetadataKey::TimeSignature => match value {
861 Value::Tuple(l) if l.len() == 2 => {
862 if let (Value::Number(num), Value::Number(den)) = (&l[0], &l[1]) {
863 if num.fract() == 0.0 && den.fract() == 0.0 && *den > 0.0 {
864 return Ok(MetadataValue::TimeSignature(*num as u32, *den as u32));
865 }
866 }
867 Err(ErrorSource::Type(
868 "Expected tuple of two numbers for time signature".to_string(),
869 )
870 .with_span(*span))
871 }
872 _ => Err(ErrorSource::Type(
873 "Expected tuple of (num, den) for time signature".to_string(),
874 )
875 .with_span(*span)),
876 },
877 MetadataKey::KeySignature => match value {
878 Value::String(s) => {
879 let parts: Vec<&str> = s.split_whitespace().collect();
880 let key_name = parts[0];
881 let mode = if parts.len() > 1 {
882 parts[1].to_lowercase()
883 } else {
884 "major".to_string()
885 };
886
887 let major_keys = ["C", "G", "D", "A", "E", "B", "F#", "C#"];
888 let minor_keys = ["A", "E", "B", "F#", "C#", "G#", "D#", "A#"];
889
890 match mode.as_str() {
891 "major" => {
892 if let Some(pos) = major_keys
893 .iter()
894 .position(|&k| k.eq_ignore_ascii_case(key_name))
895 {
896 Ok(MetadataValue::KeySignature(KeySignature::Major(pos as u8)))
897 } else {
898 Err(ErrorSource::Argument(format!(
899 "Unsupported major key signature '{s}'"
900 ))
901 .with_span(*span))
902 }
903 }
904 "minor" => {
905 if let Some(pos) = minor_keys
906 .iter()
907 .position(|&k| k.eq_ignore_ascii_case(key_name))
908 {
909 Ok(MetadataValue::KeySignature(KeySignature::Minor(pos as u8)))
910 } else {
911 Err(ErrorSource::Argument(format!(
912 "Unsupported minor key signature '{s}'"
913 ))
914 .with_span(*span))
915 }
916 }
917 _ => Err(ErrorSource::Argument(format!(
918 "Unsupported key signature mode '{mode}'"
919 ))
920 .with_span(*span)),
921 }
922 }
923 _ => Err(
924 ErrorSource::Type("Expected string for key signature".to_string())
925 .with_span(*span),
926 ),
927 },
928 MetadataKey::Clef => match value {
929 Value::String(s) => Clef::from_str(&s)
930 .map(MetadataValue::Clef)
931 .map_err(|e| e.with_span(*span)),
932 _ => {
933 Err(ErrorSource::Type("Expected string for clef".to_string()).with_span(*span))
934 }
935 },
936 }
937 }
938
939 fn propagate_implicit_octaves(&self, values: &mut Vec<Value>) {
944 let mut last_octave: Option<i8> = None;
945 for value in values {
946 process_value_octaves(value, &mut last_octave);
947 }
948 }
949
950 fn execute_statement(&mut self, statement: &SpannedStatement) -> Result<ExecutionResult> {
955 match &statement.node {
956 Statement::Expression(expr) => {
957 let val = self.evaluate_expression(expr)?;
960 Ok(ExecutionResult::Value(val))
961 }
962 Statement::VariableDeclaration { name, value, .. } => {
963 let val = self.evaluate_expression(value)?;
964 self.environment.define(name, val.clone());
965 Ok(ExecutionResult::Value(val))
966 }
967 Statement::FunctionDeclaration {
968 name, params, body, ..
969 } => {
970 let function = Value::Function {
971 name: name.clone(),
972 params: params.clone(),
973 body: body.clone(),
974 };
975 self.environment.define(name, function.clone());
976 Ok(ExecutionResult::Value(function))
977 }
978 Statement::Return { value, .. } => {
979 let val = if let Some(expr) = value {
980 self.evaluate_expression(expr)?
981 } else {
982 Value::Nil
983 };
984 Ok(ExecutionResult::Control(ControlFlow::Return(val)))
985 }
986 Statement::Metadata { key, value, .. } => {
987 let evaluated_value = self.evaluate_expression(value)?;
988 let metadata_key = MetadataKey::try_from(Value::String(key.clone()))
989 .map_err(|e| e.with_span(value.span))?;
990 let metadata_value =
991 self.create_metadata_value(&metadata_key, evaluated_value, &value.span)?;
992
993 let change = ContextChange {
994 key: metadata_key,
995 value: metadata_value,
996 time_offset: self.current_time_offset,
997 };
998 Ok(ExecutionResult::Value(Value::ContextChange(change)))
999 }
1000 }
1001 }
1002
1003 fn build_voice(&mut self, events: Vec<Value>) -> Result<Voice> {
1007 let mut voice = Voice::new();
1008 let mut voice_time_offset = Fraction::new(0, 1);
1009 for event_val in events {
1010 if let Value::MusicalEvent(event) = event_val {
1011 let mut event_with_offset = event.clone();
1012 event_with_offset.offset = voice_time_offset;
1013 voice.add_event(event_with_offset);
1014 voice_time_offset += event.total_duration();
1015 }
1016 }
1017 Ok(voice)
1018 }
1019
1020 fn build_staff_from_tuple(
1024 &mut self,
1025 elements: Vec<Value>,
1026 num_staves: usize,
1027 span: &crate::errors::Span,
1028 ) -> Result<Staff> {
1029 let mut staff = Staff::new((num_staves + 1) as u32);
1030 for voice_val in elements {
1031 let events_for_voice = match voice_val {
1032 Value::List(events) => events,
1033 Value::MusicalEvent(event) => match event.content {
1034 EventContent::Sequence(events) => {
1035 events.into_iter().map(Value::MusicalEvent).collect()
1036 }
1037 _ => vec![Value::MusicalEvent(event)],
1038 },
1039 _ => {
1040 return Err(ErrorSource::Runtime(
1041 "Tuples in a part must contain lists or musical events.".to_string(),
1042 )
1043 .with_span(*span));
1044 }
1045 };
1046 let voice = self.build_voice(events_for_voice)?;
1047 staff = staff.add_voice(voice);
1048 }
1049 Ok(staff)
1050 }
1051
1052 fn evaluate_expression(&mut self, expression: &SpannedExpression) -> Result<Value> {
1058 match &expression.node {
1059 Expression::Literal(literal) => SpannedLiteral {
1060 node: literal.clone(),
1061 span: expression.span,
1062 }
1063 .try_into(),
1064 Expression::Identifier(name) => self.environment.get(name).cloned().ok_or_else(|| {
1065 ErrorSource::Runtime(format!("Undefined variable '{name}'"))
1066 .with_span(expression.span)
1067 }),
1068 Expression::Binary {
1069 left,
1070 operator,
1071 right,
1072 } => {
1073 let left_val = self.evaluate_expression(left)?;
1074 let right_val = self.evaluate_expression(right)?;
1075 self.evaluate_binary_op(&left_val, operator, &right_val, &expression.span)
1076 }
1077 Expression::Unary { operator, operand } => {
1078 let val = self.evaluate_expression(operand)?;
1079 self.evaluate_unary_op(operator, &val, &expression.span)
1080 }
1081 Expression::Call {
1082 callee,
1083 args,
1084 kwargs,
1085 } => {
1086 let function = self.evaluate_expression(callee)?;
1087 let arg_values: Result<Vec<Value>> = args
1088 .iter()
1089 .map(|arg| self.evaluate_expression(arg))
1090 .collect();
1091 let arg_values = arg_values?;
1092
1093 let kwarg_values: Result<Vec<(String, Value)>> = kwargs
1094 .iter()
1095 .map(|(name, expr)| Ok((name.clone(), self.evaluate_expression(expr)?)))
1096 .collect();
1097 let kwarg_values = kwarg_values?;
1098
1099 self.call_function(&function, &arg_values, &kwarg_values, &expression.span)
1100 }
1101 Expression::Pipe { left, right } => {
1102 let left_val = self.evaluate_expression(left)?;
1103 match right.as_ref() {
1104 Spanned {
1105 node:
1106 Expression::Call {
1107 callee,
1108 args,
1109 kwargs,
1110 },
1111 ..
1112 } => {
1113 let function = self.evaluate_expression(callee)?;
1114 let mut arg_values = vec![left_val];
1115 for arg in args {
1116 arg_values.push(self.evaluate_expression(arg)?);
1117 }
1118
1119 let kwarg_values: Result<Vec<(String, Value)>> = kwargs
1120 .iter()
1121 .map(|(name, expr)| Ok((name.clone(), self.evaluate_expression(expr)?)))
1122 .collect();
1123 let kwarg_values = kwarg_values?;
1124 self.call_function(&function, &arg_values, &kwarg_values, &expression.span)
1125 }
1126 _ => Err(ErrorSource::Runtime(
1127 "Pipe right side must be a function call".to_string(),
1128 )
1129 .with_span(expression.span)),
1130 }
1131 }
1132 Expression::List { elements, .. } => {
1133 let values: Result<Vec<Value>> = elements
1134 .iter()
1135 .map(|elem| self.evaluate_expression(elem))
1136 .collect();
1137 let mut values = values?;
1138 self.propagate_implicit_octaves(&mut values);
1139 Ok(Value::List(values))
1140 }
1141 Expression::Tuple { elements, .. } => {
1142 let values: Result<Vec<Value>> = elements
1143 .iter()
1144 .map(|elem| self.evaluate_expression(elem))
1145 .collect();
1146 let mut values = values?;
1147 self.propagate_implicit_octaves(&mut values);
1148
1149 if values.iter().all(|v| matches!(v, Value::Pitch(_))) {
1151 let pitches: Vec<Pitch> = values
1152 .into_iter()
1153 .map(|v| match v {
1154 Value::Pitch(p) => p,
1155 _ => unreachable!(),
1156 })
1157 .collect();
1158 Ok(Value::Chord(Chord { pitches }))
1159 } else {
1160 Ok(Value::Tuple(values))
1161 }
1162 }
1163 Expression::Set { elements, .. } => {
1164 let values: Result<Vec<Value>> = elements
1165 .iter()
1166 .map(|elem| self.evaluate_expression(elem))
1167 .collect();
1168 Ok(Value::Set(values?))
1169 }
1170 Expression::Block { statements, .. } => {
1171 self.environment.push_scope();
1172 let mut last_value = Value::Nil;
1173
1174 for stmt in statements {
1175 match self.execute_statement(stmt)? {
1176 ExecutionResult::Value(val) => last_value = val,
1177 ExecutionResult::Control(flow) => {
1178 self.environment.pop_scope();
1179 return Ok(ExecutionResult::Control(flow).into_value());
1180 }
1181 }
1182 }
1183
1184 self.environment.pop_scope();
1185 Ok(last_value)
1186 }
1187 Expression::If {
1188 condition,
1189 then_branch,
1190 else_branch,
1191 ..
1192 } => {
1193 let condition_val = self.evaluate_expression(condition)?;
1194
1195 if condition_val.is_truthy() {
1196 self.evaluate_expression(then_branch)
1197 } else if let Some(else_expr) = else_branch {
1198 self.evaluate_expression(else_expr)
1199 } else {
1200 Ok(Value::Nil)
1201 }
1202 }
1203 Expression::For {
1204 variable,
1205 iterable,
1206 body,
1207 } => {
1208 let iterable_val = self.evaluate_expression(iterable)?;
1209
1210 match iterable_val {
1211 Value::List(items) => {
1212 self.environment.push_scope();
1213 let mut results = Vec::new();
1214
1215 for item in items {
1216 self.environment.define(variable, item);
1217 results.push(self.evaluate_expression(body)?);
1218 }
1219
1220 self.environment.pop_scope();
1221 Ok(Value::List(results))
1222 }
1223 _ => Err(
1224 ErrorSource::Runtime("For loop requires iterable".to_string())
1225 .with_span(expression.span),
1226 ),
1227 }
1228 }
1229 Expression::While { condition, body } => {
1230 let mut results = Vec::new();
1231 let mut iterations = 0;
1232 const MAX_ITERATIONS: usize = 10000; while iterations < MAX_ITERATIONS {
1235 let condition_val = self.evaluate_expression(condition)?;
1236 if !condition_val.is_truthy() {
1237 break;
1238 }
1239
1240 results.push(self.evaluate_expression(body)?);
1241 iterations += 1;
1242 }
1243
1244 if iterations >= MAX_ITERATIONS {
1245 return Err(ErrorSource::Runtime(
1246 "While loop exceeded maximum iterations".to_string(),
1247 )
1248 .with_span(expression.span));
1249 }
1250
1251 Ok(Value::List(results))
1252 }
1253 Expression::PitchClassSet { classes, .. } => {
1254 let pitch_classes: Vec<PitchClass> =
1255 classes.iter().map(|&n| PitchClass::new(n)).collect();
1256 Ok(Value::PitchClassSet(PitchClassSet::new(pitch_classes)))
1257 }
1258 Expression::MusicalEvent {
1259 duration,
1260 pitches,
1261 dynamic,
1262 attributes,
1263 ..
1264 } => {
1265 let duration_val = self.evaluate_expression(duration)?;
1266 let pitches_val = self.evaluate_expression(pitches)?;
1267
1268 let duration = match duration_val {
1269 Value::Duration(d) => d,
1270 _ => {
1271 return Err(ErrorSource::Runtime("Expected duration".to_string())
1272 .with_span(expression.span))
1273 }
1274 };
1275
1276 let content =
1277 match pitches_val {
1278 Value::Pitch(p) => EventContent::Note(p),
1279 Value::Chord(c) => EventContent::Chord(c),
1280 Value::Rest => EventContent::Rest,
1281 Value::List(elements) => {
1282 let mut events = Vec::new();
1283 let mut current_offset = Fraction::new(0, 1);
1284
1285 for element in elements {
1286 match element {
1287 Value::MusicalEvent(mut event) => {
1288 event.offset = current_offset;
1289 current_offset += event.duration.fraction;
1290 events.push(event);
1291 }
1292 Value::Pitch(pitch) => {
1293 let mut event = MusicalEvent::note(pitch, duration);
1294 event.offset = current_offset;
1295 events.push(event);
1296 current_offset += duration.fraction;
1297 }
1298 Value::Rest => {
1299 let mut rest_event = MusicalEvent::rest(duration);
1300 rest_event.offset = current_offset;
1301 events.push(rest_event);
1302 current_offset += duration.fraction;
1303 }
1304 Value::Chord(chord) => {
1305 let mut chord_event = MusicalEvent::chord(chord, duration);
1306 chord_event.offset = current_offset;
1307 events.push(chord_event);
1308 current_offset += duration.fraction;
1309 }
1310 _ => return Err(ErrorSource::Runtime(
1311 "Expected musical event, pitch, chord or rest in sequence"
1312 .to_string(),
1313 )
1314 .with_span(expression.span)),
1315 }
1316 }
1317
1318 EventContent::Sequence(events)
1319 }
1320 Value::Tuple(pitches) => {
1321 let pitch_vec: Result<Vec<Pitch>> = pitches
1322 .into_iter()
1323 .map(|p| match p {
1324 Value::Pitch(pitch) => Ok(pitch),
1325 _ => Err(ErrorSource::Runtime(
1326 "Expected pitch in tuple chord".to_string(),
1327 )
1328 .with_span(expression.span)),
1329 })
1330 .collect();
1331 EventContent::Chord(Chord {
1332 pitches: pitch_vec?,
1333 })
1334 }
1335 _ => {
1336 return Err(ErrorSource::Runtime(
1337 "Expected pitch, chord, or list of pitches".to_string(),
1338 )
1339 .with_span(expression.span))
1340 }
1341 };
1342
1343 let mut event = MusicalEvent {
1344 duration,
1345 content,
1346 dynamic: None,
1347 attributes: Vec::new(),
1348 offset: Fraction::new(0, 1),
1349 };
1350
1351 if let Some(dyn_expr) = dynamic {
1352 let dyn_val = self.evaluate_expression(dyn_expr)?;
1353 if let Value::Dynamic(d) = dyn_val {
1354 event.dynamic = Some(d);
1355 }
1356 }
1357
1358 for attr_expr in attributes {
1359 let attr_val = self.evaluate_expression(attr_expr)?;
1360 if let Value::Attribute(a) = attr_val {
1361 event.attributes.push(a);
1362 }
1363 }
1364
1365 Ok(Value::MusicalEvent(event))
1366 }
1367 Expression::Part { name, body, .. } => {
1368 let part_name = if let Some(name_expr) = name {
1369 let name_val = self.evaluate_expression(name_expr)?;
1370 match name_val {
1371 Value::String(s) => Some(s),
1372 _ => None,
1373 }
1374 } else {
1375 None
1376 };
1377
1378 let mut part = Part::new(part_name);
1379 let initial_time_offset = self.current_time_offset;
1380 self.current_time_offset = Fraction::new(0, 1); match body.node {
1384 Expression::Block { ref statements, .. } => {
1385 self.environment.push_scope();
1386 let mut collected_changes_in_scope = Vec::new();
1387
1388 for stmt in statements {
1389 let result = self.execute_statement(stmt)?;
1390 match result {
1391 ExecutionResult::Value(val) => match val {
1392 Value::MusicalEvent(event) => {
1393 let mut event_with_offset = event.clone();
1394 event_with_offset.offset = self.current_time_offset;
1395 part.add_event(event_with_offset);
1396 self.current_time_offset += event.total_duration();
1397 }
1398 Value::Staff(staff) => {
1399 part.add_staff(staff);
1400 }
1401 Value::ContextChange(change) => {
1402 collected_changes_in_scope.push(change);
1403 }
1404 Value::List(items) => {
1405 for item in items {
1406 if let Value::MusicalEvent(event) = item {
1407 let mut event_with_offset = event.clone();
1408 event_with_offset.offset = self.current_time_offset;
1409 part.add_event(event_with_offset);
1410 self.current_time_offset += event.total_duration();
1411 }
1412 }
1413 }
1414 Value::Tuple(elements) => {
1415 let staff = self.build_staff_from_tuple(
1416 elements,
1417 part.staves.len(),
1418 &stmt.span,
1419 )?;
1420 part.add_staff(staff);
1421 }
1422 _ => {}
1423 },
1424 ExecutionResult::Control(_) => break,
1425 }
1426 }
1427
1428 self.environment.pop_scope();
1429 part.context_changes.extend(collected_changes_in_scope);
1430 }
1431 _ => {
1432 let body_val = self.evaluate_expression(body)?;
1434 match body_val {
1435 Value::MusicalEvent(event) => {
1436 let mut event_with_offset = event.clone();
1437 event_with_offset.offset = self.current_time_offset;
1438 part.add_event(event_with_offset);
1439 self.current_time_offset += event.total_duration();
1440 }
1441 Value::Staff(staff) => {
1442 part.add_staff(staff);
1443 }
1444 Value::ContextChange(change) => {
1445 part.add_context_change(change);
1446 }
1447 Value::List(items) => {
1448 for item in items {
1449 if let Value::MusicalEvent(event) = item {
1450 let mut event_with_offset = event.clone();
1451 event_with_offset.offset = self.current_time_offset;
1452 part.add_event(event_with_offset);
1453 self.current_time_offset += event.total_duration();
1454 }
1455 }
1456 }
1457 Value::Tuple(elements) => {
1458 let staff = self.build_staff_from_tuple(
1459 elements,
1460 part.staves.len(),
1461 &expression.span,
1462 )?;
1463 part.add_staff(staff);
1464 }
1465 _ => {}
1466 }
1467 }
1468 }
1469 self.current_time_offset = initial_time_offset; Ok(Value::Part(part))
1471 }
1472 Expression::Staff { number, body, .. } => {
1473 let number_val = self.evaluate_expression(number)?;
1474 let number = match number_val {
1475 Value::Number(n) => n as u32,
1476 _ => {
1477 return Err(
1478 ErrorSource::Runtime("Expected number for staff".to_string())
1479 .with_span(expression.span),
1480 )
1481 }
1482 };
1483
1484 let mut staff = Staff::new(number);
1485 let initial_time_offset = self.current_time_offset;
1486 self.current_time_offset = Fraction::new(0, 1); let body_val = self.evaluate_expression(body)?;
1489 match body_val {
1490 Value::MusicalEvent(event) => {
1491 let voice = self.build_voice(vec![Value::MusicalEvent(event)])?;
1492 staff = staff.add_voice(voice);
1493 }
1494 Value::List(events) => {
1495 let voice = self.build_voice(events)?;
1496 staff = staff.add_voice(voice);
1497 }
1498 Value::Tuple(elements) => {
1499 for voice_val in elements {
1500 let events_for_voice = match voice_val {
1501 Value::List(events) => events,
1502 Value::MusicalEvent(event) => match event.content {
1503 EventContent::Sequence(events) => {
1504 events.into_iter().map(Value::MusicalEvent).collect()
1505 }
1506 _ => vec![Value::MusicalEvent(event)],
1507 },
1508 _ => {
1509 return Err(ErrorSource::Runtime(
1510 "Tuples in a staff must contain lists or musical events."
1511 .to_string(),
1512 )
1513 .with_span(expression.span));
1514 }
1515 };
1516 let voice = self.build_voice(events_for_voice)?;
1517 staff = staff.add_voice(voice);
1518 }
1519 }
1520 Value::ContextChange(change) => {
1521 staff.add_context_change(change);
1522 }
1523 _ => {}
1524 }
1525
1526 if let Expression::Block { statements, .. } = &body.node {
1528 for stmt in statements {
1529 if let Statement::Metadata { key, value, .. } = &stmt.node {
1530 let evaluated_value = self.evaluate_expression(value)?;
1531 let metadata_key = MetadataKey::try_from(Value::String(key.clone()))
1532 .map_err(|e| e.with_span(value.span))?;
1533 let metadata_value = self.create_metadata_value(
1534 &metadata_key,
1535 evaluated_value,
1536 &value.span,
1537 )?;
1538 let change = ContextChange {
1539 key: metadata_key,
1540 value: metadata_value,
1541 time_offset: self.current_time_offset,
1542 };
1543 staff.add_context_change(change);
1544 }
1545 }
1546 }
1547
1548 self.current_time_offset = initial_time_offset; Ok(Value::Staff(staff))
1550 }
1551 Expression::Timeline { body, .. } => {
1552 let mut timeline = Timeline::default();
1553 let initial_time_offset = self.current_time_offset;
1554 self.current_time_offset = Fraction::new(0, 1); match body.node {
1558 Expression::Block { ref statements, .. } => {
1559 self.environment.push_scope();
1560 let mut collected_changes_in_scope = Vec::new();
1561
1562 for stmt in statements {
1563 let result = self.execute_statement(stmt)?;
1564 match result {
1565 ExecutionResult::Value(val) => match val {
1566 Value::Part(part) => {
1567 timeline.add_part(part);
1568 }
1569 Value::List(parts) => {
1570 for part_val in parts {
1571 if let Value::Part(part) = part_val {
1572 timeline.add_part(part);
1573 }
1574 }
1575 }
1576 Value::ContextChange(change) => {
1577 collected_changes_in_scope.push(change);
1578 }
1579 _ => {}
1580 },
1581 ExecutionResult::Control(_) => break,
1582 }
1583 }
1584
1585 self.environment.pop_scope();
1586 timeline.context_changes.extend(collected_changes_in_scope);
1587 }
1588 _ => {
1589 let body_val = self.evaluate_expression(body)?;
1590 match body_val {
1591 Value::Part(part) => {
1592 timeline.add_part(part);
1593 }
1594 Value::List(parts) => {
1595 for part_val in parts {
1596 if let Value::Part(part) = part_val {
1597 timeline.add_part(part);
1598 }
1599 }
1600 }
1601 Value::ContextChange(change) => {
1602 timeline.add_context_change(change);
1603 }
1604 _ => {}
1605 }
1606 }
1607 }
1608 self.current_time_offset = initial_time_offset; Ok(Value::Timeline(timeline))
1610 }
1611 Expression::Movement { name, body, .. } => {
1612 let movement_name = if let Some(name_expr) = name {
1613 let name_val = self.evaluate_expression(name_expr)?;
1614 match name_val {
1615 Value::String(s) => Some(s),
1616 _ => None,
1617 }
1618 } else {
1619 None
1620 };
1621
1622 let mut movement = Movement::new(movement_name);
1623 let initial_time_offset = self.current_time_offset;
1624 self.current_time_offset = Fraction::new(0, 1); match body.node {
1628 Expression::Block { ref statements, .. } => {
1629 self.environment.push_scope();
1630 let mut collected_changes_in_scope = Vec::new();
1631
1632 for stmt in statements {
1633 let result = self.execute_statement(stmt)?;
1634 match result {
1635 ExecutionResult::Value(val) => match val {
1636 Value::Timeline(timeline) => {
1637 movement = movement.with_timeline(timeline);
1638 }
1639 Value::ContextChange(change) => {
1640 collected_changes_in_scope.push(change);
1641 }
1642 _ => {}
1643 },
1644 ExecutionResult::Control(_) => break,
1645 }
1646 }
1647
1648 self.environment.pop_scope();
1649 movement.context_changes.extend(collected_changes_in_scope);
1650 }
1651 _ => {
1652 let body_val = self.evaluate_expression(body)?;
1653 match body_val {
1654 Value::Timeline(timeline) => {
1655 movement = movement.with_timeline(timeline);
1656 }
1657 Value::ContextChange(change) => {
1658 movement.add_context_change(change);
1659 }
1660 _ => {
1661 return Err(ErrorSource::Runtime(
1662 "Movement body must contain a timeline or context changes"
1663 .to_string(),
1664 )
1665 .with_span(expression.span))
1666 }
1667 }
1668 }
1669 }
1670 self.current_time_offset = initial_time_offset; Ok(Value::Movement(movement))
1672 }
1673 Expression::Score { name, body, .. } => {
1674 let score_name = if let Some(name_expr) = name {
1675 let name_val = self.evaluate_expression(name_expr)?;
1676 match name_val {
1677 Value::String(s) => Some(s),
1678 _ => None,
1679 }
1680 } else {
1681 None
1682 };
1683
1684 let mut score = Score::default();
1685 if let Some(name) = score_name {
1686 score = score.with_name(name);
1687 }
1688 let initial_time_offset = self.current_time_offset;
1689 self.current_time_offset = Fraction::new(0, 1); match body.node {
1693 Expression::Block { ref statements, .. } => {
1694 self.environment.push_scope();
1695 let mut collected_changes_in_scope = Vec::new();
1696
1697 for stmt in statements {
1698 let result = self.execute_statement(stmt)?;
1699 match result {
1700 ExecutionResult::Value(val) => match val {
1701 Value::Timeline(timeline) => {
1702 score.set_timeline(timeline);
1703 }
1704 Value::Movement(movement) => {
1705 score.add_movement(movement);
1706 }
1707 Value::ContextChange(change) => {
1708 collected_changes_in_scope.push(change);
1709 }
1710 Value::List(items) => {
1711 for item in items {
1712 match item {
1713 Value::Movement(movement) => {
1714 score.add_movement(movement);
1715 }
1716 Value::Timeline(timeline) => {
1717 score.set_timeline(timeline);
1718 }
1719 Value::ContextChange(change) => {
1720 collected_changes_in_scope.push(change);
1721 }
1722 _ => {}
1723 }
1724 }
1725 }
1726 _ => {}
1727 },
1728 ExecutionResult::Control(_) => break,
1729 }
1730 }
1731
1732 self.environment.pop_scope();
1733 score.context_changes.extend(collected_changes_in_scope);
1734 }
1735 _ => {
1736 let body_val = self.evaluate_expression(body)?;
1737 match body_val {
1738 Value::Timeline(timeline) => {
1739 score.set_timeline(timeline);
1740 }
1741 Value::Movement(movement) => {
1742 score.add_movement(movement);
1743 }
1744 Value::ContextChange(change) => {
1745 score.add_context_change(change);
1746 }
1747 Value::List(items) => {
1748 for item in items {
1749 match item {
1750 Value::Movement(movement) => {
1751 score.add_movement(movement);
1752 }
1753 Value::Timeline(timeline) => {
1754 score.set_timeline(timeline);
1755 }
1756 Value::ContextChange(change) => {
1757 score.add_context_change(change);
1758 }
1759 _ => {}
1760 }
1761 }
1762 }
1763 _ => {}
1764 }
1765 }
1766 }
1767 self.current_time_offset = initial_time_offset; Ok(Value::Score(score))
1769 }
1770 }
1771 }
1772
1773 fn evaluate_binary_op(
1778 &self,
1779 left: &Value,
1780 operator: &BinaryOp,
1781 right: &Value,
1782 span: &crate::errors::Span,
1783 ) -> Result<Value> {
1784 match (left, operator, right) {
1785 (Value::Number(a), BinaryOp::Add, Value::Number(b)) => Ok(Value::Number(a + b)),
1787 (Value::Number(a), BinaryOp::Subtract, Value::Number(b)) => Ok(Value::Number(a - b)),
1788 (Value::Number(a), BinaryOp::Multiply, Value::Number(b)) => Ok(Value::Number(a * b)),
1789 (Value::Number(a), BinaryOp::Divide, Value::Number(b)) => {
1790 if *b == 0.0 {
1791 Err(ErrorSource::Runtime("Division by zero".to_string()).with_span(*span))
1792 } else {
1793 Ok(Value::Number(a / b))
1794 }
1795 }
1796 (Value::Number(a), BinaryOp::Modulo, Value::Number(b)) => Ok(Value::Number(a % b)),
1797
1798 (Value::String(a), BinaryOp::Add, Value::String(b)) => {
1800 Ok(Value::String(format!("{a}{b}")))
1801 }
1802
1803 (Value::List(a), BinaryOp::Add, Value::List(b)) => {
1805 let mut result = a.clone();
1806 result.extend(b.iter().cloned());
1807 Ok(Value::List(result))
1808 }
1809 (Value::List(a), BinaryOp::Multiply, Value::Number(n)) => {
1810 let n = *n as usize;
1811 let mut result = Vec::new();
1812 for _ in 0..n {
1813 result.extend(a.clone());
1814 }
1815 Ok(Value::List(result))
1816 }
1817
1818 (Value::Duration(a), BinaryOp::Add, Value::Duration(b)) => Ok(Value::Duration(a + b)),
1820 (Value::Duration(a), BinaryOp::Multiply, Value::Number(b)) => {
1821 Ok(Value::Duration(a * (*b as u32)))
1822 }
1823
1824 (Value::Pitch(p), BinaryOp::Add, Value::Number(n)) => {
1826 Ok(Value::Pitch(p.transpose(*n as i32)))
1827 }
1828 (Value::Pitch(p), BinaryOp::Subtract, Value::Number(n)) => {
1829 Ok(Value::Pitch(p.transpose(-(*n as i32))))
1830 }
1831
1832 (Value::PitchClass(pc), BinaryOp::Add, Value::Number(n)) => {
1834 Ok(Value::PitchClass(pc.transpose(*n as i32)))
1835 }
1836 (Value::PitchClass(pc), BinaryOp::Subtract, Value::Number(n)) => {
1837 Ok(Value::PitchClass(pc.transpose(-(*n as i32))))
1838 }
1839
1840 (Value::Part(a), BinaryOp::Add, Value::Part(b)) => Ok(Value::Part(a.merge(b))),
1843
1844 (Value::PitchClassSet(pcs), BinaryOp::Add, Value::Number(n)) => {
1846 Ok(Value::PitchClassSet(pcs.transpose(*n as i32)))
1847 }
1848 (Value::PitchClassSet(pcs), BinaryOp::Subtract, Value::Number(n)) => {
1849 Ok(Value::PitchClassSet(pcs.transpose(-(*n as i32))))
1850 }
1851
1852 (Value::Number(a), BinaryOp::Equal, Value::Number(b)) => Ok(Value::Boolean(a == b)),
1854 (Value::Number(a), BinaryOp::NotEqual, Value::Number(b)) => Ok(Value::Boolean(a != b)),
1855 (Value::Number(a), BinaryOp::Less, Value::Number(b)) => Ok(Value::Boolean(a < b)),
1856 (Value::Number(a), BinaryOp::Greater, Value::Number(b)) => Ok(Value::Boolean(a > b)),
1857 (Value::Number(a), BinaryOp::LessEqual, Value::Number(b)) => Ok(Value::Boolean(a <= b)),
1858 (Value::Number(a), BinaryOp::GreaterEqual, Value::Number(b)) => {
1859 Ok(Value::Boolean(a >= b))
1860 }
1861
1862 (Value::String(a), BinaryOp::Equal, Value::String(b)) => Ok(Value::Boolean(a == b)),
1863 (Value::String(a), BinaryOp::NotEqual, Value::String(b)) => Ok(Value::Boolean(a != b)),
1864
1865 (Value::Boolean(a), BinaryOp::Equal, Value::Boolean(b)) => Ok(Value::Boolean(a == b)),
1866 (Value::Boolean(a), BinaryOp::NotEqual, Value::Boolean(b)) => {
1867 Ok(Value::Boolean(a != b))
1868 }
1869
1870 (Value::Boolean(a), BinaryOp::And, Value::Boolean(b)) => Ok(Value::Boolean(*a && *b)),
1872 (Value::Boolean(a), BinaryOp::Or, Value::Boolean(b)) => Ok(Value::Boolean(*a || *b)),
1873
1874 _ => Err(ErrorSource::Type(format!(
1875 "Unsupported operation: {} {:?} {}",
1876 left.type_name(),
1877 operator,
1878 right.type_name()
1879 ))
1880 .with_span(*span)),
1881 }
1882 }
1883
1884 fn evaluate_unary_op(
1888 &self,
1889 operator: &UnaryOp,
1890 operand: &Value,
1891 span: &crate::errors::Span,
1892 ) -> Result<Value> {
1893 match (operator, operand) {
1894 (UnaryOp::Minus, Value::Number(n)) => Ok(Value::Number(-n)),
1895 (UnaryOp::Not, Value::Boolean(b)) => Ok(Value::Boolean(!b)),
1896 (UnaryOp::Not, val) => Ok(Value::Boolean(!val.is_truthy())),
1897 _ => Err(ErrorSource::Type(format!(
1898 "Unsupported unary operation: {:?} {}",
1899 operator,
1900 operand.type_name()
1901 ))
1902 .with_span(*span)),
1903 }
1904 }
1905
1906 fn call_function(
1912 &mut self,
1913 function: &Value,
1914 args: &[Value],
1915 kwargs: &[(String, Value)],
1916 span: &crate::errors::Span,
1917 ) -> Result<Value> {
1918 match function {
1919 Value::Function { params, body, .. } => {
1920 if args.len() != params.len() {
1921 return Err(ErrorSource::Runtime(format!(
1922 "Expected {} arguments, got {}",
1923 params.len(),
1924 args.len()
1925 ))
1926 .with_span(*span));
1927 }
1928
1929 self.environment.push_scope();
1930
1931 for (param, arg) in params.iter().zip(args.iter()) {
1933 self.environment.define(param, arg.clone());
1934 }
1935
1936 let mut result = Value::Nil;
1938 for (i, stmt) in body.iter().enumerate() {
1939 let is_last = i == body.len() - 1;
1940
1941 match self.execute_statement(stmt)? {
1942 ExecutionResult::Value(val) => {
1943 if is_last {
1944 result = val;
1945 }
1946 }
1947 ExecutionResult::Control(ControlFlow::Return(val)) => {
1948 self.environment.pop_scope();
1949 return Ok(val);
1950 }
1951 ExecutionResult::Control(ControlFlow::None) => {}
1952 }
1953 }
1954
1955 self.environment.pop_scope();
1956 Ok(result)
1957 }
1958 Value::BuiltinFunction(name) => {
1959 call_builtin_function(name, args, kwargs, span, &self.environment.builtins)
1960 }
1961 _ => Err(ErrorSource::Runtime("Not a function".to_string()).with_span(*span)),
1962 }
1963 }
1964}
1965
1966fn process_value_octaves(value: &mut Value, last_octave: &mut Option<i8>) {
1971 match value {
1972 Value::Pitch(p) => {
1973 *last_octave = Some(p.octave);
1974 }
1975 Value::PitchClass(pc) => {
1976 if let Some(oct) = *last_octave {
1977 *value = Value::Pitch(Pitch {
1978 pitch_class: *pc,
1979 octave: oct,
1980 });
1981 }
1982 }
1983 Value::List(values) | Value::Tuple(values) => {
1984 for val in values {
1985 process_value_octaves(val, last_octave);
1986 }
1987 }
1988 Value::MusicalEvent(event) => {
1989 *last_octave = match &event.content {
1991 EventContent::Note(p) => Some(p.octave),
1992 EventContent::Chord(c) => c.pitches.last().map(|p| p.octave),
1993 EventContent::Sequence(events) => events.last().and_then(|e| match &e.content {
1994 EventContent::Note(p) => Some(p.octave),
1995 EventContent::Chord(c) => c.pitches.last().map(|p| p.octave),
1996 _ => None,
1997 }),
1998 _ => None,
1999 };
2000 }
2001 Value::ContextChange(_) => {
2002 }
2004 _ => {}
2005 }
2006}
2007
2008fn call_builtin_function(
2012 name: &str,
2013 args: &[Value],
2014 kwargs: &[(String, Value)],
2015 span: &crate::errors::Span,
2016 registry: &BuiltinRegistry,
2017) -> Result<Value> {
2018 registry.call(name, args, kwargs, span)
2019}