Skip to main content

nargo_ir/
template.rs

1#![warn(missing_docs)]
2
3//! 模板模块
4//! 
5//! 提供 HXO 模板的 IR 表示和相关功能。
6
7use nargo_types::{Result, Span};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11use crate::expr::JsExpr;
12use crate::types::{MAX_ARRAY_LENGTH, MAX_RECURSION_DEPTH, MAX_STRING_LENGTH, IRError, Trivia};
13
14/// 测试 IR
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
16pub struct TestIR {
17    /// 测试名称
18    pub name: String,
19    /// 测试体
20    pub body: crate::program::JsProgram,
21    /// 位置信息
22    pub span: Span,
23}
24
25impl TestIR {
26    /// 验证测试的有效性
27    pub fn validate(&self) -> Result<()> {
28        if self.name.len() > MAX_STRING_LENGTH {
29            return Err(IRError::SizeLimitExceeded("Test name length exceeded".to_string()).into());
30        }
31        self.body.validate()
32    }
33}
34
35/// 模板 IR
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
37pub struct TemplateIR {
38    /// 模板节点
39    pub nodes: Vec<TemplateNodeIR>,
40    /// 位置信息
41    #[serde(default)]
42    pub span: Span,
43}
44
45impl TemplateIR {
46    /// 验证模板的有效性
47    pub fn validate(&self) -> Result<()> {
48        if self.nodes.len() > MAX_ARRAY_LENGTH {
49            return Err(IRError::SizeLimitExceeded("Template nodes length exceeded".to_string()).into());
50        }
51        for node in &self.nodes {
52            node.validate(0)?;
53        }
54        Ok(())
55    }
56}
57
58/// 模板节点 IR
59#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
60pub enum TemplateNodeIR {
61    /// 元素
62    Element(ElementIR),
63    /// if 节点
64    If(IfNodeIR),
65    /// for 节点
66    For(ForNodeIR),
67    /// 文本
68    Text(String, #[serde(default)] Span, #[serde(default)] Trivia),
69    /// 插值
70    Interpolation(ExpressionIR),
71    /// 注释
72    Comment(String, #[serde(default)] Span, #[serde(default)] Trivia),
73    /// 提升节点
74    Hoisted(String),
75}
76
77impl TemplateNodeIR {
78    /// 验证模板节点的有效性
79    pub fn validate(&self, depth: usize) -> Result<()> {
80        if depth > MAX_RECURSION_DEPTH {
81            return Err(IRError::CircularReference("Template node recursion depth exceeded".to_string()).into());
82        }
83
84        match self {
85            TemplateNodeIR::Element(element) => element.validate(depth + 1),
86            TemplateNodeIR::If(if_node) => if_node.validate(depth + 1),
87            TemplateNodeIR::For(for_node) => for_node.validate(depth + 1),
88            TemplateNodeIR::Text(text, _, _) => {
89                if text.len() > MAX_STRING_LENGTH {
90                    return Err(IRError::SizeLimitExceeded("Text length exceeded".to_string()).into());
91                }
92                Ok(())
93            }
94            TemplateNodeIR::Interpolation(expr) => expr.validate(depth + 1),
95            TemplateNodeIR::Comment(comment, _, _) => {
96                if comment.len() > MAX_STRING_LENGTH {
97                    return Err(IRError::SizeLimitExceeded("Comment length exceeded".to_string()).into());
98                }
99                Ok(())
100            }
101            TemplateNodeIR::Hoisted(key) => {
102                if key.len() > MAX_STRING_LENGTH {
103                    return Err(IRError::SizeLimitExceeded("Hoisted key length exceeded".to_string()).into());
104                }
105                Ok(())
106            }
107        }
108    }
109}
110
111/// if 节点 IR
112#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
113pub struct IfNodeIR {
114    /// 条件
115    pub condition: ExpressionIR,
116    /// 真分支
117    pub consequent: Vec<TemplateNodeIR>,
118    /// 假分支(else 或 else if)
119    pub alternate: Option<Vec<TemplateNodeIR>>,
120    /// else if 分支
121    pub else_ifs: Vec<(ExpressionIR, Vec<TemplateNodeIR>)>,
122    /// 位置信息
123    #[serde(default)]
124    pub span: Span,
125}
126
127impl IfNodeIR {
128    /// 验证 if 节点的有效性
129    pub fn validate(&self, depth: usize) -> Result<()> {
130        if depth > MAX_RECURSION_DEPTH {
131            return Err(IRError::CircularReference("If node recursion depth exceeded".to_string()).into());
132        }
133
134        self.condition.validate(depth + 1)?;
135
136        if self.consequent.len() > MAX_ARRAY_LENGTH {
137            return Err(IRError::SizeLimitExceeded("If node consequent length exceeded".to_string()).into());
138        }
139        for node in &self.consequent {
140            node.validate(depth + 1)?;
141        }
142
143        if let Some(alternate) = &self.alternate {
144            if alternate.len() > MAX_ARRAY_LENGTH {
145                return Err(IRError::SizeLimitExceeded("If node alternate length exceeded".to_string()).into());
146            }
147            for node in alternate {
148                node.validate(depth + 1)?;
149            }
150        }
151
152        if self.else_ifs.len() > MAX_ARRAY_LENGTH {
153            return Err(IRError::SizeLimitExceeded("If node else ifs length exceeded".to_string()).into());
154        }
155        for (condition, body) in &self.else_ifs {
156            condition.validate(depth + 1)?;
157            if body.len() > MAX_ARRAY_LENGTH {
158                return Err(IRError::SizeLimitExceeded("If node else if body length exceeded".to_string()).into());
159            }
160            for node in body {
161                node.validate(depth + 1)?;
162            }
163        }
164
165        Ok(())
166    }
167}
168
169/// for 节点 IR
170#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
171pub struct ForNodeIR {
172    /// 迭代器
173    pub iterator: ForIteratorIR,
174    /// 循环体
175    pub body: Vec<TemplateNodeIR>,
176    /// 位置信息
177    #[serde(default)]
178    pub span: Span,
179}
180
181impl ForNodeIR {
182    /// 验证 for 节点的有效性
183    pub fn validate(&self, depth: usize) -> Result<()> {
184        if depth > MAX_RECURSION_DEPTH {
185            return Err(IRError::CircularReference("For node recursion depth exceeded".to_string()).into());
186        }
187
188        self.iterator.validate(depth + 1)?;
189
190        if self.body.len() > MAX_ARRAY_LENGTH {
191            return Err(IRError::SizeLimitExceeded("For node body length exceeded".to_string()).into());
192        }
193        for node in &self.body {
194            node.validate(depth + 1)?;
195        }
196
197        Ok(())
198    }
199}
200
201/// for 迭代器 IR
202#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
203pub struct ForIteratorIR {
204    /// 项目
205    pub item: String,
206    /// 索引
207    pub index: Option<String>,
208    /// 集合
209    pub collection: ExpressionIR,
210}
211
212impl ForIteratorIR {
213    /// 验证 for 迭代器的有效性
214    pub fn validate(&self, depth: usize) -> Result<()> {
215        if depth > MAX_RECURSION_DEPTH {
216            return Err(IRError::CircularReference("For iterator recursion depth exceeded".to_string()).into());
217        }
218
219        if self.item.len() > MAX_STRING_LENGTH {
220            return Err(IRError::SizeLimitExceeded("For iterator item length exceeded".to_string()).into());
221        }
222
223        if let Some(index) = &self.index {
224            if index.len() > MAX_STRING_LENGTH {
225                return Err(IRError::SizeLimitExceeded("For iterator index length exceeded".to_string()).into());
226            }
227        }
228
229        self.collection.validate(depth + 1)
230    }
231}
232
233/// 元素 IR
234#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
235pub struct ElementIR {
236    /// 标签名
237    pub tag: String,
238    /// 属性列表
239    pub attributes: Vec<AttributeIR>,
240    /// 子节点
241    pub children: Vec<TemplateNodeIR>,
242    /// 是否为静态元素
243    pub is_static: bool,
244    /// 位置信息
245    #[serde(default)]
246    pub span: Span,
247    /// Trivia 信息
248    #[serde(default)]
249    pub trivia: Trivia,
250}
251
252impl ElementIR {
253    /// 验证元素的有效性
254    pub fn validate(&self, depth: usize) -> Result<()> {
255        if depth > MAX_RECURSION_DEPTH {
256            return Err(IRError::CircularReference("Element recursion depth exceeded".to_string()).into());
257        }
258
259        if self.tag.len() > MAX_STRING_LENGTH {
260            return Err(IRError::SizeLimitExceeded("Element tag length exceeded".to_string()).into());
261        }
262
263        if self.attributes.len() > MAX_ARRAY_LENGTH {
264            return Err(IRError::SizeLimitExceeded("Element attributes length exceeded".to_string()).into());
265        }
266        for attr in &self.attributes {
267            attr.validate(depth + 1)?;
268        }
269
270        if self.children.len() > MAX_ARRAY_LENGTH {
271            return Err(IRError::SizeLimitExceeded("Element children length exceeded".to_string()).into());
272        }
273        for child in &self.children {
274            child.validate(depth + 1)?;
275        }
276
277        Ok(())
278    }
279}
280
281/// 属性 IR
282#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
283pub struct AttributeIR {
284    /// 属性名
285    pub name: String,
286    /// 属性值
287    pub value: Option<String>,
288    /// 属性值的 AST
289    pub value_ast: Option<JsExpr>,
290    /// 参数
291    pub argument: Option<String>,
292    /// 修饰符
293    pub modifiers: Vec<String>,
294    /// 是否为指令
295    pub is_directive: bool,
296    /// 是否为动态属性
297    pub is_dynamic: bool,
298    /// 位置信息
299    #[serde(default)]
300    pub span: Span,
301    /// Trivia 信息
302    #[serde(default)]
303    pub trivia: Trivia,
304}
305
306impl AttributeIR {
307    /// 验证属性的有效性
308    pub fn validate(&self, depth: usize) -> Result<()> {
309        if depth > MAX_RECURSION_DEPTH {
310            return Err(IRError::CircularReference("Attribute recursion depth exceeded".to_string()).into());
311        }
312
313        if self.name.len() > MAX_STRING_LENGTH {
314            return Err(IRError::SizeLimitExceeded("Attribute name length exceeded".to_string()).into());
315        }
316
317        if let Some(value) = &self.value {
318            if value.len() > MAX_STRING_LENGTH {
319                return Err(IRError::SizeLimitExceeded("Attribute value length exceeded".to_string()).into());
320            }
321        }
322
323        if let Some(value_ast) = &self.value_ast {
324            value_ast.validate(depth + 1)?;
325        }
326
327        if let Some(argument) = &self.argument {
328            if argument.len() > MAX_STRING_LENGTH {
329                return Err(IRError::SizeLimitExceeded("Attribute argument length exceeded".to_string()).into());
330            }
331        }
332
333        if self.modifiers.len() > MAX_ARRAY_LENGTH {
334            return Err(IRError::SizeLimitExceeded("Attribute modifiers length exceeded".to_string()).into());
335        }
336        for modifier in &self.modifiers {
337            if modifier.len() > MAX_STRING_LENGTH {
338                return Err(IRError::SizeLimitExceeded("Attribute modifier length exceeded".to_string()).into());
339            }
340        }
341
342        Ok(())
343    }
344}
345
346/// 表达式 IR
347#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
348pub struct ExpressionIR {
349    /// 表达式代码
350    pub code: String,
351    /// 表达式 AST
352    pub ast: Option<JsExpr>,
353    /// 是否为静态表达式
354    pub is_static: bool,
355    /// 位置信息
356    #[serde(default)]
357    pub span: Span,
358    /// Trivia 信息
359    #[serde(default)]
360    pub trivia: Trivia,
361}
362
363impl ExpressionIR {
364    /// 验证表达式的有效性
365    pub fn validate(&self, depth: usize) -> Result<()> {
366        if depth > MAX_RECURSION_DEPTH {
367            return Err(IRError::CircularReference("Expression IR recursion depth exceeded".to_string()).into());
368        }
369
370        if self.code.len() > MAX_STRING_LENGTH {
371            return Err(IRError::SizeLimitExceeded("Expression code length exceeded".to_string()).into());
372        }
373
374        if let Some(ast) = &self.ast {
375            ast.validate(depth + 1)?;
376        }
377
378        Ok(())
379    }
380
381    /// 检查表达式是否为空
382    pub fn is_empty(&self) -> bool {
383        self.code.is_empty() && self.ast.is_none() && self.trivia.is_empty()
384    }
385}
386
387/// 自定义块 IR
388#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
389pub struct CustomBlockIR {
390    /// 块名称
391    pub name: String,
392    /// 块内容
393    pub content: String,
394    /// 块属性
395    pub attributes: HashMap<String, String>,
396    /// 位置信息
397    #[serde(default)]
398    pub span: Span,
399    /// Trivia 信息
400    #[serde(default)]
401    pub trivia: Trivia,
402}
403
404impl CustomBlockIR {
405    /// 验证自定义块的有效性
406    pub fn validate(&self) -> Result<()> {
407        if self.name.len() > MAX_STRING_LENGTH {
408            return Err(IRError::SizeLimitExceeded("Custom block name length exceeded".to_string()).into());
409        }
410
411        if self.content.len() > MAX_STRING_LENGTH {
412            return Err(IRError::SizeLimitExceeded("Custom block content length exceeded".to_string()).into());
413        }
414
415        if self.attributes.len() > MAX_ARRAY_LENGTH {
416            return Err(IRError::SizeLimitExceeded("Custom block attributes size exceeded".to_string()).into());
417        }
418        for (key, value) in &self.attributes {
419            if key.len() > MAX_STRING_LENGTH {
420                return Err(IRError::SizeLimitExceeded("Custom block attribute key length exceeded".to_string()).into());
421            }
422            if value.len() > MAX_STRING_LENGTH {
423                return Err(IRError::SizeLimitExceeded("Custom block attribute value length exceeded".to_string()).into());
424            }
425        }
426
427        Ok(())
428    }
429
430    /// 检查自定义块是否为空
431    pub fn is_empty(&self) -> bool {
432        self.name.is_empty() && self.content.is_empty() && self.attributes.is_empty() && self.trivia.is_empty()
433    }
434}
435
436/// 样式 IR
437#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
438pub struct StyleIR {
439    /// 样式代码
440    pub code: String,
441    /// 样式语言
442    pub lang: String,
443    /// 是否为作用域样式
444    pub scoped: bool,
445    /// 位置信息
446    #[serde(default)]
447    pub span: Span,
448    /// Trivia 信息
449    #[serde(default)]
450    pub trivia: Trivia,
451}
452
453impl StyleIR {
454    /// 验证样式的有效性
455    pub fn validate(&self) -> Result<()> {
456        if self.code.len() > MAX_STRING_LENGTH {
457            return Err(IRError::SizeLimitExceeded("Style code length exceeded".to_string()).into());
458        }
459
460        if self.lang.len() > MAX_STRING_LENGTH {
461            return Err(IRError::SizeLimitExceeded("Style lang length exceeded".to_string()).into());
462        }
463
464        Ok(())
465    }
466
467    /// 检查样式是否为空
468    pub fn is_empty(&self) -> bool {
469        self.code.is_empty() && self.lang.is_empty() && self.trivia.is_empty()
470    }
471}
472
473/// 模板节点访问者 trait
474pub trait TemplateNodeVisitor<R> {
475    /// 访问元素节点
476    fn visit_element(&mut self, element: &ElementIR, depth: usize) -> R;
477    /// 访问 if 节点
478    fn visit_if(&mut self, if_node: &IfNodeIR, depth: usize) -> R;
479    /// 访问 for 节点
480    fn visit_for(&mut self, for_node: &ForNodeIR, depth: usize) -> R;
481    /// 访问文本节点
482    fn visit_text(&mut self, text: &String, span: &Span, trivia: &Trivia, depth: usize) -> R;
483    /// 访问插值节点
484    fn visit_interpolation(&mut self, expr: &ExpressionIR, depth: usize) -> R;
485    /// 访问注释节点
486    fn visit_comment(&mut self, comment: &String, span: &Span, trivia: &Trivia, depth: usize) -> R;
487    /// 访问提升节点
488    fn visit_hoisted(&mut self, key: &String, depth: usize) -> R;
489}
490
491impl TemplateNodeIR {
492    /// 接受访问者
493    pub fn accept<R>(&self, visitor: &mut dyn TemplateNodeVisitor<R>, depth: usize) -> R {
494        match self {
495            TemplateNodeIR::Element(element) => visitor.visit_element(element, depth),
496            TemplateNodeIR::If(if_node) => visitor.visit_if(if_node, depth),
497            TemplateNodeIR::For(for_node) => visitor.visit_for(for_node, depth),
498            TemplateNodeIR::Text(text, span, trivia) => visitor.visit_text(text, span, trivia, depth),
499            TemplateNodeIR::Interpolation(expr) => visitor.visit_interpolation(expr, depth),
500            TemplateNodeIR::Comment(comment, span, trivia) => visitor.visit_comment(comment, span, trivia, depth),
501            TemplateNodeIR::Hoisted(key) => visitor.visit_hoisted(key, depth),
502        }
503    }
504}