1use super::gc::{Context, ObjectMap, Rto, Slot};
2use super::object::{LispBuffer, Object, OpenBuffer, Symbol, WithLifetime};
3use anyhow::{Result, anyhow};
4use rune_macros::Trace;
5use std::cell::OnceCell;
6
7mod stack;
8mod symbol_map;
9pub(crate) use stack::*;
10pub(crate) use symbol_map::*;
11
12type PropertyMap<'a> = ObjectMap<Slot<Symbol<'a>>, Vec<(Slot<Symbol<'a>>, Slot<Object<'a>>)>>;
13#[derive(Debug, Default, Trace)]
14pub(crate) struct Env<'a> {
15 pub(crate) vars: ObjectMap<Slot<Symbol<'a>>, Slot<Object<'a>>>,
16 pub(crate) props: PropertyMap<'a>,
17 pub(crate) catch_stack: Vec<Slot<Object<'a>>>,
18 exception: (Slot<Object<'a>>, Slot<Object<'a>>),
19 #[no_trace]
20 exception_id: u32,
21 binding_stack: Vec<(Slot<Symbol<'a>>, Option<Slot<Object<'a>>>)>,
22 pub(crate) match_data: Slot<Object<'a>>,
23 #[no_trace]
24 pub(crate) current_buffer: CurrentBuffer<'a>,
25 pub(crate) stack: LispStack<'a>,
26}
27
28#[derive(Debug)]
29pub(crate) struct CurrentBuffer<'a> {
30 buffer: OnceCell<OpenBuffer<'a>>,
31 pub(crate) buf_ref: &'a LispBuffer,
32}
33
34impl Default for CurrentBuffer<'_> {
35 fn default() -> Self {
36 let name = crate::buffer::generate_new_buffer_name("*scratch*", None);
37 let buffer = {
38 let global = INTERNED_SYMBOLS.lock().unwrap();
40 unsafe { global.create_buffer(&name).with_lifetime() }
41 };
42 crate::buffer::BUFFERS.lock().unwrap().insert(name, buffer);
43 Self { buffer: Default::default(), buf_ref: buffer }
44 }
45}
46
47impl<'a> CurrentBuffer<'a> {
48 fn lock(&self) -> OpenBuffer<'a> {
49 unsafe { self.buf_ref.lock().unwrap().with_lifetime() }
50 }
51
52 pub(crate) fn get(&self) -> &OpenBuffer<'a> {
53 self.buffer.get_or_init(|| self.lock())
54 }
55
56 pub(crate) fn get_mut(&mut self) -> &mut OpenBuffer<'a> {
57 if self.buffer.get().is_none() {
59 let locked = self.lock();
60 let _ = self.buffer.set(locked);
61 }
62 self.buffer.get_mut().unwrap()
63 }
64
65 pub(crate) fn set(&mut self, buffer: &LispBuffer) {
66 let buffer = unsafe { buffer.with_lifetime() };
67 self.buf_ref = buffer;
68 self.release();
69 }
70
71 pub(crate) fn release(&mut self) {
72 self.buffer.take();
73 }
74}
75
76impl PartialEq<LispBuffer> for CurrentBuffer<'_> {
77 fn eq(&self, other: &LispBuffer) -> bool {
78 self.buf_ref == other
79 }
80}
81
82impl<'a> RootedEnv<'a> {
84 pub(crate) fn set_var(&mut self, sym: Symbol, value: Object) -> Result<()> {
85 if sym.is_const() {
86 Err(anyhow!("Attempt to set a constant symbol: {sym}"))
87 } else {
88 self.vars.insert(sym, value);
89 Ok(())
90 }
91 }
92
93 pub(crate) fn set_prop(&mut self, symbol: Symbol, propname: Symbol, value: Object) {
94 match self.props.get_mut(symbol) {
95 Some(plist) => match plist.iter_mut().find(|x| x.0 == propname) {
96 Some(x) => x.1.set(value),
97 None => plist.push((propname, value)),
98 },
99 None => {
100 self.props.insert(symbol, vec![(propname, value)]);
101 }
102 }
103 }
104
105 pub(crate) fn set_exception(&mut self, tag: Object, data: Object) -> u32 {
106 self.exception.0.set(tag);
107 self.exception.1.set(data);
108 self.exception_id += 1;
109 self.exception_id
110 }
111
112 pub(crate) fn get_exception(&self, id: u32) -> Option<(&Rto<Object<'a>>, &Rto<Object<'a>>)> {
113 (id == self.exception_id).then_some((&self.exception.0, &self.exception.1))
114 }
115
116 pub(crate) fn varbind(&mut self, var: Symbol, value: Object, cx: &Context) {
117 let prev_value = self.vars.get(var).map(|x| x.bind(cx));
118 self.binding_stack.push((var, prev_value));
119 self.vars.insert(var, value);
120 }
121
122 pub(crate) fn unbind(&mut self, count: u16, cx: &Context) {
123 for _ in 0..count {
124 match self.binding_stack.bind_mut(cx).pop() {
125 Some((sym, val)) => match val {
126 Some(val) => self.vars.insert(*sym, *val),
127 None => self.vars.remove(*sym),
128 },
129 None => panic!("Binding stack was empty"),
130 }
131 }
132 }
133
134 pub(crate) fn defvar(&mut self, var: Symbol, value: Object) -> Result<()> {
135 if self.vars.get(var).is_none() {
138 self.set_var(var, value)?;
139 var.make_special();
140 }
141
142 for binding in &mut *self.binding_stack {
145 if binding.0 == var && binding.1.is_none() {
146 binding.1.set(Some(value));
147 }
148 }
149 Ok(())
150 }
151
152 pub(crate) fn set_buffer(&mut self, buffer: &LispBuffer) {
153 if buffer == self.current_buffer.buf_ref {
154 return;
155 }
156 self.current_buffer.set(buffer);
157 }
158
159 pub(crate) fn with_buffer<T>(
160 &self,
161 buffer: &LispBuffer,
162 mut func: impl FnMut(&OpenBuffer) -> T,
163 ) -> Result<T> {
164 if self.current_buffer == *buffer {
165 Ok(func(self.current_buffer.get()))
166 } else {
167 let buffer = buffer.lock()?;
168 Ok(func(&buffer))
169 }
170 }
171
172 pub(crate) fn with_buffer_mut<T>(
173 &mut self,
174 buffer: &LispBuffer,
175 mut func: impl FnMut(&mut OpenBuffer) -> T,
176 ) -> Result<T> {
177 if self.current_buffer == *buffer {
178 Ok(func(self.current_buffer.get_mut()))
179 } else {
180 let mut buffer = buffer.lock()?;
181 Ok(func(&mut buffer))
182 }
183 }
184}