1use crate::error::TabnasError;
4use crate::options::Options;
5use crate::rule::{Rule, RuleSnapshot};
6use crate::token::Token;
7use crate::value::unwrap_arc;
8use crate::value::Value;
9use indexmap::IndexMap;
10use std::cell::RefCell;
11use std::collections::VecDeque;
12use std::fmt;
13use std::rc::Rc;
14use std::sync::Arc;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ActionError {
18 pub code: String,
19 pub detail: String,
20}
21
22impl ActionError {
23 pub fn new(code: impl Into<String>, detail: impl Into<String>) -> Self {
24 Self {
25 code: code.into(),
26 detail: detail.into(),
27 }
28 }
29}
30
31impl fmt::Display for ActionError {
32 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
33 formatter.write_str(&self.detail)
34 }
35}
36
37impl std::error::Error for ActionError {}
38
39#[derive(Debug, Clone, Default, PartialEq, Eq)]
43pub struct InstanceInfo {
44 pub id: String,
45 pub parent_id: Option<String>,
46 pub tag: String,
47 pub plugins: Vec<String>,
48 pub rule_names: Vec<String>,
49}
50
51#[derive(Debug, Clone, Default, PartialEq)]
55pub struct ContextSeed {
56 pub meta: Option<Value>,
57 pub u: IndexMap<String, Value>,
58}
59
60impl From<ActionError> for TabnasError {
61 fn from(action_error: ActionError) -> Self {
62 let mut error = TabnasError::new(action_error.code, "", "", 0, 1, 1);
63 error.detail = action_error.detail;
64 error
65 }
66}
67
68fn follow_stack(frames: &mut Vec<Rc<RuleSnapshot>>, stack: &[Rule]) {
70 frames.truncate(stack.len());
71 for rule in &stack[frames.len()..] {
72 frames.push(rule.snapshot());
73 }
74}
75
76#[cfg(debug_assertions)]
86fn same_rule(snapshot: &crate::RuleSnapshot, rule: &Rule) -> bool {
87 snapshot.i == rule.i
88 && snapshot.d == rule.d
89 && snapshot.name == rule.name
92 && snapshot.state == rule.state
93 && snapshot.need == rule.need
94 && snapshot.bo == rule.bo
95 && snapshot.ao == rule.ao
96 && snapshot.bc == rule.bc
97 && snapshot.ac == rule.ac
98 && snapshot.next_rule_name == rule.next_rule_name
99 && snapshot.n == rule.n
100 && same_values(&snapshot.u, &rule.u)
101 && same_values(&snapshot.k, &rule.k)
102 && same_tokens(&snapshot.o, &rule.o)
103 && same_tokens(&snapshot.c, &rule.c)
104 && same_link(&snapshot.parent_rule, &rule.parent_rule)
105 && same_link(&snapshot.child_rule, &rule.child_rule)
106 && same_link(&snapshot.prev_rule, &rule.prev_rule)
107 && same_link(&snapshot.next_rule, &rule.next_rule)
108}
109
110#[cfg(debug_assertions)]
111fn same_values(
112 left: &std::collections::HashMap<String, Value>,
113 right: &std::collections::HashMap<String, Value>,
114) -> bool {
115 left.len() == right.len()
116 && left
117 .iter()
118 .all(|(key, value)| right.get(key).is_some_and(|other| value.deep_equal(other)))
119}
120
121#[cfg(debug_assertions)]
125fn same_tokens(left: &[Token], right: &[Token]) -> bool {
126 left.len() == right.len()
127 && left.iter().zip(right).all(|(left, right)| {
128 left.name == right.name
129 && left.tin == right.tin
130 && left.src == right.src
131 && left.len == right.len
132 && left.site == right.site
133 && left.err == right.err
134 && left.why == right.why
135 && left.val.deep_equal(&right.val)
136 && same_values(left.use_data(), right.use_data())
137 })
138}
139
140#[cfg(debug_assertions)]
144fn same_link(
145 snapshot: &Option<std::rc::Rc<crate::RuleSnapshot>>,
146 rule: &Option<std::rc::Rc<crate::RuleSnapshot>>,
147) -> bool {
148 match (snapshot, rule) {
149 (None, None) => true,
150 (Some(left), Some(right)) => std::rc::Rc::ptr_eq(left, right),
151 _ => false,
152 }
153}
154
155#[derive(Debug)]
162pub struct Context {
163 pub iteration: usize,
165 pub source: String,
167 pub meta: Value,
169 pub u: IndexMap<String, Value>,
171 pub errs: Vec<TabnasError>,
173 pub options: Arc<Options>,
179 pub instance: InstanceInfo,
181 pub rule: Option<Rc<RuleSnapshot>>,
184 pub rule_stack: Vec<Rc<RuleSnapshot>>,
185 #[cfg(debug_assertions)]
189 rule_stack_shadow: Vec<Rc<RuleSnapshot>>,
190 pub v: VecDeque<Token>,
197 pub v_abs: usize,
199 pub t: Vec<Token>,
201 replay: VecDeque<Token>,
202 history_limit: Option<usize>,
203 root: Option<Rc<RefCell<Value>>>,
204 pub(crate) recover_at: Option<usize>,
205 pub(crate) recover_si: Option<usize>,
206 pub(crate) bad_to: Option<usize>,
207 pub(crate) bad_error: Option<usize>,
208}
209
210impl Context {
211 pub(crate) fn new(
212 history_limit: Option<usize>,
213 source: impl Into<String>,
214 meta: Value,
215 options: Arc<Options>,
216 instance: InstanceInfo,
217 ) -> Self {
218 Self {
219 iteration: 0,
220 source: source.into(),
221 meta,
222 u: IndexMap::new(),
223 errs: Vec::new(),
224 options,
225 instance,
226 rule: None,
227 rule_stack: Vec::new(),
228 #[cfg(debug_assertions)]
229 rule_stack_shadow: Vec::new(),
230 v: VecDeque::new(),
231 v_abs: 0,
232 t: Vec::with_capacity(8),
233 replay: VecDeque::new(),
234 history_limit,
235 root: None,
236 recover_at: None,
237 recover_si: None,
238 bad_to: None,
239 bad_error: None,
240 }
241 }
242
243 pub fn mark(&self) -> usize {
245 self.v_abs
246 }
247
248 pub fn v1(&self) -> Option<&Token> {
250 self.v.back()
251 }
252
253 pub fn v2(&self) -> Option<&Token> {
255 self.v.get(self.v.len().wrapping_sub(2))
256 }
257
258 pub fn t0(&self) -> Option<&Token> {
259 self.t.first()
260 }
261
262 pub fn t1(&self) -> Option<&Token> {
263 self.t.get(1)
264 }
265
266 pub fn set_t0(&mut self, token: Token) {
267 if self.t.is_empty() {
268 self.t.push(token);
269 } else {
270 self.t[0] = token;
271 }
272 }
273
274 pub fn set_t1(&mut self, token: Token) {
275 while self.t.len() < 2 {
276 self.t.push(Token::no_token());
277 }
278 self.t[1] = token;
279 }
280
281 pub fn set_v1(&mut self, token: Token) {
282 if let Some(last) = self.v.back_mut() {
283 *last = token;
284 } else {
285 self.v.push_back(token);
286 }
287 }
288
289 pub fn set_v2(&mut self, token: Token) {
290 match self.v.len() {
291 0 => self.v.push_back(token),
292 1 => self.v.push_front(token),
293 length => self.v[length - 2] = token,
294 }
295 }
296
297 pub fn root(&self) -> Option<Value> {
298 self.root.as_ref().map(|root| root.borrow().clone())
299 }
300
301 pub(crate) fn set_root(&mut self, root: Rc<RefCell<Value>>) {
302 self.root = Some(root);
303 }
304
305 pub(crate) fn set_active(&mut self, rule: &Rule, stack: &[Rule]) {
306 self.set_rule(rule);
307 self.sync_rule_stack(stack);
308 }
309
310 fn sync_rule_stack(&mut self, stack: &[Rule]) {
344 follow_stack(&mut self.rule_stack, stack);
345 #[cfg(debug_assertions)]
346 {
347 follow_stack(&mut self.rule_stack_shadow, stack);
348 debug_assert!(
349 self.rule_stack_shadow
350 .iter()
351 .zip(stack)
352 .all(|(snapshot, rule)| same_rule(snapshot, rule)),
353 "the incremental rule stack drifted from the live parse stack"
354 );
355 }
356 }
357
358 pub(crate) fn set_rule(&mut self, rule: &Rule) {
359 self.rule = Some(rule.snapshot());
360 }
361
362 pub(crate) fn apply_seed(&mut self, seed: &ContextSeed) {
363 if let Some(meta) = &seed.meta {
364 self.meta = merge_seed_value(self.meta.clone(), meta.clone());
365 }
366 for (key, value) in &seed.u {
367 let previous = self.u.shift_remove(key).unwrap_or(Value::Undefined);
368 self.u
369 .insert(key.clone(), merge_seed_value(previous, value.clone()));
370 }
371 self.errs.clear();
372 }
373
374 pub fn rewind(&mut self, mark: usize) -> Result<(), ActionError> {
381 let Some(count) = self.v_abs.checked_sub(mark) else {
382 return Ok(());
383 };
384 if count == 0 {
385 return Ok(());
386 }
387 if count > self.v.len() {
388 return Err(ActionError::new(
389 "internal",
390 format!(
391 "tabnas: ctx.rewind target {mark} is outside the retained history window \
392 (oldest mark available is {}, current is {}); increase \
393 options.rewind.history",
394 self.v_abs - self.v.len(),
395 self.v_abs,
396 ),
397 ));
398 }
399
400 let retained_at = self.v.len() - count;
401 let rewound = self.v.split_off(retained_at);
402 let lookahead = std::mem::take(&mut self.t);
403 let pending = std::mem::take(&mut self.replay);
404 self.replay = rewound
405 .into_iter()
406 .chain(lookahead)
407 .chain(pending)
408 .collect();
409 self.v_abs -= count;
410 Ok(())
411 }
412
413 pub(crate) fn record_consumed(&mut self, count: usize) {
414 if count == 0 {
415 return;
416 }
417 let count = count.min(self.t.len());
418 self.v.extend(self.t.drain(0..count));
419 self.v_abs += count;
420
421 if let Some(limit) = self.history_limit {
422 if self.v.len() > 2 * limit {
423 let remove = self.v.len() - limit;
424 self.v.drain(0..remove);
425 }
426 }
427 }
428
429 pub(crate) fn next_replay(&mut self) -> Option<Token> {
430 self.replay.pop_front()
431 }
432
433 pub(crate) fn take_replay(&mut self) -> VecDeque<Token> {
434 std::mem::take(&mut self.replay)
435 }
436
437 pub(crate) fn restore_replay(&mut self, replay: VecDeque<Token>) {
438 self.replay = replay;
439 }
440}
441
442fn merge_seed_value(base: Value, overlay: Value) -> Value {
443 match (base, overlay) {
444 (base, Value::Undefined) => base,
445 (Value::Object(base), Value::Object(overlay)) => {
446 let mut base = unwrap_arc(base);
447 for (key, value) in unwrap_arc(overlay) {
448 let previous = base.shift_remove(&key).unwrap_or(Value::Undefined);
449 base.insert(key, merge_seed_value(previous, value));
450 }
451 Value::object(base)
452 }
453 (_, overlay) => overlay,
454 }
455}