Skip to main content

vize_relief/ast/
codegen.rs

1//! Code generation AST node types.
2//!
3//! Contains VNodeCall, JavaScript expression nodes, SSR codegen nodes,
4//! and all types used during code generation from the template AST.
5
6use vize_carton::{Box, Bump, PatchFlags, String, Vec};
7
8use super::{
9    RuntimeHelper,
10    core::{NodeType, SourceLocation},
11    expressions::{CompoundExpressionNode, ExpressionNode, SimpleExpressionNode},
12    nodes::TemplateChildNode,
13};
14
15/// VNode call expression
16#[derive(Debug)]
17pub struct VNodeCall<'a> {
18    pub tag: VNodeTag<'a>,
19    pub props: Option<PropsExpression<'a>>,
20    pub children: Option<VNodeChildren<'a>>,
21    pub patch_flag: Option<PatchFlags>,
22    pub dynamic_props: Option<DynamicProps<'a>>,
23    pub directives: Option<DirectiveArguments<'a>>,
24    pub is_block: bool,
25    pub disable_tracking: bool,
26    pub is_component: bool,
27    pub loc: SourceLocation,
28}
29
30impl<'a> VNodeCall<'a> {
31    pub fn node_type(&self) -> NodeType {
32        NodeType::VNodeCall
33    }
34}
35
36/// VNode tag type
37#[derive(Debug)]
38pub enum VNodeTag<'a> {
39    String(String),
40    Symbol(RuntimeHelper),
41    Call(Box<'a, CallExpression<'a>>),
42}
43
44/// VNode children type
45#[derive(Debug)]
46pub enum VNodeChildren<'a> {
47    Multiple(Vec<'a, TemplateChildNode<'a>>),
48    Single(TemplateTextChildNode<'a>),
49    Slots(Box<'a, SlotsExpression<'a>>),
50    ForRenderList(Box<'a, CallExpression<'a>>),
51    Simple(Box<'a, SimpleExpressionNode<'a>>),
52    Cache(Box<'a, CacheExpression<'a>>),
53}
54
55/// Template text child node
56#[derive(Debug)]
57pub enum TemplateTextChildNode<'a> {
58    Text(Box<'a, super::elements::TextNode>),
59    Interpolation(Box<'a, super::elements::InterpolationNode<'a>>),
60    Compound(Box<'a, CompoundExpressionNode<'a>>),
61}
62
63/// Props expression type
64#[derive(Debug)]
65pub enum PropsExpression<'a> {
66    Object(Box<'a, ObjectExpression<'a>>),
67    Call(Box<'a, CallExpression<'a>>),
68    Simple(Box<'a, SimpleExpressionNode<'a>>),
69}
70
71/// Dynamic props type
72#[derive(Debug)]
73pub enum DynamicProps<'a> {
74    String(String),
75    Simple(Box<'a, SimpleExpressionNode<'a>>),
76}
77
78/// Directive arguments
79#[derive(Debug)]
80pub struct DirectiveArguments<'a> {
81    pub elements: Vec<'a, DirectiveArgumentNode<'a>>,
82    pub loc: SourceLocation,
83}
84
85/// Single directive argument
86#[derive(Debug)]
87pub struct DirectiveArgumentNode<'a> {
88    pub directive: String,
89    pub exp: Option<ExpressionNode<'a>>,
90    pub arg: Option<ExpressionNode<'a>>,
91    pub modifiers: Option<Box<'a, ObjectExpression<'a>>>,
92}
93
94/// Slots expression
95#[derive(Debug)]
96pub enum SlotsExpression<'a> {
97    Object(Box<'a, ObjectExpression<'a>>),
98    Dynamic(Box<'a, CallExpression<'a>>),
99}
100
101// ============================================================================
102// JavaScript AST Nodes
103// ============================================================================
104
105/// All JavaScript child node types for codegen
106#[derive(Debug)]
107pub enum JsChildNode<'a> {
108    VNodeCall(Box<'a, VNodeCall<'a>>),
109    Call(Box<'a, CallExpression<'a>>),
110    Object(Box<'a, ObjectExpression<'a>>),
111    Array(Box<'a, ArrayExpression<'a>>),
112    Function(Box<'a, FunctionExpression<'a>>),
113    Conditional(Box<'a, ConditionalExpression<'a>>),
114    Cache(Box<'a, CacheExpression<'a>>),
115    Assignment(Box<'a, AssignmentExpression<'a>>),
116    Sequence(Box<'a, SequenceExpression<'a>>),
117    SimpleExpression(Box<'a, SimpleExpressionNode<'a>>),
118    CompoundExpression(Box<'a, CompoundExpressionNode<'a>>),
119}
120
121/// Codegen node union type
122#[derive(Debug)]
123pub enum CodegenNode<'a> {
124    TemplateChild(TemplateChildNode<'a>),
125    JsChild(JsChildNode<'a>),
126    BlockStatement(Box<'a, BlockStatement<'a>>),
127}
128
129/// Call expression
130#[derive(Debug)]
131pub struct CallExpression<'a> {
132    pub callee: Callee,
133    pub arguments: Vec<'a, CallArgument<'a>>,
134    pub loc: SourceLocation,
135}
136
137impl<'a> CallExpression<'a> {
138    pub fn new(allocator: &'a Bump, callee: Callee, loc: SourceLocation) -> Self {
139        Self {
140            callee,
141            arguments: Vec::new_in(allocator),
142            loc,
143        }
144    }
145
146    pub fn node_type(&self) -> NodeType {
147        NodeType::JsCallExpression
148    }
149}
150
151/// Callee type
152#[derive(Debug)]
153pub enum Callee {
154    String(String),
155    Symbol(RuntimeHelper),
156}
157
158/// Call argument type
159#[derive(Debug)]
160pub enum CallArgument<'a> {
161    String(String),
162    Symbol(RuntimeHelper),
163    JsChild(JsChildNode<'a>),
164    TemplateChild(TemplateChildNode<'a>),
165    TemplateChildren(Vec<'a, TemplateChildNode<'a>>),
166}
167
168/// Object expression
169#[derive(Debug)]
170pub struct ObjectExpression<'a> {
171    pub properties: Vec<'a, Property<'a>>,
172    pub loc: SourceLocation,
173}
174
175impl<'a> ObjectExpression<'a> {
176    pub fn new(allocator: &'a Bump, loc: SourceLocation) -> Self {
177        Self {
178            properties: Vec::new_in(allocator),
179            loc,
180        }
181    }
182
183    pub fn node_type(&self) -> NodeType {
184        NodeType::JsObjectExpression
185    }
186}
187
188/// Object property
189#[derive(Debug)]
190pub struct Property<'a> {
191    pub key: ExpressionNode<'a>,
192    pub value: JsChildNode<'a>,
193    pub loc: SourceLocation,
194}
195
196impl<'a> Property<'a> {
197    pub fn node_type(&self) -> NodeType {
198        NodeType::JsProperty
199    }
200}
201
202/// Array expression
203#[derive(Debug)]
204pub struct ArrayExpression<'a> {
205    pub elements: Vec<'a, ArrayElement<'a>>,
206    pub loc: SourceLocation,
207}
208
209impl<'a> ArrayExpression<'a> {
210    pub fn new(allocator: &'a Bump, loc: SourceLocation) -> Self {
211        Self {
212            elements: Vec::new_in(allocator),
213            loc,
214        }
215    }
216
217    pub fn node_type(&self) -> NodeType {
218        NodeType::JsArrayExpression
219    }
220}
221
222/// Array element type
223#[derive(Debug)]
224pub enum ArrayElement<'a> {
225    String(String),
226    Node(JsChildNode<'a>),
227}
228
229/// Function expression
230#[derive(Debug)]
231pub struct FunctionExpression<'a> {
232    pub params: Option<FunctionParams<'a>>,
233    pub returns: Option<FunctionReturns<'a>>,
234    pub body: Option<FunctionBody<'a>>,
235    pub newline: bool,
236    pub is_slot: bool,
237    pub is_non_scoped_slot: bool,
238    pub loc: SourceLocation,
239}
240
241impl<'a> FunctionExpression<'a> {
242    pub fn node_type(&self) -> NodeType {
243        NodeType::JsFunctionExpression
244    }
245}
246
247/// Function parameters
248#[derive(Debug)]
249pub enum FunctionParams<'a> {
250    Single(ExpressionNode<'a>),
251    String(String),
252    Multiple(Vec<'a, FunctionParam<'a>>),
253}
254
255/// Single function parameter
256#[derive(Debug)]
257pub enum FunctionParam<'a> {
258    Expression(ExpressionNode<'a>),
259    String(String),
260}
261
262/// Function returns
263#[derive(Debug)]
264pub enum FunctionReturns<'a> {
265    Single(TemplateChildNode<'a>),
266    Multiple(Vec<'a, TemplateChildNode<'a>>),
267    JsChild(JsChildNode<'a>),
268}
269
270/// Function body
271#[derive(Debug)]
272pub enum FunctionBody<'a> {
273    Block(Box<'a, BlockStatement<'a>>),
274    If(Box<'a, IfStatement<'a>>),
275}
276
277/// Conditional expression (ternary)
278#[derive(Debug)]
279pub struct ConditionalExpression<'a> {
280    pub test: JsChildNode<'a>,
281    pub consequent: JsChildNode<'a>,
282    pub alternate: JsChildNode<'a>,
283    pub newline: bool,
284    pub loc: SourceLocation,
285}
286
287impl<'a> ConditionalExpression<'a> {
288    pub fn node_type(&self) -> NodeType {
289        NodeType::JsConditionalExpression
290    }
291}
292
293/// Cache expression
294#[derive(Debug)]
295pub struct CacheExpression<'a> {
296    pub index: u32,
297    pub value: JsChildNode<'a>,
298    pub need_pause_tracking: bool,
299    pub in_v_once: bool,
300    pub need_array_spread: bool,
301    pub loc: SourceLocation,
302}
303
304impl<'a> CacheExpression<'a> {
305    pub fn node_type(&self) -> NodeType {
306        NodeType::JsCacheExpression
307    }
308}
309
310// ============================================================================
311// SSR Codegen Nodes
312// ============================================================================
313
314/// Block statement
315#[derive(Debug)]
316pub struct BlockStatement<'a> {
317    pub body: Vec<'a, BlockStatementBody<'a>>,
318    pub loc: SourceLocation,
319}
320
321impl<'a> BlockStatement<'a> {
322    pub fn new(allocator: &'a Bump, loc: SourceLocation) -> Self {
323        Self {
324            body: Vec::new_in(allocator),
325            loc,
326        }
327    }
328
329    pub fn node_type(&self) -> NodeType {
330        NodeType::JsBlockStatement
331    }
332}
333
334/// Block statement body item
335#[derive(Debug)]
336pub enum BlockStatementBody<'a> {
337    JsChild(JsChildNode<'a>),
338    If(Box<'a, IfStatement<'a>>),
339}
340
341/// Template literal
342#[derive(Debug)]
343pub struct TemplateLiteral<'a> {
344    pub elements: Vec<'a, TemplateLiteralElement<'a>>,
345    pub loc: SourceLocation,
346}
347
348impl<'a> TemplateLiteral<'a> {
349    pub fn node_type(&self) -> NodeType {
350        NodeType::JsTemplateLiteral
351    }
352}
353
354/// Template literal element
355#[derive(Debug)]
356pub enum TemplateLiteralElement<'a> {
357    String(String),
358    JsChild(JsChildNode<'a>),
359}
360
361/// If statement (SSR)
362#[derive(Debug)]
363pub struct IfStatement<'a> {
364    pub test: ExpressionNode<'a>,
365    pub consequent: Box<'a, BlockStatement<'a>>,
366    pub alternate: Option<IfStatementAlternate<'a>>,
367    pub loc: SourceLocation,
368}
369
370impl<'a> IfStatement<'a> {
371    pub fn node_type(&self) -> NodeType {
372        NodeType::JsIfStatement
373    }
374}
375
376/// If statement alternate
377#[derive(Debug)]
378pub enum IfStatementAlternate<'a> {
379    If(Box<'a, IfStatement<'a>>),
380    Block(Box<'a, BlockStatement<'a>>),
381    Return(Box<'a, ReturnStatement<'a>>),
382}
383
384/// Assignment expression
385#[derive(Debug)]
386pub struct AssignmentExpression<'a> {
387    pub left: Box<'a, SimpleExpressionNode<'a>>,
388    pub right: JsChildNode<'a>,
389    pub loc: SourceLocation,
390}
391
392impl<'a> AssignmentExpression<'a> {
393    pub fn node_type(&self) -> NodeType {
394        NodeType::JsAssignmentExpression
395    }
396}
397
398/// Sequence expression
399#[derive(Debug)]
400pub struct SequenceExpression<'a> {
401    pub expressions: Vec<'a, JsChildNode<'a>>,
402    pub loc: SourceLocation,
403}
404
405impl<'a> SequenceExpression<'a> {
406    pub fn node_type(&self) -> NodeType {
407        NodeType::JsSequenceExpression
408    }
409}
410
411/// Return statement
412#[derive(Debug)]
413pub struct ReturnStatement<'a> {
414    pub returns: ReturnValue<'a>,
415    pub loc: SourceLocation,
416}
417
418impl<'a> ReturnStatement<'a> {
419    pub fn node_type(&self) -> NodeType {
420        NodeType::JsReturnStatement
421    }
422}
423
424/// Return value type
425#[derive(Debug)]
426pub enum ReturnValue<'a> {
427    Single(TemplateChildNode<'a>),
428    Multiple(Vec<'a, TemplateChildNode<'a>>),
429    JsChild(JsChildNode<'a>),
430}