1use crate::types::{TypedProgram, TypedItem};
8use crate::error::{KainResult, KainError};
9use crate::ast::{
10 Type, Expr, Stmt, Block, BinaryOp, UnaryOp, Pattern, Function, Struct, Enum,
11 Field, Variant, VariantFields, Impl, Param, MatchArm, CallArg, ElseBranch,
12 VariantPatternFields, EnumVariantFields,
13};
14use crate::span::Span;
15
16pub fn generate(program: &TypedProgram) -> KainResult<String> {
18 let mut gen = RustGen::new();
19 Ok(gen.gen_program(program))
20}
21
22struct StringBuilder {
24 lines: Vec<String>,
25}
26
27impl StringBuilder {
28 fn new() -> Self {
29 Self { lines: Vec::new() }
30 }
31
32 fn push(&mut self, text: &str) {
33 self.lines.push(text.to_string());
34 }
35
36 fn push_line(&mut self, text: &str) {
37 self.lines.push(format!("{}\n", text));
38 }
39
40 fn build(&self) -> String {
41 self.lines.join("")
42 }
43}
44
45struct RustGen {
47 output: StringBuilder,
48 indent: usize,
49}
50
51impl RustGen {
52 fn new() -> Self {
53 Self {
54 output: StringBuilder::new(),
55 indent: 0,
56 }
57 }
58
59 fn push_indent(&mut self) {
60 self.indent += 1;
61 }
62
63 fn pop_indent(&mut self) {
64 if self.indent > 0 {
65 self.indent -= 1;
66 }
67 }
68
69 fn indent_str(&self) -> String {
70 " ".repeat(self.indent)
71 }
72
73 fn write_line(&mut self, line: &str) {
74 let indented = format!("{}{}", self.indent_str(), line);
75 self.output.push_line(&indented);
76 }
77
78 fn write_blank(&mut self) {
79 self.output.push_line("");
80 }
81
82 fn gen_program(&mut self, program: &TypedProgram) -> String {
84 self.write_line("// Generated by KAIN Compiler (Project Ouroboros)");
86 self.write_line("// Do not edit - regenerate from .kn source");
87 self.write_blank();
88 self.write_line("#![allow(unused_variables)]");
89 self.write_line("#![allow(unused_mut)]");
90 self.write_line("#![allow(dead_code)]");
91 self.write_line("#![allow(unused_parens)]");
92 self.write_blank();
93
94 self.write_line("use std::collections::HashMap;");
96 self.write_line("use std::rc::Rc;");
97 self.write_line("use std::cell::RefCell;");
98 self.write_blank();
99
100 for item in &program.items {
102 self.gen_item(item);
103 self.write_blank();
104 }
105
106 self.output.build()
107 }
108
109 fn gen_item(&mut self, item: &TypedItem) {
110 match item {
111 TypedItem::Function(fn_typed) => self.gen_function(&fn_typed.ast),
112 TypedItem::Struct(st) => self.gen_struct(&st.ast),
113 TypedItem::Enum(en) => self.gen_enum(&en.ast),
114 TypedItem::Impl(im) => self.gen_impl(&im.ast),
115 _ => {} }
117 }
118
119 fn gen_function(&mut self, func: &Function) {
121 let vis = match func.visibility {
122 crate::ast::Visibility::Public => "pub ",
123 _ => "",
124 };
125
126 let params = self.gen_params(&func.params);
128
129 let ret = if let Some(ty) = &func.return_type {
131 format!(" -> {}", self.map_type(ty))
132 } else {
133 String::new()
134 };
135
136 self.write_line(&format!("{}fn {}({}){} {{", vis, func.name, params, ret));
138 self.push_indent();
139
140 self.gen_block(&func.body);
142
143 self.pop_indent();
144 self.write_line("}");
145 }
146
147 fn gen_params(&self, params: &[Param]) -> String {
148 let parts: Vec<String> = params
149 .iter()
150 .map(|p| {
151 let ty_str = self.map_type(&p.ty);
152 if p.mutable {
153 format!("mut {}: {}", p.name, ty_str)
154 } else {
155 format!("{}: {}", p.name, ty_str)
156 }
157 })
158 .collect();
159 parts.join(", ")
160 }
161
162 fn gen_struct(&mut self, struct_def: &Struct) {
163 let vis = match struct_def.visibility {
164 crate::ast::Visibility::Public => "pub ",
165 _ => "",
166 };
167
168 self.write_line("#[derive(Debug, Clone)]");
169 self.write_line(&format!("{}struct {} {{", vis, struct_def.name));
170 self.push_indent();
171
172 for field in &struct_def.fields {
173 self.write_line(&format!("pub {}: {},", field.name, self.map_type(&field.ty)));
174 }
175
176 self.pop_indent();
177 self.write_line("}");
178 }
179
180 fn gen_enum(&mut self, enum_def: &Enum) {
181 self.write_line("#[derive(Debug, Clone, PartialEq)]");
182 self.write_line(&format!("pub enum {} {{", enum_def.name));
183 self.push_indent();
184
185 for variant in &enum_def.variants {
186 match &variant.fields {
187 VariantFields::Unit => {
188 self.write_line(&format!("{},", variant.name));
189 }
190 VariantFields::Tuple(types) => {
191 let fields: Vec<String> = types.iter().map(|t| self.map_type(t)).collect();
192 self.write_line(&format!("{}({}),", variant.name, fields.join(", ")));
193 }
194 VariantFields::Struct(fields) => {
195 self.write_line(&format!("{} {{", variant.name));
196 self.push_indent();
197 for f in fields {
198 self.write_line(&format!("{}: {},", f.name, self.map_type(&f.ty)));
199 }
200 self.pop_indent();
201 self.write_line("},");
202 }
203 }
204 }
205
206 self.pop_indent();
207 self.write_line("}");
208 }
209
210 fn gen_impl(&mut self, impl_def: &Impl) {
211 let target = self.map_type(&impl_def.target_type);
212
213 if let Some(trait_name) = &impl_def.trait_name {
214 self.write_line(&format!("impl {} for {} {{", trait_name, target));
215 } else {
216 self.write_line(&format!("impl {} {{", target));
217 }
218 self.push_indent();
219
220 for method in &impl_def.methods {
221 self.gen_function(method);
222 self.write_blank();
223 }
224
225 self.pop_indent();
226 self.write_line("}");
227 }
228
229 fn gen_block(&mut self, block: &Block) {
230 for stmt in &block.stmts {
231 self.gen_stmt(stmt);
232 }
233 }
234
235 fn gen_stmt(&mut self, stmt: &Stmt) {
236 match stmt {
237 Stmt::Let { pattern, ty, value, .. } => {
238 let pat_str = self.gen_pattern(pattern);
239 let ty_str = ty.as_ref().map(|t| format!(": {}", self.map_type(t))).unwrap_or_default();
240 if let Some(val) = value {
241 self.write_line(&format!("let {}{} = {};", pat_str, ty_str, self.gen_expr(val)));
242 } else {
243 self.write_line(&format!("let {}{};", pat_str, ty_str));
244 }
245 }
246
247 Stmt::Return(maybe_expr, _) => {
248 if let Some(expr) = maybe_expr {
249 self.write_line(&format!("return {};", self.gen_expr(expr)));
250 } else {
251 self.write_line("return;");
252 }
253 }
254
255 Stmt::Break(maybe_expr, _) => {
256 if let Some(expr) = maybe_expr {
257 self.write_line(&format!("break {};", self.gen_expr(expr)));
258 } else {
259 self.write_line("break;");
260 }
261 }
262
263 Stmt::Continue(_) => {
264 self.write_line("continue;");
265 }
266
267 Stmt::For { binding, iter, body, .. } => {
268 let pat = self.gen_pattern(binding);
269 self.write_line(&format!("for {} in {} {{", pat, self.gen_expr(iter)));
270 self.push_indent();
271 self.gen_block(body);
272 self.pop_indent();
273 self.write_line("}");
274 }
275
276 Stmt::While { condition, body, .. } => {
277 self.write_line(&format!("while {} {{", self.gen_expr(condition)));
278 self.push_indent();
279 self.gen_block(body);
280 self.pop_indent();
281 self.write_line("}");
282 }
283
284 Stmt::Loop { body, .. } => {
285 self.write_line("loop {");
286 self.push_indent();
287 self.gen_block(body);
288 self.pop_indent();
289 self.write_line("}");
290 }
291
292 Stmt::Expr(expr) => {
293 if let Expr::Assign { target, value, .. } = expr {
295 self.write_line(&format!("{} = {};", self.gen_expr(target), self.gen_expr(value)));
296 } else {
297 self.write_line(&format!("{};", self.gen_expr(expr)));
298 }
299 }
300
301 Stmt::Item(item) => {
302 }
305 }
306 }
307
308 fn gen_expr(&self, expr: &Expr) -> String {
309 match expr {
310 Expr::Int(n, _) => n.to_string(),
311 Expr::Float(f, _) => format!("{:.1}", f),
312 Expr::String(s, _) => format!("\"{}\".to_string()", self.escape_string(s)),
313 Expr::Bool(b, _) => if *b { "true".to_string() } else { "false".to_string() },
314 Expr::None(_) => "None".to_string(),
315 Expr::Ident(name, _) => name.clone(),
316
317 Expr::Binary { left, op, right, .. } => {
318 let l = self.gen_expr(left);
319 let r = self.gen_expr(right);
320 let rust_op = self.map_binop(op);
321 format!("({} {} {})", l, rust_op, r)
322 }
323
324 Expr::Unary { op, operand, .. } => {
325 let o = self.gen_expr(operand);
326 let rust_op = self.map_unaryop(op);
327 format!("({}{})", rust_op, o)
328 }
329
330 Expr::Call { callee, args, .. } => {
331 let fn_name = self.gen_expr(callee);
332
333 if fn_name == "println" || fn_name == "print" {
335 let arg_strs: Vec<String> = args.iter().map(|a| self.gen_expr(&a.value)).collect();
336 let placeholders: Vec<&str> = arg_strs.iter().map(|_| "{}").collect();
337 let format_str = format!("\"{}\"", placeholders.join(" "));
338 if !arg_strs.is_empty() {
339 return format!("{}!({}, {})", fn_name, format_str, arg_strs.join(", "));
340 }
341 return format!("{}!()", fn_name);
342 }
343
344 let arg_strs: Vec<String> = args.iter().map(|a| {
345 if let Some(name) = &a.name {
346 format!("{}: {}", name, self.gen_expr(&a.value))
347 } else {
348 self.gen_expr(&a.value)
349 }
350 }).collect();
351 format!("{}({})", fn_name, arg_strs.join(", "))
352 }
353
354 Expr::MethodCall { receiver, method, args, .. } => {
355 let recv = self.gen_expr(receiver);
356 let arg_strs: Vec<String> = args.iter().map(|a| self.gen_expr(&a.value)).collect();
357 format!("{}.{}({})", recv, method, arg_strs.join(", "))
358 }
359
360 Expr::Field { object, field, .. } => {
361 format!("{}.{}", self.gen_expr(object), field)
362 }
363
364 Expr::Index { object, index, .. } => {
365 format!("{}[{}]", self.gen_expr(object), self.gen_expr(index))
366 }
367
368 Expr::Array(elements, _) => {
369 let elems: Vec<String> = elements.iter().map(|e| self.gen_expr(e)).collect();
370 format!("vec![{}]", elems.join(", "))
371 }
372
373 Expr::Tuple(elements, _) => {
374 let elems: Vec<String> = elements.iter().map(|e| self.gen_expr(e)).collect();
375 if elems.len() == 1 {
376 format!("({},)", elems[0])
377 } else {
378 format!("({})", elems.join(", "))
379 }
380 }
381
382 Expr::Struct { name, fields, .. } => {
383 let field_strs: Vec<String> = fields
384 .iter()
385 .map(|(fname, fval)| format!("{}: {}", fname, self.gen_expr(fval)))
386 .collect();
387 format!("{} {{ {} }}", name, field_strs.join(", "))
388 }
389
390 Expr::EnumVariant { enum_name, variant, fields, .. } => {
391 match fields {
392 EnumVariantFields::Unit => format!("{}::{}", enum_name, variant),
393 EnumVariantFields::Tuple(args) => {
394 let arg_strs: Vec<String> = args.iter().map(|a| self.gen_expr(a)).collect();
395 format!("{}::{}({})", enum_name, variant, arg_strs.join(", "))
396 }
397 EnumVariantFields::Struct(fields) => {
398 let field_strs: Vec<String> = fields
399 .iter()
400 .map(|(n, v)| format!("{}: {}", n, self.gen_expr(v)))
401 .collect();
402 format!("{}::{} {{ {} }}", enum_name, variant, field_strs.join(", "))
403 }
404 }
405 }
406
407 Expr::If { condition, then_branch, else_branch, .. } => {
408 let cond = self.gen_expr(condition);
409 let then_str = self.gen_block_expr(then_branch);
410 if let Some(else_b) = else_branch {
411 let else_str = self.gen_else_branch(else_b);
412 format!("if {} {{ {} }} else {}", cond, then_str, else_str)
413 } else {
414 format!("if {} {{ {} }}", cond, then_str)
415 }
416 }
417
418 Expr::Match { scrutinee, arms, .. } => {
419 let scrut = self.gen_expr(scrutinee);
420 let mut result = format!("match {} {{\n", scrut);
421 for arm in arms {
422 let pat = self.gen_pattern(&arm.pattern);
423 let body = self.gen_expr(&arm.body);
424 result.push_str(&format!(" {} => {{ {} }}\n", pat, body));
425 }
426 result.push_str("}");
427 result
428 }
429
430 Expr::Lambda { params, body, .. } => {
431 let param_strs: Vec<String> = params.iter().map(|p| p.name.clone()).collect();
432 format!("|{}| {}", param_strs.join(", "), self.gen_expr(body))
433 }
434
435 Expr::Await(future, _) => {
436 format!("{}.await", self.gen_expr(future))
437 }
438
439 Expr::Ref { mutable, value, .. } => {
440 if *mutable {
441 format!("&mut {}", self.gen_expr(value))
442 } else {
443 format!("&{}", self.gen_expr(value))
444 }
445 }
446
447 Expr::Deref(inner, _) => {
448 format!("*{}", self.gen_expr(inner))
449 }
450
451 Expr::Cast { value, target, .. } => {
452 format!("{} as {}", self.gen_expr(value), self.map_type(target))
453 }
454
455 Expr::Try(inner, _) => {
456 format!("{}?", self.gen_expr(inner))
457 }
458
459 Expr::Range { start, end, inclusive, .. } => {
460 let s = start.as_ref().map(|e| self.gen_expr(e)).unwrap_or_default();
461 let e = end.as_ref().map(|e| self.gen_expr(e)).unwrap_or_default();
462 if *inclusive {
463 format!("{}..={}", s, e)
464 } else {
465 format!("{}..{}", s, e)
466 }
467 }
468
469 Expr::Block(block, _) => {
470 format!("{{ {} }}", self.gen_block_expr(block))
471 }
472
473 Expr::Paren(inner, _) => {
474 format!("({})", self.gen_expr(inner))
475 }
476
477 Expr::Return(maybe_expr, _) => {
478 if let Some(expr) = maybe_expr {
479 format!("return {}", self.gen_expr(expr))
480 } else {
481 "return".to_string()
482 }
483 }
484
485 Expr::Break(maybe_expr, _) => {
486 if let Some(expr) = maybe_expr {
487 format!("break {}", self.gen_expr(expr))
488 } else {
489 "break".to_string()
490 }
491 }
492
493 Expr::Continue(_) => "continue".to_string(),
494
495 Expr::FString(parts, _) => {
497 let mut format_str = String::new();
498 let mut args = Vec::new();
499 for part in parts {
500 if let Expr::String(s, _) = part {
501 format_str.push_str(s);
502 } else {
503 format_str.push_str("{}");
504 args.push(self.gen_expr(part));
505 }
506 }
507 if args.is_empty() {
508 format!("format!(\"{}\")", format_str)
509 } else {
510 format!("format!(\"{}\", {})", format_str, args.join(", "))
511 }
512 }
513
514 _ => "/* unhandled expr */".to_string(),
516 }
517 }
518
519 fn gen_block_expr(&self, block: &Block) -> String {
520 if block.stmts.is_empty() {
522 return "()".to_string();
523 }
524
525 let mut parts = Vec::new();
526 for stmt in &block.stmts {
527 match stmt {
528 Stmt::Expr(e) => parts.push(self.gen_expr(e)),
529 Stmt::Return(Some(e), _) => parts.push(format!("return {}", self.gen_expr(e))),
530 Stmt::Return(None, _) => parts.push("return".to_string()),
531 _ => {} }
533 }
534 parts.join("; ")
535 }
536
537 fn gen_else_branch(&self, branch: &ElseBranch) -> String {
538 match branch {
539 ElseBranch::Else(block) => {
540 format!("{{ {} }}", self.gen_block_expr(block))
541 }
542 ElseBranch::ElseIf(cond, block, maybe_else) => {
543 let cond_str = self.gen_expr(cond);
544 let then_str = self.gen_block_expr(block);
545 if let Some(else_b) = maybe_else {
546 format!("if {} {{ {} }} else {}", cond_str, then_str, self.gen_else_branch(else_b))
547 } else {
548 format!("if {} {{ {} }}", cond_str, then_str)
549 }
550 }
551 }
552 }
553
554 fn gen_pattern(&self, pattern: &Pattern) -> String {
555 match pattern {
556 Pattern::Wildcard(_) => "_".to_string(),
557 Pattern::Literal(expr) => self.gen_expr(expr),
558 Pattern::Binding { name, mutable, .. } => {
559 if *mutable {
560 format!("mut {}", name)
561 } else {
562 name.clone()
563 }
564 }
565 Pattern::Struct { name, fields, rest, .. } => {
566 let field_pats: Vec<String> = fields
567 .iter()
568 .map(|(n, p)| format!("{}: {}", n, self.gen_pattern(p)))
569 .collect();
570 if *rest {
571 format!("{} {{ {}, .. }}", name, field_pats.join(", "))
572 } else {
573 format!("{} {{ {} }}", name, field_pats.join(", "))
574 }
575 }
576 Pattern::Tuple(pats, _) => {
577 let pat_strs: Vec<String> = pats.iter().map(|p| self.gen_pattern(p)).collect();
578 format!("({})", pat_strs.join(", "))
579 }
580 Pattern::Variant { enum_name, variant, fields, .. } => {
581 let full_name = if let Some(en) = enum_name {
582 format!("{}::{}", en, variant)
583 } else {
584 variant.clone()
585 };
586
587 match fields {
588 VariantPatternFields::Unit => full_name,
589 VariantPatternFields::Tuple(pats) => {
590 let pat_strs: Vec<String> = pats.iter().map(|p| self.gen_pattern(p)).collect();
591 format!("{}({})", full_name, pat_strs.join(", "))
592 }
593 VariantPatternFields::Struct(field_pats) => {
594 let field_strs: Vec<String> = field_pats
595 .iter()
596 .map(|(n, p)| format!("{}: {}", n, self.gen_pattern(p)))
597 .collect();
598 format!("{} {{ {} }}", full_name, field_strs.join(", "))
599 }
600 }
601 }
602 Pattern::Slice { patterns, rest, .. } => {
603 let mut pat_strs: Vec<String> = patterns.iter().map(|p| self.gen_pattern(p)).collect();
604 if let Some(rest_name) = rest {
605 pat_strs.push(format!("{} @ ..", rest_name));
606 }
607 format!("[{}]", pat_strs.join(", "))
608 }
609 Pattern::Or(pats, _) => {
610 let pat_strs: Vec<String> = pats.iter().map(|p| self.gen_pattern(p)).collect();
611 pat_strs.join(" | ")
612 }
613 Pattern::Range { start, end, inclusive, .. } => {
614 let s = start.as_ref().map(|e| self.gen_expr(e)).unwrap_or_default();
615 let e = end.as_ref().map(|e| self.gen_expr(e)).unwrap_or_default();
616 if *inclusive {
617 format!("{}..={}", s, e)
618 } else {
619 format!("{}..{}", s, e)
620 }
621 }
622 }
623 }
624
625 fn map_type(&self, ty: &Type) -> String {
627 match ty {
628 Type::Named { name, generics, .. } => {
629 let rust_name = match name.as_str() {
630 "Int" => "i64",
631 "Float" => "f64",
632 "Bool" => "bool",
633 "String" => "String",
634 "Unit" => "()",
635 "Array" => "Vec",
636 _ => name,
637 };
638
639 if generics.is_empty() {
640 rust_name.to_string()
641 } else {
642 let gen_strs: Vec<String> = generics.iter().map(|g| self.map_type(g)).collect();
643 format!("{}<{}>", rust_name, gen_strs.join(", "))
644 }
645 }
646 Type::Tuple(types, _) => {
647 let type_strs: Vec<String> = types.iter().map(|t| self.map_type(t)).collect();
648 format!("({})", type_strs.join(", "))
649 }
650 Type::Array(inner, size, _) => {
651 format!("[{}; {}]", self.map_type(inner), size)
652 }
653 Type::Slice(inner, _) => {
654 format!("[{}]", self.map_type(inner))
655 }
656 Type::Ref { mutable, inner, .. } => {
657 if *mutable {
658 format!("&mut {}", self.map_type(inner))
659 } else {
660 format!("&{}", self.map_type(inner))
661 }
662 }
663 Type::Function { params, return_type, .. } => {
664 let param_strs: Vec<String> = params.iter().map(|p| self.map_type(p)).collect();
665 format!("fn({}) -> {}", param_strs.join(", "), self.map_type(return_type))
666 }
667 Type::Option(inner, _) => {
668 format!("Option<{}>", self.map_type(inner))
669 }
670 Type::Result(ok, err, _) => {
671 format!("Result<{}, {}>", self.map_type(ok), self.map_type(err))
672 }
673 Type::Infer(_) => "_".to_string(),
674 Type::Never(_) => "!".to_string(),
675 Type::Unit(_) => "()".to_string(),
676 Type::Impl { trait_name, generics, .. } => {
677 if generics.is_empty() {
678 format!("impl {}", trait_name)
679 } else {
680 let gen_strs: Vec<String> = generics.iter().map(|g| self.map_type(g)).collect();
681 format!("impl {}<{}>", trait_name, gen_strs.join(", "))
682 }
683 }
684 }
685 }
686
687 fn map_binop(&self, op: &BinaryOp) -> &'static str {
688 match op {
689 BinaryOp::Add => "+",
690 BinaryOp::Sub => "-",
691 BinaryOp::Mul => "*",
692 BinaryOp::Div => "/",
693 BinaryOp::Mod => "%",
694 BinaryOp::Pow => ".pow", BinaryOp::And => "&&",
696 BinaryOp::Or => "||",
697 BinaryOp::Eq => "==",
698 BinaryOp::Ne => "!=",
699 BinaryOp::Lt => "<",
700 BinaryOp::Le => "<=",
701 BinaryOp::Gt => ">",
702 BinaryOp::Ge => ">=",
703 BinaryOp::BitAnd => "&",
704 BinaryOp::BitOr => "|",
705 BinaryOp::BitXor => "^",
706 BinaryOp::Shl => "<<",
707 BinaryOp::Shr => ">>",
708 BinaryOp::Assign => "=",
709 BinaryOp::AddAssign => "+=",
710 BinaryOp::SubAssign => "-=",
711 BinaryOp::MulAssign => "*=",
712 BinaryOp::DivAssign => "/=",
713 BinaryOp::Range => "..",
714 BinaryOp::RangeInclusive => "..=",
715 }
716 }
717
718 fn map_unaryop(&self, op: &UnaryOp) -> &'static str {
719 match op {
720 UnaryOp::Not => "!",
721 UnaryOp::Neg => "-",
722 UnaryOp::Ref => "&",
723 UnaryOp::RefMut => "&mut ",
724 UnaryOp::BitNot => "!", UnaryOp::Deref => "*",
726 }
727 }
728
729 fn escape_string(&self, s: &str) -> String {
730 let mut result = String::new();
731 for c in s.chars() {
732 match c {
733 '\n' => result.push_str("\\n"),
734 '\t' => result.push_str("\\t"),
735 '\\' => result.push_str("\\\\"),
736 '"' => result.push_str("\\\""),
737 _ => result.push(c),
738 }
739 }
740 result
741 }
742}
743
744pub fn gen_cargo_toml(name: &str, deps: &[&str]) -> String {
746 let mut sb = StringBuilder::new();
747
748 sb.push_line("[package]");
749 sb.push_line(&format!("name = \"{}\"", name));
750 sb.push_line("version = \"0.1.0\"");
751 sb.push_line("edition = \"2021\"");
752 sb.push_line("");
753 sb.push_line("# Generated by KAIN Compiler");
754 sb.push_line("");
755 sb.push_line("[dependencies]");
756
757 for dep in deps {
758 sb.push_line(&format!("{} = \"*\"", dep));
759 }
760
761 sb.build()
762}
763
764#[cfg(test)]
765mod tests {
766 use super::*;
767
768 #[test]
769 fn test_type_mapping() {
770 let gen = RustGen::new();
771 let int_ty = Type::Named {
772 name: "Int".to_string(),
773 generics: vec![],
774 span: Span::default(),
775 };
776 assert_eq!(gen.map_type(&int_ty), "i64");
777 }
778}