devalang_wasm/engine/audio/interpreter/statements/
arrow_call.rs1use crate::engine::functions::FunctionContext;
2use anyhow::{Result, anyhow};
4
5pub fn execute_arrow_call(
6 interpreter: &mut crate::engine::audio::interpreter::driver::AudioInterpreter,
7 target: &str,
8 method: &str,
9 args: &[crate::language::syntax::ast::Value],
10 chain: Option<&[crate::language::syntax::ast::Value]>,
11 cursor_time: f32,
12 tempo: f32,
13) -> Result<FunctionContext> {
14 let mut context = FunctionContext {
16 target: target.to_string(),
17 state: std::collections::HashMap::new(),
18 start_time: cursor_time,
19 duration: 0.0,
20 tempo,
21 };
22
23 context.set(
25 "method",
26 crate::language::syntax::ast::Value::String(method.to_string()),
27 );
28
29 let resolved_args: Vec<crate::language::syntax::ast::Value> = args
31 .iter()
32 .map(|v| interpreter.resolve_value(v))
33 .collect::<Result<Vec<_>>>()?;
34
35 if interpreter.function_registry.has(method) {
37 interpreter
38 .function_registry
39 .execute(method, &mut context, &resolved_args)?;
40 } else {
41 context.set(
43 "route_to",
44 crate::language::syntax::ast::Value::String(method.to_string()),
45 );
46 }
47
48 if let Some(chain_calls) = chain {
50 let mut unknown_effects: Vec<crate::language::syntax::ast::Value> = Vec::new();
53 for call_value in chain_calls {
54 if let crate::language::syntax::ast::Value::Map(call_map) = call_value {
55 let method_name = call_map
57 .get("method")
58 .and_then(|v| {
59 if let crate::language::syntax::ast::Value::String(s) = v {
60 Some(s.as_str())
61 } else {
62 None
63 }
64 })
65 .ok_or_else(|| anyhow!("Chain call missing method name"))?;
66
67 let method_args = call_map
68 .get("args")
69 .and_then(|v| {
70 if let crate::language::syntax::ast::Value::Array(a) = v {
71 Some(a.as_slice())
72 } else {
73 None
74 }
75 })
76 .unwrap_or(&[]);
77
78 let resolved_method_args: Vec<crate::language::syntax::ast::Value> = method_args
80 .iter()
81 .map(|v| interpreter.resolve_value(v))
82 .collect::<Result<Vec<_>>>()?;
83
84 if interpreter.function_registry.has(method_name) {
86 interpreter.function_registry.execute(
87 method_name,
88 &mut context,
89 &resolved_method_args,
90 )?;
91 } else {
92 let mut effect_map: std::collections::HashMap<
95 String,
96 crate::language::syntax::ast::Value,
97 > = std::collections::HashMap::new();
98 effect_map.insert(
99 "type".to_string(),
100 crate::language::syntax::ast::Value::String(method_name.to_string()),
101 );
102
103 if let Some(first_arg) = resolved_method_args.get(0) {
105 if let crate::language::syntax::ast::Value::Map(m) = first_arg {
106 for (k, v) in m.iter() {
107 effect_map.insert(k.clone(), v.clone());
108 }
109 } else {
110 effect_map.insert("value".to_string(), first_arg.clone());
112 }
113 }
114
115 unknown_effects.push(crate::language::syntax::ast::Value::Map(effect_map));
116 }
117 }
118 }
119
120 if !unknown_effects.is_empty() {
121 context.set(
122 "effects",
123 crate::language::syntax::ast::Value::Array(unknown_effects),
124 );
125 }
126 }
127
128 Ok(context)
129}