1use super::{
7 expr::Value,
8 types::{TypeRef, Visibility},
9};
10
11#[derive(Debug, Clone, PartialEq)]
13pub struct FunctionSpec {
14 pub name: String,
16 pub doc: Option<String>,
18 pub params: Vec<ParamSpec>,
20 pub return_type: Option<TypeRef>,
22 pub is_async: bool,
24 pub body: Vec<Statement>,
26 pub visibility: Visibility,
28 pub generics: Vec<GenericParam>,
30 pub receiver: Option<Receiver>,
32}
33
34impl FunctionSpec {
35 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 pub fn doc(mut self, doc: impl Into<String>) -> Self {
52 self.doc = Some(doc.into());
53 self
54 }
55
56 pub fn param(mut self, param: ParamSpec) -> Self {
58 self.params.push(param);
59 self
60 }
61
62 pub fn params(mut self, params: impl IntoIterator<Item = ParamSpec>) -> Self {
64 self.params.extend(params);
65 self
66 }
67
68 pub fn returns(mut self, ty: TypeRef) -> Self {
70 self.return_type = Some(ty);
71 self
72 }
73
74 pub fn async_(mut self) -> Self {
76 self.is_async = true;
77 self
78 }
79
80 pub fn statement(mut self, stmt: Statement) -> Self {
82 self.body.push(stmt);
83 self
84 }
85
86 pub fn statements(mut self, stmts: impl IntoIterator<Item = Statement>) -> Self {
88 self.body.extend(stmts);
89 self
90 }
91
92 pub fn visibility(mut self, vis: Visibility) -> Self {
94 self.visibility = vis;
95 self
96 }
97
98 pub fn private(mut self) -> Self {
100 self.visibility = Visibility::Private;
101 self
102 }
103
104 pub fn generic(mut self, param: GenericParam) -> Self {
106 self.generics.push(param);
107 self
108 }
109
110 pub fn receiver(mut self, recv: Receiver) -> Self {
112 self.receiver = Some(recv);
113 self
114 }
115
116 pub fn method(self) -> Self {
118 self.receiver(Receiver::Ref)
119 }
120
121 pub fn method_mut(self) -> Self {
123 self.receiver(Receiver::RefMut)
124 }
125
126 pub fn has_body(&self) -> bool {
128 !self.body.is_empty()
129 }
130}
131
132#[derive(Debug, Clone, PartialEq)]
134pub struct ParamSpec {
135 pub name: String,
137 pub ty: TypeRef,
139 pub default: Option<Value>,
141 pub variadic: bool,
143}
144
145impl ParamSpec {
146 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 pub fn default(mut self, value: Value) -> Self {
158 self.default = Some(value);
159 self
160 }
161
162 pub fn variadic(mut self) -> Self {
164 self.variadic = true;
165 self
166 }
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum Receiver {
172 Owned,
174 Ref,
176 RefMut,
178}
179
180#[derive(Debug, Clone, PartialEq)]
182pub struct GenericParam {
183 pub name: String,
185 pub bounds: Vec<String>,
187 pub default: Option<TypeRef>,
189}
190
191impl GenericParam {
192 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 pub fn bound(mut self, bound: impl Into<String>) -> Self {
203 self.bounds.push(bound.into());
204 self
205 }
206
207 pub fn default(mut self, ty: TypeRef) -> Self {
209 self.default = Some(ty);
210 self
211 }
212}
213
214#[derive(Debug, Clone, PartialEq)]
216pub enum Statement {
217 Let {
219 name: String,
221 ty: Option<TypeRef>,
223 value: Value,
225 mutable: bool,
227 },
228 Return(Option<Value>),
230 Expr(Value),
232 If {
234 condition: Value,
236 then_branch: Vec<Statement>,
238 else_branch: Option<Vec<Statement>>,
240 },
241 Match {
243 expr: Value,
245 arms: Vec<MatchArm>,
247 },
248 For {
250 var: String,
252 iter: Value,
254 body: Vec<Statement>,
256 },
257 While {
259 condition: Value,
261 body: Vec<Statement>,
263 },
264 Raw(String),
266 Block(Vec<Statement>),
268}
269
270impl Statement {
271 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 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 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 pub fn return_(value: Value) -> Self {
303 Self::Return(Some(value))
304 }
305
306 pub fn return_void() -> Self {
308 Self::Return(None)
309 }
310
311 pub fn expr(value: Value) -> Self {
313 Self::Expr(value)
314 }
315
316 pub fn raw(code: impl Into<String>) -> Self {
318 Self::Raw(code.into())
319 }
320
321 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 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 pub fn match_(expr: Value, arms: Vec<MatchArm>) -> Self {
345 Self::Match { expr, arms }
346 }
347
348 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 pub fn while_(condition: Value, body: Vec<Statement>) -> Self {
359 Self::While { condition, body }
360 }
361
362 pub fn block(stmts: Vec<Statement>) -> Self {
364 Self::Block(stmts)
365 }
366}
367
368#[derive(Debug, Clone, PartialEq)]
370pub struct MatchArm {
371 pub pattern: Pattern,
373 pub guard: Option<Value>,
375 pub body: Vec<Statement>,
377}
378
379impl MatchArm {
380 pub fn new(pattern: Pattern, body: Vec<Statement>) -> Self {
382 Self {
383 pattern,
384 guard: None,
385 body,
386 }
387 }
388
389 pub fn guard(mut self, condition: Value) -> Self {
391 self.guard = Some(condition);
392 self
393 }
394}
395
396#[derive(Debug, Clone, PartialEq)]
398pub enum Pattern {
399 Wildcard,
401 Literal(Value),
403 Binding(String),
405 Variant {
407 path: String,
409 fields: Vec<Pattern>,
411 },
412 Tuple(Vec<Pattern>),
414 Struct {
416 name: String,
418 fields: Vec<(String, Pattern)>,
420 },
421}
422
423impl Pattern {
424 pub fn wildcard() -> Self {
426 Self::Wildcard
427 }
428
429 pub fn literal(value: Value) -> Self {
431 Self::Literal(value)
432 }
433
434 pub fn binding(name: impl Into<String>) -> Self {
436 Self::Binding(name.into())
437 }
438
439 pub fn variant(path: impl Into<String>, fields: Vec<Pattern>) -> Self {
441 Self::Variant {
442 path: path.into(),
443 fields,
444 }
445 }
446
447 pub fn tuple(patterns: Vec<Pattern>) -> Self {
449 Self::Tuple(patterns)
450 }
451}
452
453pub trait FunctionRenderer {
458 fn render_function(&self, spec: &FunctionSpec) -> String;
460
461 fn render_param(&self, spec: &ParamSpec) -> String;
463
464 fn render_statement(&self, stmt: &Statement, indent: usize) -> String;
466
467 fn render_match_arm(&self, arm: &MatchArm, indent: usize) -> String;
469
470 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}