devalang_wasm/language/preprocessor/resolver/
trigger.rs1use crate::language::preprocessor::resolver::value::resolve_value;
2use crate::language::syntax::ast::{DurationValue, Statement, StatementKind, Value};
3use std::collections::HashMap;
4
5pub 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}