1use pflow_tokenmodel::schema::{self, Schema};
4
5use crate::ast::*;
6
7pub 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
64pub 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}