devalang_wasm/language/preprocessor/resolver/
trigger.rs

1use crate::language::preprocessor::resolver::value::resolve_value;
2use crate::language::syntax::ast::{DurationValue, Statement, StatementKind, Value};
3use std::collections::HashMap;
4
5/// Resolve trigger statement: expand duration and effect identifiers
6pub fn resolve_trigger(
7    stmt: &Statement,
8    entity: &str,
9    duration: &DurationValue,
10    effects: &Option<Value>,
11    variables: &HashMap<String, Value>,
12) -> Statement {
13    let final_duration = resolve_duration(duration, variables);
14    let final_effects = effects.as_ref().map(|e| resolve_value(e, variables, 0));
15
16    Statement::new(
17        StatementKind::Trigger {
18            entity: entity.to_string(),
19            duration: final_duration,
20            effects: final_effects,
21        },
22        Value::Null,
23        stmt.indent,
24        stmt.line,
25        stmt.column,
26    )
27}
28
29fn resolve_duration(duration: &DurationValue, variables: &HashMap<String, Value>) -> DurationValue {
30    match duration {
31        DurationValue::Identifier(name) => {
32            if let Some(val) = variables.get(name) {
33                match val {
34                    Value::Number(n) => DurationValue::Milliseconds(*n),
35                    Value::Identifier(s) if s == "auto" => DurationValue::Auto,
36                    Value::String(s) if s.ends_with("ms") => {
37                        if let Ok(ms) = s.trim_end_matches("ms").parse::<f32>() {
38                            return DurationValue::Milliseconds(ms);
39                        }
40                        DurationValue::Identifier(name.clone())
41                    }
42                    _ => DurationValue::Identifier(name.clone()),
43                }
44            } else {
45                DurationValue::Identifier(name.clone())
46            }
47        }
48        other => other.clone(),
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn test_resolve_trigger_with_duration_identifier() {
58        let mut vars = HashMap::new();
59        vars.insert("short".to_string(), Value::Number(100.0));
60
61        let stmt = Statement::new(
62            StatementKind::Trigger {
63                entity: "kick".to_string(),
64                duration: DurationValue::Identifier("short".to_string()),
65                effects: None,
66            },
67            Value::Null,
68            0,
69            1,
70            1,
71        );
72
73        let resolved = resolve_trigger(
74            &stmt,
75            "kick",
76            &DurationValue::Identifier("short".to_string()),
77            &None,
78            &vars,
79        );
80
81        if let StatementKind::Trigger { duration, .. } = &resolved.kind {
82            assert!(
83                matches!(duration, DurationValue::Milliseconds(ms) if (ms - 100.0).abs() < f32::EPSILON)
84            );
85        } else {
86            panic!("Expected trigger statement");
87        }
88    }
89}