knave_expand/expand/
generated_entry.rs1use std::rc::Rc;
2
3use super::Program;
4use super::result_printer::{GeneratedFunction, ResultPrinter};
5use crate::core::{BindingId, Block, BodyItem, Expr, ExprKind, Item, ItemKind, Lambda};
6use crate::source::Span;
7
8#[derive(Clone)]
9pub struct GeneratedEntry {
10 binding: BindingId,
11 body: Block,
12 span: Span,
13 functions: Vec<GeneratedFunction>,
14}
15
16impl GeneratedEntry {
17 pub(super) fn new(binding: BindingId, body: Block, span: Span) -> Self {
18 Self {
19 binding,
20 body,
21 span,
22 functions: Vec::new(),
23 }
24 }
25
26 pub fn printing(&self, printer: &ResultPrinter, printed: &[usize]) -> Self {
27 let items = self
28 .body
29 .items
30 .iter()
31 .enumerate()
32 .map(|(position, item)| match item {
33 BodyItem::Expr(expr) if printed.contains(&position) => {
34 BodyItem::Expr(printer.print(expr))
35 }
36 other => other.clone(),
37 });
38 Self {
39 body: Block {
40 items: items.collect(),
41 },
42 functions: printer.functions().to_vec(),
43 ..self.clone()
44 }
45 }
46
47 fn defines(&self, binding: BindingId) -> bool {
48 binding == self.binding
49 || self
50 .functions
51 .iter()
52 .any(|function| function.binding() == binding)
53 }
54
55 fn items(&self) -> impl Iterator<Item = Item> {
56 let functions = self.functions.iter().map(GeneratedFunction::item);
57 functions.chain(std::iter::once(self.item()))
58 }
59
60 fn item(&self) -> Item {
61 let lambda = Lambda {
62 params: Vec::new(),
63 body: self.body.clone(),
64 };
65 let holds_no_written_text = self.span.start();
66 let value = Expr::new(ExprKind::Fn(Rc::new(lambda)), holds_no_written_text);
67 Item {
68 kind: ItemKind::Def(self.binding, Rc::new(value)),
69 span: self.span,
70 hidden: false,
71 }
72 }
73}
74
75impl Program {
76 pub fn enter(&mut self, entry: &GeneratedEntry) {
77 let entry_module = self.entry;
78 let module = self
79 .modules
80 .iter_mut()
81 .find(|module| module.id == entry_module)
82 .expect("the entry module is expanded");
83 module.items.retain(
84 |item| !matches!(item.kind, ItemKind::Def(binding, _) if entry.defines(binding)),
85 );
86 module.items.extend(entry.items());
87 self.entry_function = Some(entry.binding);
88 self.restore_reached();
89 }
90}