baobao_codegen/builder/
function.rs

1//! Language-agnostic function definitions.
2//!
3//! This module provides declarative specifications for functions, methods,
4//! and their components that can be rendered to any target language.
5
6use super::{
7    expr::Value,
8    types::{TypeRef, Visibility},
9};
10
11/// A declarative specification for a function or method.
12#[derive(Debug, Clone, PartialEq)]
13pub struct FunctionSpec {
14    /// Function name.
15    pub name: String,
16    /// Documentation comment.
17    pub doc: Option<String>,
18    /// Parameters.
19    pub params: Vec<ParamSpec>,
20    /// Return type (None for void/unit).
21    pub return_type: Option<TypeRef>,
22    /// Whether this function is async.
23    pub is_async: bool,
24    /// Function body as statements.
25    pub body: Vec<Statement>,
26    /// Visibility modifier.
27    pub visibility: Visibility,
28    /// Generic type parameters.
29    pub generics: Vec<GenericParam>,
30    /// Whether this is a method (has self/this).
31    pub receiver: Option<Receiver>,
32}
33
34impl FunctionSpec {
35    /// Create a new public function spec.
36    pub fn new(name: impl Into<String>) -> Self {
37        Self {
38            name: name.into(),
39            doc: None,
40            params: Vec::new(),
41            return_type: None,
42            is_async: false,
43            body: Vec::new(),
44            visibility: Visibility::Public,
45            generics: Vec::new(),
46            receiver: None,
47        }
48    }
49
50    /// Set documentation comment.
51    pub fn doc(mut self, doc: impl Into<String>) -> Self {
52        self.doc = Some(doc.into());
53        self
54    }
55
56    /// Add a parameter.
57    pub fn param(mut self, param: ParamSpec) -> Self {
58        self.params.push(param);
59        self
60    }
61
62    /// Add multiple parameters.
63    pub fn params(mut self, params: impl IntoIterator<Item = ParamSpec>) -> Self {
64        self.params.extend(params);
65        self
66    }
67
68    /// Set return type.
69    pub fn returns(mut self, ty: TypeRef) -> Self {
70        self.return_type = Some(ty);
71        self
72    }
73
74    /// Mark as async.
75    pub fn async_(mut self) -> Self {
76        self.is_async = true;
77        self
78    }
79
80    /// Add a statement to the body.
81    pub fn statement(mut self, stmt: Statement) -> Self {
82        self.body.push(stmt);
83        self
84    }
85
86    /// Add multiple statements to the body.
87    pub fn statements(mut self, stmts: impl IntoIterator<Item = Statement>) -> Self {
88        self.body.extend(stmts);
89        self
90    }
91
92    /// Set visibility.
93    pub fn visibility(mut self, vis: Visibility) -> Self {
94        self.visibility = vis;
95        self
96    }
97
98    /// Make this function private.
99    pub fn private(mut self) -> Self {
100        self.visibility = Visibility::Private;
101        self
102    }
103
104    /// Add a generic type parameter.
105    pub fn generic(mut self, param: GenericParam) -> Self {
106        self.generics.push(param);
107        self
108    }
109
110    /// Set the receiver (makes this a method).
111    pub fn receiver(mut self, recv: Receiver) -> Self {
112        self.receiver = Some(recv);
113        self
114    }
115
116    /// Make this an immutable self method.
117    pub fn method(self) -> Self {
118        self.receiver(Receiver::Ref)
119    }
120
121    /// Make this a mutable self method.
122    pub fn method_mut(self) -> Self {
123        self.receiver(Receiver::RefMut)
124    }
125
126    /// Check if this function has a body.
127    pub fn has_body(&self) -> bool {
128        !self.body.is_empty()
129    }
130}
131
132/// A function parameter.
133#[derive(Debug, Clone, PartialEq)]
134pub struct ParamSpec {
135    /// Parameter name.
136    pub name: String,
137    /// Parameter type.
138    pub ty: TypeRef,
139    /// Default value (if optional).
140    pub default: Option<Value>,
141    /// Whether this parameter is variadic (...args in TS, ... in Rust).
142    pub variadic: bool,
143}
144
145impl ParamSpec {
146    /// Create a new required parameter.
147    pub fn new(name: impl Into<String>, ty: TypeRef) -> Self {
148        Self {
149            name: name.into(),
150            ty,
151            default: None,
152            variadic: false,
153        }
154    }
155
156    /// Set a default value.
157    pub fn default(mut self, value: Value) -> Self {
158        self.default = Some(value);
159        self
160    }
161
162    /// Mark as variadic.
163    pub fn variadic(mut self) -> Self {
164        self.variadic = true;
165        self
166    }
167}
168
169/// Method receiver type.
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum Receiver {
172    /// Owned receiver: `self` in Rust, `this` in TS.
173    Owned,
174    /// Immutable reference: `&self` in Rust.
175    Ref,
176    /// Mutable reference: `&mut self` in Rust.
177    RefMut,
178}
179
180/// A generic type parameter.
181#[derive(Debug, Clone, PartialEq)]
182pub struct GenericParam {
183    /// Parameter name (e.g., "T", "E").
184    pub name: String,
185    /// Trait bounds (Rust) or constraints (TS extends).
186    pub bounds: Vec<String>,
187    /// Default type.
188    pub default: Option<TypeRef>,
189}
190
191impl GenericParam {
192    /// Create a new generic parameter.
193    pub fn new(name: impl Into<String>) -> Self {
194        Self {
195            name: name.into(),
196            bounds: Vec::new(),
197            default: None,
198        }
199    }
200
201    /// Add a trait bound.
202    pub fn bound(mut self, bound: impl Into<String>) -> Self {
203        self.bounds.push(bound.into());
204        self
205    }
206
207    /// Set a default type.
208    pub fn default(mut self, ty: TypeRef) -> Self {
209        self.default = Some(ty);
210        self
211    }
212}
213
214/// A statement in a function body.
215#[derive(Debug, Clone, PartialEq)]
216pub enum Statement {
217    /// Variable declaration: `let x = ...` or `const x = ...`.
218    Let {
219        /// Variable name.
220        name: String,
221        /// Optional explicit type annotation.
222        ty: Option<TypeRef>,
223        /// Initial value.
224        value: Value,
225        /// Whether the binding is mutable.
226        mutable: bool,
227    },
228    /// Return statement.
229    Return(Option<Value>),
230    /// Expression statement.
231    Expr(Value),
232    /// If statement.
233    If {
234        /// Condition expression.
235        condition: Value,
236        /// Then branch.
237        then_branch: Vec<Statement>,
238        /// Else branch.
239        else_branch: Option<Vec<Statement>>,
240    },
241    /// Match/switch statement.
242    Match {
243        /// Expression to match.
244        expr: Value,
245        /// Match arms.
246        arms: Vec<MatchArm>,
247    },
248    /// For loop.
249    For {
250        /// Loop variable name.
251        var: String,
252        /// Iterator/iterable expression.
253        iter: Value,
254        /// Loop body.
255        body: Vec<Statement>,
256    },
257    /// While loop.
258    While {
259        /// Condition.
260        condition: Value,
261        /// Loop body.
262        body: Vec<Statement>,
263    },
264    /// Raw code (escape hatch for language-specific code).
265    Raw(String),
266    /// Block of statements.
267    Block(Vec<Statement>),
268}
269
270impl Statement {
271    /// Create a let binding.
272    pub fn let_(name: impl Into<String>, value: Value) -> Self {
273        Self::Let {
274            name: name.into(),
275            ty: None,
276            value,
277            mutable: false,
278        }
279    }
280
281    /// Create a mutable let binding.
282    pub fn let_mut(name: impl Into<String>, value: Value) -> Self {
283        Self::Let {
284            name: name.into(),
285            ty: None,
286            value,
287            mutable: true,
288        }
289    }
290
291    /// Create a typed let binding.
292    pub fn let_typed(name: impl Into<String>, ty: TypeRef, value: Value) -> Self {
293        Self::Let {
294            name: name.into(),
295            ty: Some(ty),
296            value,
297            mutable: false,
298        }
299    }
300
301    /// Create a return statement.
302    pub fn return_(value: Value) -> Self {
303        Self::Return(Some(value))
304    }
305
306    /// Create an empty return statement.
307    pub fn return_void() -> Self {
308        Self::Return(None)
309    }
310
311    /// Create an expression statement.
312    pub fn expr(value: Value) -> Self {
313        Self::Expr(value)
314    }
315
316    /// Create a raw code statement.
317    pub fn raw(code: impl Into<String>) -> Self {
318        Self::Raw(code.into())
319    }
320
321    /// Create an if statement.
322    pub fn if_(condition: Value, then_branch: Vec<Statement>) -> Self {
323        Self::If {
324            condition,
325            then_branch,
326            else_branch: None,
327        }
328    }
329
330    /// Create an if-else statement.
331    pub fn if_else(
332        condition: Value,
333        then_branch: Vec<Statement>,
334        else_branch: Vec<Statement>,
335    ) -> Self {
336        Self::If {
337            condition,
338            then_branch,
339            else_branch: Some(else_branch),
340        }
341    }
342
343    /// Create a match statement.
344    pub fn match_(expr: Value, arms: Vec<MatchArm>) -> Self {
345        Self::Match { expr, arms }
346    }
347
348    /// Create a for loop.
349    pub fn for_(var: impl Into<String>, iter: Value, body: Vec<Statement>) -> Self {
350        Self::For {
351            var: var.into(),
352            iter,
353            body,
354        }
355    }
356
357    /// Create a while loop.
358    pub fn while_(condition: Value, body: Vec<Statement>) -> Self {
359        Self::While { condition, body }
360    }
361
362    /// Create a block of statements.
363    pub fn block(stmts: Vec<Statement>) -> Self {
364        Self::Block(stmts)
365    }
366}
367
368/// A match arm (case in switch).
369#[derive(Debug, Clone, PartialEq)]
370pub struct MatchArm {
371    /// Pattern to match.
372    pub pattern: Pattern,
373    /// Optional guard condition.
374    pub guard: Option<Value>,
375    /// Arm body.
376    pub body: Vec<Statement>,
377}
378
379impl MatchArm {
380    /// Create a new match arm.
381    pub fn new(pattern: Pattern, body: Vec<Statement>) -> Self {
382        Self {
383            pattern,
384            guard: None,
385            body,
386        }
387    }
388
389    /// Add a guard condition.
390    pub fn guard(mut self, condition: Value) -> Self {
391        self.guard = Some(condition);
392        self
393    }
394}
395
396/// A pattern for matching.
397#[derive(Debug, Clone, PartialEq)]
398pub enum Pattern {
399    /// Wildcard pattern: `_` or `default`.
400    Wildcard,
401    /// Literal pattern.
402    Literal(Value),
403    /// Variable binding pattern.
404    Binding(String),
405    /// Enum variant pattern.
406    Variant {
407        /// Variant path (e.g., "Option::Some").
408        path: String,
409        /// Bound fields/values.
410        fields: Vec<Pattern>,
411    },
412    /// Tuple pattern.
413    Tuple(Vec<Pattern>),
414    /// Struct pattern.
415    Struct {
416        /// Struct name.
417        name: String,
418        /// Field patterns.
419        fields: Vec<(String, Pattern)>,
420    },
421}
422
423impl Pattern {
424    /// Create a wildcard pattern.
425    pub fn wildcard() -> Self {
426        Self::Wildcard
427    }
428
429    /// Create a literal pattern.
430    pub fn literal(value: Value) -> Self {
431        Self::Literal(value)
432    }
433
434    /// Create a binding pattern.
435    pub fn binding(name: impl Into<String>) -> Self {
436        Self::Binding(name.into())
437    }
438
439    /// Create a variant pattern.
440    pub fn variant(path: impl Into<String>, fields: Vec<Pattern>) -> Self {
441        Self::Variant {
442            path: path.into(),
443            fields,
444        }
445    }
446
447    /// Create a tuple pattern.
448    pub fn tuple(patterns: Vec<Pattern>) -> Self {
449        Self::Tuple(patterns)
450    }
451}
452
453/// Trait for rendering function specs to language-specific code.
454///
455/// Implement this trait to support rendering functions and methods
456/// in a new target language.
457pub trait FunctionRenderer {
458    /// Render a function specification to code.
459    fn render_function(&self, spec: &FunctionSpec) -> String;
460
461    /// Render a parameter specification to code.
462    fn render_param(&self, spec: &ParamSpec) -> String;
463
464    /// Render a statement to code.
465    fn render_statement(&self, stmt: &Statement, indent: usize) -> String;
466
467    /// Render a match arm to code.
468    fn render_match_arm(&self, arm: &MatchArm, indent: usize) -> String;
469
470    /// Render a pattern to code.
471    fn render_pattern(&self, pattern: &Pattern) -> String;
472}
473
474#[cfg(test)]
475mod tests {
476    use super::*;
477
478    #[test]
479    fn test_function_spec() {
480        let spec = FunctionSpec::new("process")
481            .doc("Process the input")
482            .async_()
483            .param(ParamSpec::new("input", TypeRef::string()))
484            .returns(TypeRef::result(TypeRef::unit(), TypeRef::named("Error")))
485            .statement(Statement::return_(Value::ident("Ok(())")));
486
487        assert_eq!(spec.name, "process");
488        assert!(spec.is_async);
489        assert_eq!(spec.params.len(), 1);
490        assert!(spec.return_type.is_some());
491        assert!(spec.has_body());
492    }
493
494    #[test]
495    fn test_method_spec() {
496        let spec = FunctionSpec::new("get_name")
497            .method()
498            .returns(TypeRef::string());
499
500        assert!(matches!(spec.receiver, Some(Receiver::Ref)));
501    }
502
503    #[test]
504    fn test_param_spec() {
505        let required = ParamSpec::new("name", TypeRef::string());
506        assert!(required.default.is_none());
507
508        let optional = ParamSpec::new("count", TypeRef::int()).default(Value::int(10));
509        assert!(optional.default.is_some());
510    }
511
512    #[test]
513    fn test_statements() {
514        let let_stmt = Statement::let_("x", Value::int(42));
515        assert!(matches!(let_stmt, Statement::Let { mutable: false, .. }));
516
517        let let_mut = Statement::let_mut("y", Value::int(0));
518        assert!(matches!(let_mut, Statement::Let { mutable: true, .. }));
519
520        let ret = Statement::return_(Value::ident("result"));
521        assert!(matches!(ret, Statement::Return(Some(_))));
522    }
523
524    #[test]
525    fn test_match_arm() {
526        let arm = MatchArm::new(
527            Pattern::variant("Some", vec![Pattern::binding("value")]),
528            vec![Statement::return_(Value::ident("value"))],
529        )
530        .guard(Value::ident("value > 0"));
531
532        assert!(arm.guard.is_some());
533        assert!(matches!(arm.pattern, Pattern::Variant { .. }));
534    }
535
536    #[test]
537    fn test_generic_param() {
538        let generic = GenericParam::new("T")
539            .bound("Clone")
540            .bound("Send")
541            .default(TypeRef::string());
542
543        assert_eq!(generic.name, "T");
544        assert_eq!(generic.bounds.len(), 2);
545        assert!(generic.default.is_some());
546    }
547}