Skip to main content

pflow_dsl/
interpret.rs

1//! AST to Schema conversion.
2
3use pflow_tokenmodel::schema::{self, Schema};
4
5use crate::ast::*;
6
7/// Converts a parsed SchemaNode into a tokenmodel Schema.
8pub fn interpret(node: &SchemaNode) -> Result<Schema, String> {
9    let mut schema = Schema::new(&node.name);
10    schema.version = node.version.clone();
11
12    for s in &node.states {
13        let kind = if s.kind == "token" {
14            schema::Kind::Token
15        } else {
16            schema::Kind::Data
17        };
18
19        let initial = match &s.initial {
20            Some(InitialValue::Int(n)) => Some(serde_json::Value::Number((*n).into())),
21            Some(InitialValue::Str(s)) => Some(serde_json::Value::String(s.clone())),
22            Some(InitialValue::Nil) | None => None,
23        };
24
25        schema.add_state(schema::State {
26            id: s.id.clone(),
27            kind,
28            typ: s.typ.clone(),
29            initial,
30            exported: s.exported,
31        });
32    }
33
34    for a in &node.actions {
35        schema.add_action(schema::Action {
36            id: a.id.clone(),
37            guard: a.guard.clone(),
38            event_id: String::new(),
39            event_bindings: None,
40        });
41    }
42
43    for a in &node.arcs {
44        schema.add_arc(schema::Arc {
45            source: a.source.clone(),
46            target: a.target.clone(),
47            keys: a.keys.clone(),
48            value: a.value.clone(),
49        });
50    }
51
52    for c in &node.constraints {
53        schema.add_constraint(schema::Constraint {
54            id: c.id.clone(),
55            expr: c.expr.clone(),
56        });
57    }
58
59    schema.validate().map_err(|e| e.to_string())?;
60
61    Ok(schema)
62}
63
64/// Parse DSL input and return a Schema.
65pub fn parse_schema(input: &str) -> Result<Schema, String> {
66    let node = crate::parser::parse(input)?;
67    interpret(&node)
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_interpret_basic() {
76        let input = r#"(schema test
77  (version v1.0.0)
78  (states
79    (state count :kind token :initial 5)
80  )
81  (actions
82    (action inc)
83  )
84  (arcs
85    (arc inc -> count)
86  )
87)"#;
88
89        let schema = parse_schema(input).unwrap();
90        assert_eq!(schema.name, "test");
91        assert_eq!(schema.states.len(), 1);
92        assert!(schema.states[0].is_token());
93        assert_eq!(schema.states[0].initial_tokens(), 5);
94    }
95}