Skip to main content

knave_expand/reader/
form.rs

1use std::fmt;
2use std::rc::Rc;
3
4use crate::scope::{ChainPrefix, Scope, ScopeSet};
5use crate::source::Span;
6
7#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
8pub struct Form {
9    kind: Rc<FormKind>,
10    span: Span,
11}
12
13#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
14pub enum FormKind {
15    Symbol(Symbol),
16    String(Rc<str>),
17    Number(Number),
18    List(Vec<Form>),
19}
20
21impl Form {
22    pub const NESTING_LIMIT: usize = 1024;
23
24    pub fn new(kind: FormKind, span: Span) -> Self {
25        Self {
26            kind: Rc::new(kind),
27            span,
28        }
29    }
30
31    pub fn kind(&self) -> &FormKind {
32        &self.kind
33    }
34
35    pub fn span(&self) -> Span {
36        self.span
37    }
38
39    pub fn is_same_form(&self, other: &Form) -> bool {
40        Rc::ptr_eq(&self.kind, &other.kind)
41    }
42
43    pub fn identity(&self) -> *const FormKind {
44        Rc::as_ptr(&self.kind)
45    }
46
47    pub fn form_count(&self) -> usize {
48        let items = self.as_list().unwrap_or_default();
49        1 + items.iter().map(Form::form_count).sum::<usize>()
50    }
51
52    pub fn as_symbol(&self) -> Option<&Symbol> {
53        match self.kind() {
54            FormKind::Symbol(symbol) => Some(symbol),
55            _ => None,
56        }
57    }
58
59    pub fn as_list(&self) -> Option<&[Form]> {
60        match self.kind() {
61            FormKind::List(items) => Some(items),
62            _ => None,
63        }
64    }
65
66    pub fn add_scope(&mut self, scope: Scope) {
67        self.update_scopes(&|scopes| scopes.add(scope));
68    }
69
70    pub fn add_prefix(&mut self, prefix: &ChainPrefix) {
71        self.update_scopes(&|scopes| scopes.add_prefix(prefix));
72    }
73
74    pub fn flip_scope(&mut self, scope: Scope) {
75        self.update_scopes(&|scopes| scopes.flip(scope));
76    }
77
78    pub fn flip_scope_within(&mut self, scope: Scope, allowance: &mut usize) -> bool {
79        self.update_scopes_within(&|scopes| scopes.flip(scope), allowance)
80    }
81
82    pub fn remove_scope(&mut self, scope: Scope) {
83        self.update_scopes(&|scopes| scopes.remove(scope));
84    }
85
86    pub fn retain_scopes(&mut self, keep: &dyn Fn(Scope) -> bool) {
87        self.update_scopes(&|scopes| scopes.retain(keep));
88    }
89
90    pub fn relocate_outside(&mut self, region: Span) {
91        if !region.contains(self.span) {
92            self.span = region;
93        }
94        if self.as_list().is_some()
95            && let FormKind::List(items) = Rc::make_mut(&mut self.kind)
96        {
97            items
98                .iter_mut()
99                .for_each(|item| item.relocate_outside(region));
100        }
101    }
102
103    fn update_scopes(&mut self, update: &dyn Fn(&mut ScopeSet)) {
104        match self.scoped_kind_mut() {
105            Some(FormKind::Symbol(symbol)) => update(symbol.scopes_mut()),
106            Some(FormKind::List(items)) => {
107                items.iter_mut().for_each(|item| item.update_scopes(update))
108            }
109            _ => {}
110        }
111    }
112
113    fn update_scopes_within(
114        &mut self,
115        update: &dyn Fn(&mut ScopeSet),
116        allowance: &mut usize,
117    ) -> bool {
118        let Some(remaining) = allowance.checked_sub(1) else {
119            return false;
120        };
121        *allowance = remaining;
122        match self.scoped_kind_mut() {
123            Some(FormKind::Symbol(symbol)) => {
124                update(symbol.scopes_mut());
125                true
126            }
127            Some(FormKind::List(items)) => items
128                .iter_mut()
129                .all(|item| item.update_scopes_within(update, allowance)),
130            _ => true,
131        }
132    }
133
134    #[inline(always)]
135    fn scoped_kind_mut(&mut self) -> Option<&mut FormKind> {
136        match self.kind() {
137            FormKind::Symbol(_) | FormKind::List(_) => Some(Rc::make_mut(&mut self.kind)),
138            FormKind::String(_) | FormKind::Number(_) => None,
139        }
140    }
141}
142
143impl fmt::Display for Form {
144    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
145        match self.kind() {
146            FormKind::Symbol(symbol) => write!(formatter, "{}", symbol.name()),
147            FormKind::String(text) => write!(formatter, "{text:?}"),
148            FormKind::Number(number) => write!(formatter, "{}", number.text()),
149            FormKind::List(items) => Self::fmt_list(items, formatter),
150        }
151    }
152}
153
154impl Form {
155    fn fmt_list(items: &[Form], formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
156        let rendered: Vec<String> = items.iter().map(Form::to_string).collect();
157        write!(formatter, "({})", rendered.join(" "))
158    }
159}
160
161#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
162pub struct Symbol {
163    name: Rc<str>,
164    scopes: ScopeSet,
165}
166
167impl Symbol {
168    pub fn new(name: impl Into<Rc<str>>) -> Self {
169        Self::with_scopes(name, ScopeSet::default())
170    }
171
172    pub fn with_scopes(name: impl Into<Rc<str>>, scopes: ScopeSet) -> Self {
173        Self {
174            name: name.into(),
175            scopes,
176        }
177    }
178
179    pub fn name(&self) -> &str {
180        &self.name
181    }
182
183    pub fn shared_name(&self) -> Rc<str> {
184        Rc::clone(&self.name)
185    }
186
187    pub fn scopes(&self) -> &ScopeSet {
188        &self.scopes
189    }
190
191    pub fn scopes_mut(&mut self) -> &mut ScopeSet {
192        &mut self.scopes
193    }
194}
195
196#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
197pub enum NumberValue {
198    Integer(i128),
199    Float(f64),
200}
201
202#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
203pub struct Number {
204    text: Rc<str>,
205    value: NumberValue,
206}
207
208impl Number {
209    pub fn new(text: impl Into<Rc<str>>, value: NumberValue) -> Self {
210        Self {
211            text: text.into(),
212            value,
213        }
214    }
215
216    pub fn text(&self) -> &str {
217        &self.text
218    }
219
220    pub fn value(&self) -> &NumberValue {
221        &self.value
222    }
223}