appcore_filemaker/source_element.rs
1// =============================================================================
2// #######
3// ### ### F: source_element.rs
4// ## ## ## ## P: AppCore-Runtime
5// ## ##
6// C: 2026/08/30 05:00:00 by dnettoRaw
7// ## ## ## ## U: 2026/08/30 05:00:00 by dnettoRaw
8// ########### S: 1.0.2-rc
9// =============================================================================
10
11use crate::{ElementIr, ElementSource, ErrorCode, FileMakerError, ResourceLimits, Result};
12
13impl ElementSource {
14 /// Validates and converts one static, self-contained source element to IR.
15 ///
16 /// This compact boundary is suitable for programmatic and tool-driven
17 /// Canvas additions. Components, props, slots, named or conditional
18 /// styles, bindings, conditions, and repeats require the complete
19 /// [`crate::Compiler`] pipeline and are rejected here.
20 pub fn to_ir(&self, limits: &ResourceLimits) -> Result<ElementIr> {
21 validate_self_contained(self)?;
22 crate::source_build::self_contained_element_to_ir(self, limits)
23 }
24}
25
26fn validate_self_contained(root: &ElementSource) -> Result<()> {
27 let mut stack = vec![root];
28 while let Some(element) = stack.pop() {
29 if element.component.is_some()
30 || !element.props.is_empty()
31 || !element.slots.is_empty()
32 || !element.styles.is_empty()
33 || !element.style_rules.is_empty()
34 || element.binding.is_some()
35 || element.when.is_some()
36 || element.repeat.is_some()
37 {
38 return Err(FileMakerError::new(
39 ErrorCode::SchemaField,
40 "compact element conversion does not run compiler expansion or data binding",
41 )
42 .at(element.id.clone()));
43 }
44 stack.extend(element.children.iter());
45 }
46 Ok(())
47}