1use std::fmt;
8
9use gruel_builtins::Posture;
10
11use crate::inst::{InstData, Rir, RirArgMode, RirCallArg, RirParamMode, RirPattern};
12
13pub struct RirPrinter<'a, 'b> {
15 rir: &'a Rir,
16 interner: &'b lasso::ThreadedRodeo,
17}
18
19impl<'a, 'b> RirPrinter<'a, 'b> {
20 pub fn new(rir: &'a Rir, interner: &'b lasso::ThreadedRodeo) -> Self {
22 Self { rir, interner }
23 }
24
25 fn format_call_arg(arg: &RirCallArg) -> String {
27 match arg.mode {
28 RirArgMode::MutRef => format!("mut_ref {}", arg.value),
29 RirArgMode::Ref => format!("ref {}", arg.value),
30 RirArgMode::Normal => format!("{}", arg.value),
31 }
32 }
33
34 fn format_call_args(args: &[RirCallArg]) -> String {
36 args.iter()
37 .map(Self::format_call_arg)
38 .collect::<Vec<_>>()
39 .join(", ")
40 }
41
42 fn format_pattern(&self, pat: &RirPattern) -> String {
44 match pat {
45 RirPattern::Wildcard(_) => "_".to_string(),
46 RirPattern::Int(n, _) => n.to_string(),
47 RirPattern::Bool(b, _) => b.to_string(),
48 RirPattern::Path {
49 module,
50 type_name,
51 variant,
52 ..
53 } => {
54 let prefix = if let Some(module_ref) = module {
55 format!("%{}..", module_ref.as_u32())
56 } else {
57 String::new()
58 };
59 format!(
60 "{}{}::{}",
61 prefix,
62 self.interner.resolve(type_name),
63 self.interner.resolve(variant)
64 )
65 }
66 RirPattern::DataVariant {
67 module,
68 type_name,
69 variant,
70 bindings,
71 ..
72 } => {
73 let prefix = if let Some(module_ref) = module {
74 format!("%{}..", module_ref.as_u32())
75 } else {
76 String::new()
77 };
78 let binding_strs: Vec<String> = bindings
79 .iter()
80 .map(|b| {
81 if b.is_wildcard {
82 "_".to_string()
83 } else {
84 let name = b
85 .name
86 .map(|s| self.interner.resolve(&s).to_string())
87 .unwrap_or_else(|| "_".to_string());
88 if b.is_mut {
89 format!("mut {}", name)
90 } else {
91 name
92 }
93 }
94 })
95 .collect();
96 format!(
97 "{}{}::{}({})",
98 prefix,
99 self.interner.resolve(type_name),
100 self.interner.resolve(variant),
101 binding_strs.join(", ")
102 )
103 }
104 RirPattern::StructVariant {
105 module,
106 type_name,
107 variant,
108 field_bindings,
109 ..
110 } => {
111 let prefix = if let Some(module_ref) = module {
112 format!("%{}..", module_ref.as_u32())
113 } else {
114 String::new()
115 };
116 let field_strs: Vec<String> = field_bindings
117 .iter()
118 .map(|fb| {
119 let field = self.interner.resolve(&fb.field_name);
120 if fb.binding.is_wildcard {
121 format!("{}: _", field)
122 } else {
123 let name = fb
124 .binding
125 .name
126 .map(|s| self.interner.resolve(&s).to_string())
127 .unwrap_or_else(|| "_".to_string());
128 if fb.binding.is_mut {
129 format!("{}: mut {}", field, name)
130 } else if name == field {
131 field.to_string()
132 } else {
133 format!("{}: {}", field, name)
134 }
135 }
136 })
137 .collect();
138 format!(
139 "{}{}::{} {{ {} }}",
140 prefix,
141 self.interner.resolve(type_name),
142 self.interner.resolve(variant),
143 field_strs.join(", ")
144 )
145 }
146 RirPattern::Ident { name, is_mut, .. } => {
147 let n = self.interner.resolve(name);
148 if *is_mut {
149 format!("mut {}", n)
150 } else {
151 n.to_string()
152 }
153 }
154 RirPattern::Tuple { elems, .. } => {
155 let parts: Vec<String> = elems.iter().map(|e| self.format_pattern(e)).collect();
156 format!("({})", parts.join(", "))
157 }
158 RirPattern::Struct {
159 module,
160 type_name,
161 fields,
162 has_rest,
163 ..
164 } => {
165 let prefix = if let Some(module_ref) = module {
166 format!("%{}..", module_ref.as_u32())
167 } else {
168 String::new()
169 };
170 let mut parts: Vec<String> = fields
171 .iter()
172 .map(|f| {
173 format!(
174 "{}: {}",
175 self.interner.resolve(&f.field_name),
176 self.format_pattern(&f.pattern)
177 )
178 })
179 .collect();
180 if *has_rest {
181 parts.push("..".to_string());
182 }
183 format!(
184 "{}{} {{ {} }}",
185 prefix,
186 self.interner.resolve(type_name),
187 parts.join(", ")
188 )
189 }
190 RirPattern::ComptimeUnrollArm {
191 binding, iterable, ..
192 } => {
193 format!(
194 "comptime_unroll for {} in %{}",
195 self.interner.resolve(binding),
196 iterable.as_u32()
197 )
198 }
199 }
200 }
201
202 pub fn render(&self) -> String {
204 use std::fmt::Write;
205
206 let mut out = String::new();
207 for (inst_ref, inst) in self.rir.iter() {
208 write!(out, "{} = ", inst_ref).unwrap();
209 match &inst.data {
210 InstData::IntConst(v) => writeln!(out, "const {}", v).unwrap(),
212 InstData::FloatConst(bits) => {
213 writeln!(out, "const {}", f64::from_bits(*bits)).unwrap()
214 }
215 InstData::BoolConst(v) => writeln!(out, "const {}", v).unwrap(),
216 InstData::CharConst(v) => writeln!(out, "const 'U+{:04X}'", v).unwrap(),
217 InstData::StringConst(s) => {
218 writeln!(out, "const {:?}", self.interner.resolve(s)).unwrap()
219 }
220 InstData::UnitConst => writeln!(out, "const ()").unwrap(),
221
222 InstData::Bin { op, lhs, rhs } => writeln!(out, "{} {}, {}", op, lhs, rhs).unwrap(),
223 InstData::Unary { op, operand } => writeln!(out, "{} {}", op, operand).unwrap(),
224 InstData::MakeRef { operand, is_mut } => writeln!(
225 out,
226 "make_ref{} {}",
227 if *is_mut { "_mut" } else { "" },
228 operand
229 )
230 .unwrap(),
231 InstData::BareRangeSubscript => writeln!(out, "bare_range_subscript").unwrap(),
232 InstData::MakeSlice {
233 base,
234 lo,
235 hi,
236 is_mut,
237 } => {
238 write!(
239 out,
240 "make_slice{} {}",
241 if *is_mut { "_mut" } else { "" },
242 base
243 )
244 .unwrap();
245 if let Some(lo) = lo {
246 write!(out, ", lo={}", lo).unwrap();
247 }
248 if let Some(hi) = hi {
249 write!(out, ", hi={}", hi).unwrap();
250 }
251 writeln!(out).unwrap();
252 }
253
254 InstData::Branch {
256 cond,
257 then_block,
258 else_block,
259 is_comptime,
260 } => {
261 let kw = if *is_comptime {
262 "comptime_branch"
263 } else {
264 "branch"
265 };
266 if let Some(else_b) = else_block {
267 writeln!(out, "{} {}, {}, {}", kw, cond, then_block, else_b).unwrap();
268 } else {
269 writeln!(out, "{} {}, {}", kw, cond, then_block).unwrap();
270 }
271 }
272 InstData::Loop { cond, body } => writeln!(out, "loop {}, {}", cond, body).unwrap(),
273 InstData::For {
274 binding,
275 is_mut,
276 iterable,
277 body,
278 } => {
279 let mut_str = if *is_mut { "mut " } else { "" };
280 writeln!(
281 out,
282 "for {}{} in {}, {}",
283 mut_str,
284 self.interner.resolve(binding),
285 iterable,
286 body
287 )
288 .unwrap()
289 }
290 InstData::InfiniteLoop { body } => writeln!(out, "infinite_loop {}", body).unwrap(),
291 InstData::Match {
292 scrutinee,
293 arms_start,
294 arms_len,
295 } => {
296 let arms = self.rir.get_match_arms(*arms_start, *arms_len);
297 let arms_str: Vec<String> = arms
298 .iter()
299 .map(|(pat, body)| format!("{} => {}", self.format_pattern(pat), body))
300 .collect();
301 writeln!(out, "match {} {{ {} }}", scrutinee, arms_str.join(", ")).unwrap();
302 }
303 InstData::Break => writeln!(out, "break").unwrap(),
304 InstData::Continue => writeln!(out, "continue").unwrap(),
305
306 InstData::FnDecl {
308 directives_start: _,
309 directives_len: _,
310 is_pub,
311 is_unchecked,
312 name,
313 params_start,
314 params_len,
315 return_type,
316 body,
317 has_self,
318 receiver_mode: _,
319 } => {
320 let pub_str = if *is_pub { "pub " } else { "" };
321 let unchecked_str = if *is_unchecked { "unchecked " } else { "" };
322 let name_str = self.interner.resolve(name);
323 let ret_str = self.interner.resolve(return_type);
324 let self_str = if *has_self { "self, " } else { "" };
325 let params = self.rir.get_params(*params_start, *params_len);
326 let params_str: Vec<String> = params
327 .iter()
328 .map(|p| {
329 let mode_prefix = match p.mode {
330 RirParamMode::MutRef => "mut_ref ",
331 RirParamMode::Ref => "ref ",
332 RirParamMode::Comptime => "comptime ",
333 RirParamMode::Normal => "",
334 };
335 format!(
336 "{}{}: {}",
337 mode_prefix,
338 self.interner.resolve(&p.name),
339 self.interner.resolve(&p.ty)
340 )
341 })
342 .collect();
343 writeln!(
344 out,
345 "{}{}fn {}({}{}) -> {} {{",
346 pub_str,
347 unchecked_str,
348 name_str,
349 self_str,
350 params_str.join(", "),
351 ret_str
352 )
353 .unwrap();
354 writeln!(out, " {}", body).unwrap();
355 writeln!(out, "}}").unwrap();
356 }
357 InstData::ConstDecl {
358 directives_start: _,
359 directives_len: _,
360 is_pub,
361 name,
362 ty,
363 init,
364 } => {
365 let pub_str = if *is_pub { "pub " } else { "" };
366 let name_str = self.interner.resolve(name);
367 let ty_str = ty
368 .map(|t| format!(": {}", self.interner.resolve(&t)))
369 .unwrap_or_default();
370 writeln!(out, "{}const {}{} = {}", pub_str, name_str, ty_str, init).unwrap();
371 }
372 InstData::Ret(inner) => {
373 if let Some(inner) = inner {
374 writeln!(out, "ret {}", inner).unwrap();
375 } else {
376 writeln!(out, "ret").unwrap();
377 }
378 }
379 InstData::Call {
380 name,
381 args_start,
382 args_len,
383 } => {
384 let name_str = self.interner.resolve(name);
385 let args = self.rir.get_call_args(*args_start, *args_len);
386 writeln!(out, "call {}({})", name_str, Self::format_call_args(&args)).unwrap();
387 }
388 InstData::Intrinsic {
389 name,
390 args_start,
391 args_len,
392 } => {
393 let name_str = self.interner.resolve(name);
394 let args = self.rir.get_inst_refs(*args_start, *args_len);
395 let args_str: Vec<String> = args.iter().map(|a| format!("{}", a)).collect();
396 writeln!(out, "intrinsic @{}({})", name_str, args_str.join(", ")).unwrap();
397 }
398 InstData::TypeIntrinsic { name, type_arg } => {
399 let name_str = self.interner.resolve(name);
400 let type_str = self.interner.resolve(type_arg);
401 writeln!(out, "type_intrinsic @{}({})", name_str, type_str).unwrap();
402 }
403 InstData::TypeInterfaceIntrinsic {
404 name,
405 type_arg,
406 type_inst,
407 interface_arg,
408 } => {
409 let name_str = self.interner.resolve(name);
410 let iface_str = self.interner.resolve(interface_arg);
411 if let Some(t) = type_inst {
412 writeln!(
413 out,
414 "type_intrinsic @{}(%{}, {})",
415 name_str,
416 t.as_u32(),
417 iface_str
418 )
419 .unwrap();
420 } else {
421 let type_str = self.interner.resolve(type_arg);
422 writeln!(
423 out,
424 "type_intrinsic @{}({}, {})",
425 name_str, type_str, iface_str
426 )
427 .unwrap();
428 }
429 }
430 InstData::ParamRef { index, name } => {
431 writeln!(out, "param {} ({})", index, self.interner.resolve(name)).unwrap();
432 }
433 InstData::Block { extra_start, len } => {
434 writeln!(out, "block({}, {})", extra_start, len).unwrap();
435 }
436
437 InstData::Alloc {
439 directives_start: _,
440 directives_len: _,
441 name,
442 is_mut,
443 ty,
444 init,
445 } => {
446 let name_str = name
447 .map(|n| self.interner.resolve(&n).to_string())
448 .unwrap_or_else(|| "_".to_string());
449 let mut_str = if *is_mut { "mut " } else { "" };
450 let ty_str = ty
451 .map(|t| format!(": {}", self.interner.resolve(&t)))
452 .unwrap_or_default();
453 writeln!(out, "alloc {}{}{}= {}", mut_str, name_str, ty_str, init).unwrap();
454 }
455 InstData::StructDestructure {
456 type_name,
457 fields_start,
458 fields_len,
459 init,
460 } => {
461 let type_str = self.interner.resolve(type_name);
462 let fields = self.rir.get_destructure_fields(*fields_start, *fields_len);
463 let field_strs: Vec<String> = fields
464 .iter()
465 .map(|f| {
466 let name = self.interner.resolve(&f.field_name);
467 if f.is_wildcard {
468 format!("{}: _", name)
469 } else if let Some(binding) = f.binding_name {
470 let binding_str = self.interner.resolve(&binding);
471 format!("{}: {}", name, binding_str)
472 } else {
473 name.to_string()
474 }
475 })
476 .collect();
477 writeln!(
478 out,
479 "destructure {} {{ {} }} = {}",
480 type_str,
481 field_strs.join(", "),
482 init
483 )
484 .unwrap();
485 }
486 InstData::VarRef { name } => {
487 writeln!(out, "var_ref {}", self.interner.resolve(name)).unwrap();
488 }
489 InstData::Assign { name, value } => {
490 writeln!(out, "assign {} = {}", self.interner.resolve(name), value).unwrap();
491 }
492
493 InstData::StructDecl {
495 directives_start,
496 directives_len,
497 is_pub,
498 posture,
499 name,
500 fields_start,
501 fields_len,
502 methods_start,
503 methods_len,
504 } => {
505 let pub_str = if *is_pub { "pub " } else { "" };
506 let name_str = self.interner.resolve(name);
507 let fields = self.rir.get_field_decls(*fields_start, *fields_len);
508 let fields_str: Vec<String> = fields
509 .iter()
510 .map(|(fname, ftype)| {
511 format!(
512 "{}: {}",
513 self.interner.resolve(fname),
514 self.interner.resolve(ftype)
515 )
516 })
517 .collect();
518 let directives = self.rir.get_directives(*directives_start, *directives_len);
519 let posture_dir = match posture {
520 Posture::Copy => Some("@mark(copy)"),
521 Posture::Linear => Some("@mark(linear)"),
522 Posture::Affine => None,
523 };
524 let mut dir_names: Vec<String> =
525 posture_dir.into_iter().map(|s| s.to_string()).collect();
526 for d in directives {
527 dir_names.push(format!("@{}", self.interner.resolve(&d.name)));
528 }
529 let directives_str = if dir_names.is_empty() {
530 String::new()
531 } else {
532 format!("{} ", dir_names.join(" "))
533 };
534 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
535 let methods_str = if methods.is_empty() {
536 String::new()
537 } else {
538 let method_refs: Vec<String> =
539 methods.iter().map(|m| format!("{}", m)).collect();
540 format!(" methods: [{}]", method_refs.join(", "))
541 };
542 writeln!(
543 out,
544 "{}{}struct {} {{ {} }}{}",
545 directives_str,
546 pub_str,
547 name_str,
548 fields_str.join(", "),
549 methods_str
550 )
551 .unwrap();
552 }
553 InstData::StructInit {
554 module,
555 type_name,
556 fields_start,
557 fields_len,
558 } => {
559 let module_str = module.map(|m| format!("{}.", m)).unwrap_or_default();
560 let type_str = self.interner.resolve(type_name);
561 let fields = self.rir.get_field_inits(*fields_start, *fields_len);
562 let fields_str: Vec<String> = fields
563 .iter()
564 .map(|(fname, value)| {
565 format!("{}: {}", self.interner.resolve(fname), value)
566 })
567 .collect();
568 writeln!(
569 out,
570 "struct_init {}{} {{ {} }}",
571 module_str,
572 type_str,
573 fields_str.join(", ")
574 )
575 .unwrap();
576 }
577 InstData::FieldGet { base, field } => {
578 writeln!(out, "field_get {}.{}", base, self.interner.resolve(field)).unwrap();
579 }
580 InstData::FieldSet { base, field, value } => {
581 writeln!(
582 out,
583 "field_set {}.{} = {}",
584 base,
585 self.interner.resolve(field),
586 value
587 )
588 .unwrap();
589 }
590
591 InstData::EnumDecl {
593 is_pub,
594 posture,
595 name,
596 variants_start,
597 variants_len,
598 methods_start,
599 methods_len,
600 directives_start: _,
601 directives_len: _,
602 } => {
603 let pub_str = if *is_pub { "pub " } else { "" };
604 let posture_str = match posture {
605 Posture::Copy => "@mark(copy) ",
606 Posture::Linear => "@mark(linear) ",
607 Posture::Affine => "",
608 };
609 let name_str = self.interner.resolve(name);
610 let variants = self
611 .rir
612 .get_enum_variant_decls(*variants_start, *variants_len);
613 let variants_str: Vec<String> = variants
614 .iter()
615 .map(|(v, field_types, field_names)| {
616 let vname = self.interner.resolve(v).to_string();
617 if field_types.is_empty() {
618 vname
619 } else if field_names.is_empty() {
620 let field_strs: Vec<&str> = field_types
622 .iter()
623 .map(|f| self.interner.resolve(f))
624 .collect();
625 format!("{}({})", vname, field_strs.join(", "))
626 } else {
627 let field_strs: Vec<String> = field_names
629 .iter()
630 .zip(field_types.iter())
631 .map(|(n, t)| {
632 format!(
633 "{}: {}",
634 self.interner.resolve(n),
635 self.interner.resolve(t)
636 )
637 })
638 .collect();
639 format!("{} {{ {} }}", vname, field_strs.join(", "))
640 }
641 })
642 .collect();
643 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
644 let methods_str: Vec<String> =
645 methods.iter().map(|m| format!("fn {}", m)).collect();
646 let body_parts: Vec<String> = variants_str
647 .into_iter()
648 .chain(methods_str.into_iter())
649 .collect();
650 writeln!(
651 out,
652 "{}{}enum {} {{ {} }}",
653 posture_str,
654 pub_str,
655 name_str,
656 body_parts.join(", ")
657 )
658 .unwrap();
659 }
660 InstData::EnumVariant {
661 module,
662 type_name,
663 variant,
664 } => {
665 let module_str = module.map(|m| format!("{}.", m)).unwrap_or_default();
666 writeln!(
667 out,
668 "enum_variant {}{}::{}",
669 module_str,
670 self.interner.resolve(type_name),
671 self.interner.resolve(variant)
672 )
673 .unwrap();
674 }
675 InstData::EnumStructVariant {
676 module,
677 type_name,
678 variant,
679 fields_start,
680 fields_len,
681 } => {
682 let module_str = module.map(|m| format!("{}.", m)).unwrap_or_default();
683 let fields = self.rir.get_field_inits(*fields_start, *fields_len);
684 let field_strs: Vec<String> = fields
685 .iter()
686 .map(|(name, value)| format!("{}: {}", self.interner.resolve(name), value))
687 .collect();
688 writeln!(
689 out,
690 "enum_struct_variant {}{}::{} {{ {} }}",
691 module_str,
692 self.interner.resolve(type_name),
693 self.interner.resolve(variant),
694 field_strs.join(", ")
695 )
696 .unwrap();
697 }
698
699 InstData::ArrayInit {
701 elems_start,
702 elems_len,
703 } => {
704 let elements = self.rir.get_inst_refs(*elems_start, *elems_len);
705 let elems_str: Vec<String> =
706 elements.iter().map(|e| format!("{}", e)).collect();
707 writeln!(out, "array_init [{}]", elems_str.join(", ")).unwrap();
708 }
709 InstData::IndexGet { base, index } => {
710 writeln!(out, "index_get {}[{}]", base, index).unwrap();
711 }
712 InstData::IndexSet { base, index, value } => {
713 writeln!(out, "index_set {}[{}] = {}", base, index, value).unwrap();
714 }
715
716 InstData::MethodCall {
718 receiver,
719 method,
720 args_start,
721 args_len,
722 } => {
723 let args = self.rir.get_call_args(*args_start, *args_len);
724 writeln!(
725 out,
726 "method_call {}.{}({})",
727 receiver,
728 self.interner.resolve(method),
729 Self::format_call_args(&args)
730 )
731 .unwrap();
732 }
733 InstData::AssocFnCall {
734 type_name,
735 function,
736 args_start,
737 args_len,
738 } => {
739 let args = self.rir.get_call_args(*args_start, *args_len);
740 writeln!(
741 out,
742 "assoc_fn_call {}::{}({})",
743 self.interner.resolve(type_name),
744 self.interner.resolve(function),
745 Self::format_call_args(&args)
746 )
747 .unwrap();
748 }
749
750 InstData::InterfaceDecl {
752 is_pub,
753 name,
754 methods_start,
755 methods_len,
756 directives_start: _,
757 directives_len: _,
758 } => {
759 let pub_str = if *is_pub { "pub " } else { "" };
760 let name_str = self.interner.resolve(name);
761 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
762 let method_refs: Vec<String> =
763 methods.iter().map(|m| format!("{}", m)).collect();
764 writeln!(
765 out,
766 "{}interface {} {{ {} }}",
767 pub_str,
768 name_str,
769 method_refs.join(", ")
770 )
771 .unwrap();
772 }
773 InstData::InterfaceMethodSig {
774 name,
775 params_start,
776 params_len,
777 return_type,
778 receiver_mode,
779 is_unchecked,
780 directives_start: _,
781 directives_len: _,
782 } => {
783 let params = self.rir.get_params(*params_start, *params_len);
784 let params_str: Vec<String> = params
785 .iter()
786 .map(|p| {
787 format!(
788 "{}: {}",
789 self.interner.resolve(&p.name),
790 self.interner.resolve(&p.ty)
791 )
792 })
793 .collect();
794 let recv = match *receiver_mode {
795 1 => "inout self",
796 2 => "borrow self",
797 _ => "self",
798 };
799 let unchecked_str = if *is_unchecked { "unchecked " } else { "" };
800 writeln!(
801 out,
802 "{}interface_method_sig {}({}{}{}) -> {}",
803 unchecked_str,
804 self.interner.resolve(name),
805 recv,
806 if params.is_empty() { "" } else { ", " },
807 params_str.join(", "),
808 self.interner.resolve(return_type)
809 )
810 .unwrap();
811 }
812
813 InstData::DeriveDecl {
815 name,
816 methods_start,
817 methods_len,
818 } => {
819 let name_str = self.interner.resolve(name);
820 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
821 let method_refs: Vec<String> =
822 methods.iter().map(|m| format!("{}", m)).collect();
823 writeln!(out, "derive {} {{ {} }}", name_str, method_refs.join(", ")).unwrap();
824 }
825
826 InstData::Comptime { expr } => {
828 writeln!(out, "comptime {{ {} }}", expr).unwrap();
829 }
830
831 InstData::ComptimeUnrollFor {
833 binding,
834 iterable,
835 body,
836 } => writeln!(
837 out,
838 "comptime_unroll for {} in {}, {}",
839 self.interner.resolve(binding),
840 iterable,
841 body
842 )
843 .unwrap(),
844
845 InstData::Checked { expr } => {
847 writeln!(out, "checked {{ {} }}", expr).unwrap();
848 }
849
850 InstData::TypeConst { type_name } => {
852 let name = self.interner.resolve(type_name);
853 writeln!(out, "type {}", name).unwrap();
854 }
855
856 InstData::AnonStructType {
858 fields_start,
859 fields_len,
860 methods_start,
861 methods_len,
862 ..
863 } => {
864 write!(out, "struct {{ ").unwrap();
865 let fields = self.rir.get_field_decls(*fields_start, *fields_len);
866 for (i, (name, ty)) in fields.iter().enumerate() {
867 if i > 0 {
868 write!(out, ", ").unwrap();
869 }
870 let name_str = self.interner.resolve(name);
871 let ty_str = self.interner.resolve(ty);
872 write!(out, "{}: {}", name_str, ty_str).unwrap();
873 }
874 if *methods_len > 0 {
876 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
877 let methods_str: Vec<String> =
878 methods.iter().map(|m| format!("{}", m)).collect();
879 if !fields.is_empty() {
880 write!(out, ", ").unwrap();
881 }
882 write!(out, "methods: [{}]", methods_str.join(", ")).unwrap();
883 }
884 writeln!(out, " }}").unwrap();
885 }
886
887 InstData::AnonEnumType {
889 variants_start,
890 variants_len,
891 methods_start,
892 methods_len,
893 ..
894 } => {
895 write!(out, "enum {{ ").unwrap();
896 let variants = self
897 .rir
898 .get_enum_variant_decls(*variants_start, *variants_len);
899 let variants_str: Vec<String> = variants
900 .iter()
901 .map(|(v, field_types, field_names)| {
902 let vname = self.interner.resolve(v).to_string();
903 if field_types.is_empty() {
904 vname
905 } else if field_names.is_empty() {
906 let field_strs: Vec<&str> = field_types
907 .iter()
908 .map(|f| self.interner.resolve(f))
909 .collect();
910 format!("{}({})", vname, field_strs.join(", "))
911 } else {
912 let field_strs: Vec<String> = field_names
913 .iter()
914 .zip(field_types.iter())
915 .map(|(n, t)| {
916 format!(
917 "{}: {}",
918 self.interner.resolve(n),
919 self.interner.resolve(t)
920 )
921 })
922 .collect();
923 format!("{} {{ {} }}", vname, field_strs.join(", "))
924 }
925 })
926 .collect();
927 write!(out, "{}", variants_str.join(", ")).unwrap();
928 if *methods_len > 0 {
929 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
930 let methods_str: Vec<String> =
931 methods.iter().map(|m| format!("{}", m)).collect();
932 if !variants_str.is_empty() {
933 write!(out, ", ").unwrap();
934 }
935 write!(out, "methods: [{}]", methods_str.join(", ")).unwrap();
936 }
937 writeln!(out, " }}").unwrap();
938 }
939 InstData::TupleInit {
941 elems_start,
942 elems_len,
943 } => {
944 let elems = self.rir.get_inst_refs(*elems_start, *elems_len);
945 let elems_str: Vec<String> = elems.iter().map(|e| format!("{}", e)).collect();
946 if elems.len() == 1 {
947 writeln!(out, "tuple ({},)", elems_str[0]).unwrap();
948 } else {
949 writeln!(out, "tuple ({})", elems_str.join(", ")).unwrap();
950 }
951 }
952 InstData::AnonFnValue { method } => {
954 writeln!(out, "anon_fn call={}", method).unwrap();
955 }
956 InstData::AnonInterfaceType {
958 methods_start,
959 methods_len,
960 } => {
961 let methods = self.rir.get_inst_refs(*methods_start, *methods_len);
962 let refs: Vec<String> = methods.iter().map(|m| format!("{}", m)).collect();
963 writeln!(out, "anon_interface_type {{ {} }}", refs.join(", ")).unwrap();
964 }
965 }
966 }
967 out
968 }
969}
970
971impl fmt::Display for RirPrinter<'_, '_> {
972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
973 write!(f, "{}", self.render())
974 }
975}