Skip to main content

hara_native/kernel/generated/
rewrite.rs

1use super::super::Form;
2use super::{canonical, known_namespace, GeneratedNamespaceConfig};
3
4impl GeneratedNamespaceConfig {
5    pub fn rewrite(&self, form: Form) -> Form {
6        self.rewrite_form(form, false)
7    }
8
9    /// Rewrites a form before macro expansion. In addition to ordinary
10    /// namespace aliases and `:refer` entries, explicit `:refer-macros`
11    /// declarations canonicalize list operators to the defining macro Var.
12    pub fn rewrite_for_macroexpand(&self, form: Form) -> Form {
13        self.rewrite_form(form, true)
14    }
15
16    fn rewrite_form(&self, form: Form, macro_head: bool) -> Form {
17        match form {
18            Form::Symbol(name) => Form::Symbol(self.resolve_symbol(&name)),
19            Form::List(values) => {
20                if matches!(
21                    values.first(),
22                    Some(Form::Symbol(name))
23                        if name == "quote"
24                            || name == "require"
25                            || (macro_head && name == "syntax-quote")
26                ) {
27                    return Form::List(values);
28                }
29                let mut values = values.into_iter();
30                let Some(head) = values.next() else {
31                    return Form::List(Vec::new());
32                };
33                let head = match head {
34                    Form::Symbol(name) if macro_head => {
35                        Form::Symbol(self.resolve_macro_symbol(&name))
36                    }
37                    value => self.rewrite_form(value, macro_head),
38                };
39                Form::List(
40                    std::iter::once(head)
41                        .chain(values.map(|value| self.rewrite_form(value, macro_head)))
42                        .collect(),
43                )
44            }
45            Form::Vector(values) => Form::Vector(
46                values
47                    .into_iter()
48                    .map(|value| self.rewrite_form(value, macro_head))
49                    .collect(),
50            ),
51            Form::Set(values) => Form::Set(
52                values
53                    .into_iter()
54                    .map(|value| self.rewrite_form(value, macro_head))
55                    .collect(),
56            ),
57            Form::Map(values) => Form::Map(
58                values
59                    .into_iter()
60                    .map(|(key, value)| {
61                        (
62                            self.rewrite_form(key, macro_head),
63                            self.rewrite_form(value, macro_head),
64                        )
65                    })
66                    .collect(),
67            ),
68            Form::Tagged(tag, value) => {
69                Form::Tagged(tag, Box::new(self.rewrite_form(*value, macro_head)))
70            }
71            Form::Metadata(meta, value) => {
72                Form::Metadata(meta, Box::new(self.rewrite_form(*value, macro_head)))
73            }
74            value => value,
75        }
76    }
77
78    fn resolve_macro_symbol(&self, symbol: &str) -> String {
79        self.macro_refers
80            .get(symbol)
81            .cloned()
82            .unwrap_or_else(|| self.resolve_symbol(symbol))
83    }
84
85    fn resolve_symbol(&self, symbol: &str) -> String {
86        if let Some(canonical) = crate::core::canonical_native_symbol(symbol) {
87            return canonical;
88        }
89        if let Some(canonical) = self.refers.get(symbol) {
90            return canonical.clone();
91        }
92        if symbol.contains('/') {
93            if let Ok(registry) = crate::core::namespace_registry() {
94                if let Some(variable) = registry.resolve(&crate::lang::data::Symbol::parse(symbol)) {
95                    return variable.symbol().as_str().to_owned();
96                }
97            }
98        }
99        let Some((alias, method)) = symbol.split_once('/') else {
100            return symbol.into();
101        };
102        if self.lazy_aliases.contains_key(alias) {
103            return symbol.into();
104        }
105        if let Some(namespace) = self.global_aliases.get(alias) {
106            return canonical(namespace, method);
107        }
108        if let Some(namespace) = self.aliases.get(alias) {
109            return canonical(namespace, method);
110        }
111        if known_namespace(alias) {
112            return canonical(alias, method);
113        }
114        symbol.into()
115    }
116}