Skip to main content

knave_expand/expand/
generated_entry.rs

1use 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}