1use std::cell::RefCell;
2use std::rc::Rc;
3
4use anyhow::Result;
5use num_bigint::BigInt;
6use tycho_vm::{SafeDelete, SafeRc};
7
8use super::stack::RcIntoDynFiftValue;
9use super::{Context, Dictionary, Stack, StackValue, StackValueType, WordList};
10use crate::core::IntoDynFiftValue;
11use crate::util::*;
12
13pub trait DynFiftCont {
14 fn new_dyn_fift_cont<T: FiftCont + 'static>(cont: T) -> RcFiftCont;
15}
16
17impl DynFiftCont for RcFiftCont {
18 #[inline]
19 fn new_dyn_fift_cont<T: FiftCont + 'static>(cont: T) -> RcFiftCont {
20 let cont: Rc<dyn FiftCont> = Rc::new(cont);
21 RcFiftCont::from(cont)
22 }
23}
24
25pub trait IntoDynFiftCont {
26 fn into_dyn_fift_cont(self) -> RcFiftCont;
27}
28
29impl<T: FiftCont> IntoDynFiftCont for Rc<T> {
30 #[inline]
31 fn into_dyn_fift_cont(self) -> RcFiftCont {
32 let this: Rc<dyn FiftCont> = self;
33 RcFiftCont::from(this)
34 }
35}
36
37impl<T: FiftCont> IntoDynFiftCont for SafeRc<T> {
38 #[inline]
39 fn into_dyn_fift_cont(self) -> RcFiftCont {
40 Rc::<T>::into_dyn_fift_cont(SafeRc::into_inner(self))
41 }
42}
43
44pub type RcFiftCont = SafeRc<dyn FiftCont>;
45
46pub trait FiftCont: SafeDelete + RcIntoDynFiftValue {
47 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>>;
48
49 fn up(&self) -> Option<&RcFiftCont> {
50 None
51 }
52
53 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
54
55 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 self.fmt_name(d, f)
57 }
58}
59
60impl dyn FiftCont + '_ {
61 pub fn display_backtrace<'a>(&'a self, d: &'a Dictionary) -> impl std::fmt::Display + 'a {
62 struct ContinuationBacktrace<'a> {
63 d: &'a Dictionary,
64 cont: &'a dyn FiftCont,
65 }
66
67 impl std::fmt::Display for ContinuationBacktrace<'_> {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 let mut cont = self.cont;
70 let mut newline = "";
71 for i in 1..=16 {
72 write!(f, "{newline}{i:>4}: {}", cont.display_dump(self.d))?;
73 newline = "\n";
74 match cont.up() {
75 Some(next) => cont = next.as_ref(),
76 None => return Ok(()),
77 }
78 }
79 write!(f, "{newline}... more levels ...")
80 }
81 }
82
83 ContinuationBacktrace { d, cont: self }
84 }
85
86 pub fn display_name<'a>(&'a self, d: &'a Dictionary) -> impl std::fmt::Display + 'a {
87 struct ContinuationWriteName<'a> {
88 d: &'a Dictionary,
89 cont: &'a dyn FiftCont,
90 }
91
92 impl std::fmt::Display for ContinuationWriteName<'_> {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 self.cont.fmt_name(self.d, f)
95 }
96 }
97
98 ContinuationWriteName { d, cont: self }
99 }
100
101 pub fn display_dump<'a>(&'a self, d: &'a Dictionary) -> impl std::fmt::Display + 'a {
102 struct ContinuationDump<'a> {
103 d: &'a Dictionary,
104 cont: &'a dyn FiftCont,
105 }
106
107 impl std::fmt::Display for ContinuationDump<'_> {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 self.cont.fmt_dump(self.d, f)
110 }
111 }
112
113 ContinuationDump { d, cont: self }
114 }
115}
116
117impl<T: FiftCont + 'static> StackValue for T {
118 fn ty(&self) -> StackValueType {
119 StackValueType::Cont
120 }
121
122 fn is_equal(&self, other: &dyn StackValue) -> bool {
123 StackValue::is_equal(self as &dyn FiftCont, other)
124 }
125
126 fn fmt_dump(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 StackValue::fmt_dump(self as &dyn FiftCont, f)
128 }
129
130 fn as_cont(&self) -> ::anyhow::Result<&dyn FiftCont> {
131 Ok(self)
132 }
133
134 fn rc_into_cont(self: Rc<Self>) -> Result<Rc<dyn FiftCont>> {
135 Ok(self)
136 }
137}
138
139#[derive(Clone, Copy)]
140pub struct InterpreterCont;
141
142impl FiftCont for InterpreterCont {
143 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
144 thread_local! {
145 static COMPILE_EXECUTE: RcFiftCont = SafeRc::new_dyn_fift_cont(CompileExecuteCont);
146 static WORD: RefCell<String> = RefCell::new(String::with_capacity(128));
147 };
148
149 let this = self.into_dyn_fift_cont();
150
151 ctx.stdout.flush()?;
152
153 let compile_exec = COMPILE_EXECUTE.with(|c| c.clone());
154
155 'source_block: loop {
156 'token: {
157 let mut rewind = None;
158 let entry = 'entry: {
159 let Some(token) = ctx.input.scan_word()? else {
160 if ctx.input.pop_source_block() {
161 continue 'source_block;
162 }
163 return Ok(None);
164 };
165
166 if let Some(entry) = WORD.with(|word| {
168 let mut word = word.borrow_mut();
169 word.clear();
170 word.push_str(token);
171 word.push(' ');
172
173 if let Some(entry) = ctx.dicts.lookup(&word, false)? {
175 return Ok::<_, anyhow::Error>(Some(entry));
176 }
177
178 while !word.is_empty() {
180 word.pop();
181 if let Some(entry) = ctx.dicts.lookup(&word, false)? {
182 rewind = Some(word.len());
183 return Ok(Some(entry));
184 }
185 }
186
187 Ok(None)
188 })? {
189 break 'entry entry;
190 }
191
192 if let Some(value) = ImmediateInt::try_from_str(token)? {
194 ctx.stack.push(value.num)?;
195 if let Some(denom) = value.denom {
196 ctx.stack.push(denom)?;
197 ctx.stack.push_argcount(2)?;
198 } else {
199 ctx.stack.push_argcount(1)?;
200 }
201 break 'token;
202 }
203
204 anyhow::bail!("Undefined word `{token}`");
205 };
206
207 if let Some(rewind) = rewind {
208 ctx.input.rewind(rewind);
209 } else {
210 ctx.input.skip_line_whitespace();
211 }
212
213 if entry.active {
214 ctx.next = SeqCont::make(
215 Some(compile_exec),
216 SeqCont::make(Some(this), ctx.next.take()),
217 );
218 return Ok(Some(entry.definition.clone()));
219 } else {
220 ctx.stack.push_int(0)?;
221 ctx.stack.push_raw(entry.definition.into_dyn_fift_value())?;
222 }
223 };
224
225 ctx.exit_interpret.store(match &ctx.next {
226 Some(next) => next.clone().into_dyn_fift_value(),
227 None => NopCont::value_instance(),
228 });
229
230 ctx.next = SeqCont::make(Some(this), ctx.next.take());
231 break Ok(Some(compile_exec));
232 }
233 }
234
235 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236 f.write_str("<text interpreter continuation>")
237 }
238}
239
240#[derive(Clone, Copy)]
241struct CompileExecuteCont;
242
243impl FiftCont for CompileExecuteCont {
244 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
245 Ok(if ctx.state.is_compile() {
246 ctx.compile_stack_top()?;
247 None
248 } else {
249 Some(ctx.execute_stack_top()?)
250 })
251 }
252
253 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 f.write_str("<compile execute continuation>")
255 }
256}
257
258#[derive(Clone)]
259pub struct ListCont {
260 pub list: Rc<WordList>,
261 pub after: Option<RcFiftCont>,
262 pub pos: usize,
263}
264
265impl FiftCont for ListCont {
266 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
267 let is_last = self.pos + 1 >= self.list.items.len();
268 let Some(current) = self.list.items.get(self.pos).cloned() else {
269 return Ok(ctx.next.take());
270 };
271
272 match Rc::get_mut(&mut self) {
273 Some(this) => {
274 ctx.insert_before_next(&mut this.after);
275 this.pos += 1;
276 ctx.next = if is_last {
277 this.after.take()
278 } else {
279 Some(self.into_dyn_fift_cont())
280 };
281 }
282 None => {
283 if let Some(next) = ctx.next.take() {
284 ctx.next = Some(RcFiftCont::new_dyn_fift_cont(ListCont {
285 after: SeqCont::make(self.after.clone(), Some(next)),
286 list: self.list.clone(),
287 pos: self.pos + 1,
288 }))
289 } else if is_last {
290 ctx.next = self.after.clone()
291 } else {
292 ctx.next = Some(RcFiftCont::new_dyn_fift_cont(ListCont {
293 after: self.after.clone(),
294 list: self.list.clone(),
295 pos: self.pos + 1,
296 }))
297 }
298 }
299 }
300
301 Ok(Some(current))
302 }
303
304 fn up(&self) -> Option<&RcFiftCont> {
305 self.after.as_ref()
306 }
307
308 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309 write_cont_name(self, d, f)
310 }
311
312 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313 if self.pos == 0 {
314 f.write_str("{")?;
315 for item in &self.list.items {
316 write!(f, " {}", item.display_name(d))?;
317 }
318 f.write_str(" }")
319 } else {
320 const N: usize = 16;
321
322 if let Some(name) = d.resolve_name(self) {
323 write!(f, "[in {name}:] ")?;
324 }
325
326 let len = self.list.items.len();
327 let start = self.pos.saturating_sub(N);
328 let items = self.list.items.iter();
329
330 if start > 0 {
331 f.write_str("... ")?;
332 }
333 for (i, item) in items.enumerate().skip(start).take(N) {
334 if i == self.pos {
335 f.write_str("**HERE** ")?;
336 }
337 write!(f, "{} ", item.display_name(d))?;
338 }
339 if self.pos + N < len {
340 f.write_str("...")?;
341 }
342 Ok(())
343 }
344 }
345}
346
347#[derive(Clone, Copy)]
348pub struct NopCont;
349
350impl NopCont {
351 thread_local! {
352 static INSTANCE: (RcFiftCont, SafeRc<dyn StackValue>) = {
353 let cont = RcFiftCont::new_dyn_fift_cont(NopCont);
354 let value: SafeRc<dyn StackValue> = cont.clone().into_dyn_fift_value();
355 (cont, value)
356 };
357 }
358
359 pub fn instance() -> RcFiftCont {
360 Self::INSTANCE.with(|(c, _)| c.clone())
361 }
362
363 pub fn value_instance() -> SafeRc<dyn StackValue> {
364 Self::INSTANCE.with(|(_, v)| v.clone())
365 }
366
367 pub fn is_nop(cont: &dyn FiftCont) -> bool {
368 let left = Self::INSTANCE.with(|(c, _)| SafeRc::as_ptr(c) as *const ());
369 std::ptr::addr_eq(left, cont)
370 }
371}
372
373impl FiftCont for NopCont {
374 fn run(self: Rc<Self>, _: &mut crate::Context) -> Result<Option<RcFiftCont>> {
375 Ok(None)
376 }
377
378 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379 f.write_str("<nop>")
380 }
381}
382
383#[derive(Clone)]
384pub struct SeqCont {
385 pub first: Option<RcFiftCont>,
386 pub second: Option<RcFiftCont>,
387}
388
389impl SeqCont {
390 pub fn make(first: Option<RcFiftCont>, second: Option<RcFiftCont>) -> Option<RcFiftCont> {
391 if second.is_none() {
392 first
393 } else if let Some(first) = first {
394 Some(RcFiftCont::new_dyn_fift_cont(Self {
395 first: Some(first),
396 second,
397 }))
398 } else {
399 second
400 }
401 }
402}
403
404impl FiftCont for SeqCont {
405 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
406 Ok(match Rc::get_mut(&mut self) {
407 Some(this) => {
408 if ctx.next.is_none() {
409 ctx.next = this.second.take();
410 this.first.take()
411 } else {
412 let result = std::mem::replace(&mut this.first, this.second.take());
413 this.second = ctx.next.take();
414 ctx.next = Some(self.into_dyn_fift_cont());
415 result
416 }
417 }
418 None => {
419 ctx.next = SeqCont::make(self.second.clone(), ctx.next.take());
420 self.first.clone()
421 }
422 })
423 }
424
425 fn up(&self) -> Option<&RcFiftCont> {
426 self.second.as_ref()
427 }
428
429 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
430 if let Some(first) = &self.first {
431 first.as_ref().fmt_name(d, f)
432 } else {
433 Ok(())
434 }
435 }
436
437 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
438 if let Some(first) = &self.first {
439 first.as_ref().fmt_dump(d, f)?;
440 }
441 Ok(())
442 }
443}
444
445#[derive(Clone)]
446pub struct TimesCont {
447 pub body: Option<RcFiftCont>,
448 pub after: Option<RcFiftCont>,
449 pub count: usize,
450}
451
452impl FiftCont for TimesCont {
453 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
454 Ok(match Rc::get_mut(&mut self) {
455 Some(this) => {
456 ctx.insert_before_next(&mut this.after);
457
458 if this.count > 1 {
459 this.count -= 1;
460 let body = this.body.clone();
461 ctx.next = Some(self.into_dyn_fift_cont());
462 body
463 } else {
464 ctx.next = this.after.take();
465 this.body.take()
466 }
467 }
468 None => {
469 let next = SeqCont::make(self.after.clone(), ctx.next.take());
470
471 ctx.next = if self.count > 1 {
472 Some(RcFiftCont::new_dyn_fift_cont(Self {
473 body: self.body.clone(),
474 after: next,
475 count: self.count - 1,
476 }))
477 } else {
478 next
479 };
480
481 self.body.clone()
482 }
483 })
484 }
485
486 fn up(&self) -> Option<&RcFiftCont> {
487 self.after.as_ref()
488 }
489
490 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
491 write!(f, "<repeat {} times>", self.count)
492 }
493
494 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
495 write!(f, "<repeat {} times:> ", self.count)?;
496 if let Some(body) = &self.body {
497 FiftCont::fmt_dump(body.as_ref(), d, f)?;
498 }
499 Ok(())
500 }
501}
502
503#[derive(Clone)]
504pub struct UntilCont {
505 pub body: Option<RcFiftCont>,
506 pub after: Option<RcFiftCont>,
507}
508
509impl FiftCont for UntilCont {
510 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
511 if ctx.stack.pop_bool()? {
512 return Ok(match Rc::get_mut(&mut self) {
513 Some(this) => this.after.take(),
514 None => self.after.clone(),
515 });
516 }
517
518 let body = self.body.clone();
519 let next = match Rc::get_mut(&mut self) {
520 Some(this) => {
521 ctx.insert_before_next(&mut this.after);
522 self
523 }
524 None => {
525 if let Some(next) = ctx.next.take() {
526 Rc::new(UntilCont {
527 body: self.body.clone(),
528 after: SeqCont::make(self.after.clone(), Some(next)),
529 })
530 } else {
531 self
532 }
533 }
534 };
535 ctx.next = Some(next.into_dyn_fift_cont());
536 Ok(body)
537 }
538
539 fn up(&self) -> Option<&RcFiftCont> {
540 self.after.as_ref()
541 }
542
543 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
544 f.write_str("<until loop continuation>")
545 }
546
547 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
548 f.write_str("<until loop continuation:> ")?;
549 if let Some(body) = &self.body {
550 FiftCont::fmt_dump(body.as_ref(), d, f)?;
551 }
552 Ok(())
553 }
554}
555
556#[derive(Clone)]
557pub struct WhileCont {
558 pub condition: Option<RcFiftCont>,
559 pub body: Option<RcFiftCont>,
560 pub after: Option<RcFiftCont>,
561 pub running_body: bool,
562}
563
564impl WhileCont {
565 fn stage_name(&self) -> &'static str {
566 if self.running_body {
567 "body"
568 } else {
569 "condition"
570 }
571 }
572}
573
574impl FiftCont for WhileCont {
575 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
576 let cont = if self.running_body {
577 if !ctx.stack.pop_bool()? {
578 return Ok(match Rc::get_mut(&mut self) {
579 Some(this) => this.after.take(),
580 None => self.after.clone(),
581 });
582 }
583
584 self.body.clone()
585 } else {
586 self.condition.clone()
587 };
588
589 let next = match Rc::get_mut(&mut self) {
590 Some(this) => {
591 ctx.insert_before_next(&mut this.after);
592 this.running_body = !this.running_body;
593 self
594 }
595 None => Rc::new(Self {
596 condition: self.condition.clone(),
597 body: self.body.clone(),
598 after: SeqCont::make(self.after.clone(), ctx.next.take()),
599 running_body: !self.running_body,
600 }),
601 };
602
603 ctx.next = Some(next.into_dyn_fift_cont());
604 Ok(cont)
605 }
606
607 fn up(&self) -> Option<&RcFiftCont> {
608 self.after.as_ref()
609 }
610
611 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
612 write!(f, "<while loop {}>", self.stage_name())
613 }
614
615 fn fmt_dump(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
616 write!(f, "<while loop {}:>", self.stage_name())?;
617 let stage = if self.running_body {
618 self.body.as_ref()
619 } else {
620 self.condition.as_ref()
621 };
622 if let Some(stage) = stage {
623 FiftCont::fmt_dump(stage.as_ref(), d, f)?;
624 }
625 Ok(())
626 }
627}
628
629pub struct LoopCont<T> {
630 inner: T,
631 state: LoopContState,
632 func: RcFiftCont,
633 after: Option<RcFiftCont>,
634}
635
636impl<T: Clone> Clone for LoopCont<T> {
637 #[inline]
638 fn clone(&self) -> Self {
639 Self {
640 inner: self.inner.clone(),
641 state: self.state,
642 func: self.func.clone(),
643 after: self.after.clone(),
644 }
645 }
646}
647
648impl<T> LoopCont<T> {
649 pub fn new(inner: T, func: RcFiftCont, after: Option<RcFiftCont>) -> Self {
650 Self {
651 inner,
652 state: LoopContState::Init,
653 func,
654 after,
655 }
656 }
657}
658
659impl<T: LoopContImpl + 'static> FiftCont for LoopCont<T> {
660 fn run(mut self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
661 let Some(this) = Rc::get_mut(&mut self) else {
662 return Ok(Some(SafeRc::new_dyn_fift_cont(Self {
663 inner: self.inner.clone(),
664 state: self.state,
665 func: self.func.clone(),
666 after: self.after.clone(),
667 })));
668 };
669
670 ctx.insert_before_next(&mut this.after);
671 Ok(loop {
672 match this.state {
673 LoopContState::Init => {
674 if !this.inner.init(ctx)? {
675 break this.after.take();
676 }
677 this.state = LoopContState::PreExec;
678 }
679 LoopContState::PreExec => {
680 if !this.inner.pre_exec(ctx)? {
681 this.state = LoopContState::Finalize;
682 continue;
683 }
684 this.state = LoopContState::PostExec;
685 let res = self.func.clone();
686 ctx.next = Some(self.into_dyn_fift_cont());
687 break Some(res);
688 }
689 LoopContState::PostExec => {
690 if !this.inner.post_exec(ctx)? {
691 this.state = LoopContState::Finalize;
692 continue;
693 }
694 this.state = LoopContState::PreExec;
695 break Some(self.into_dyn_fift_cont());
696 }
697 LoopContState::Finalize => {
698 break if this.inner.finalize(ctx)? {
699 this.after.take()
700 } else {
701 None
702 };
703 }
704 }
705 })
706 }
707
708 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
709 write!(f, "<generic loop continuation state {:?}>", self.state)
710 }
711}
712
713pub trait LoopContImpl: Clone {
714 fn init(&mut self, ctx: &mut Context) -> Result<bool> {
715 _ = ctx;
716 Ok(true)
717 }
718 fn pre_exec(&mut self, ctx: &mut Context) -> Result<bool> {
719 _ = ctx;
720 Ok(true)
721 }
722 fn post_exec(&mut self, ctx: &mut Context) -> Result<bool> {
723 _ = ctx;
724 Ok(true)
725 }
726 fn finalize(&mut self, ctx: &mut Context) -> Result<bool> {
727 _ = ctx;
728 Ok(true)
729 }
730}
731
732#[derive(Debug, Clone, Copy, Eq, PartialEq)]
733enum LoopContState {
734 Init,
735 PreExec,
736 PostExec,
737 Finalize,
738}
739
740#[derive(Clone)]
741pub struct IntLitCont(BigInt);
742
743impl<T> From<T> for IntLitCont
744where
745 BigInt: From<T>,
746{
747 fn from(value: T) -> Self {
748 Self(BigInt::from(value))
749 }
750}
751
752impl FiftCont for IntLitCont {
753 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
754 let value = match Rc::try_unwrap(self) {
755 Ok(value) => value.0,
756 Err(this) => this.0.clone(),
757 };
758 ctx.stack.push(value)?;
759 Ok(None)
760 }
761
762 fn fmt_name(&self, _: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
763 write!(f, "{}", self.0)
764 }
765}
766
767#[derive(Clone)]
768pub struct LitCont(pub SafeRc<dyn StackValue>);
769
770impl FiftCont for LitCont {
771 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
772 let value = match Rc::try_unwrap(self) {
773 Ok(value) => value.0,
774 Err(this) => this.0.clone(),
775 };
776 ctx.stack.push_raw(value)?;
777 Ok(None)
778 }
779
780 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
781 write_lit_cont_name(self.0.as_ref(), d, f)
782 }
783}
784
785#[derive(Clone)]
786pub struct MultiLitCont(pub Vec<SafeRc<dyn StackValue>>);
787
788impl FiftCont for MultiLitCont {
789 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
790 match Rc::try_unwrap(self) {
791 Ok(value) => {
792 for item in value.0 {
793 ctx.stack.push_raw(item)?;
794 }
795 }
796 Err(this) => {
797 for item in &this.0 {
798 ctx.stack.push_raw(item.clone())?;
799 }
800 }
801 };
802 Ok(None)
803 }
804
805 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
806 let mut first = true;
807 for item in &self.0 {
808 if !std::mem::take(&mut first) {
809 f.write_str(" ")?;
810 }
811 write_lit_cont_name(item.as_ref(), d, f)?;
812 }
813 Ok(())
814 }
815}
816
817pub type ContextWordFunc = fn(&mut Context) -> Result<()>;
818
819impl FiftCont for ContextWordFunc {
820 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
821 (self)(ctx)?;
822 Ok(None)
823 }
824
825 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
826 write_cont_name(self, d, f)
827 }
828}
829
830pub type ContextTailWordFunc = fn(&mut Context) -> Result<Option<RcFiftCont>>;
831
832impl FiftCont for ContextTailWordFunc {
833 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
834 (self)(ctx)
835 }
836
837 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
838 write_cont_name(self, d, f)
839 }
840}
841
842pub type StackWordFunc = fn(&mut Stack) -> Result<()>;
843
844impl FiftCont for StackWordFunc {
845 fn run(self: Rc<Self>, ctx: &mut Context) -> Result<Option<RcFiftCont>> {
846 (self)(&mut ctx.stack)?;
847 Ok(None)
848 }
849
850 fn fmt_name(&self, d: &Dictionary, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
851 write_cont_name(self, d, f)
852 }
853}
854
855impl Context<'_> {
858 fn insert_before_next(&mut self, cont: &mut Option<RcFiftCont>) {
859 if let Some(next) = self.next.take() {
860 *cont = match cont.take() {
861 Some(prev) => Some(RcFiftCont::new_dyn_fift_cont(SeqCont {
862 first: Some(prev),
863 second: Some(next),
864 })),
865 None => Some(next),
866 };
867 }
868 }
869}
870
871fn write_lit_cont_name(
872 stack_entry: &dyn StackValue,
873 d: &Dictionary,
874 f: &mut std::fmt::Formatter<'_>,
875) -> std::fmt::Result {
876 let ty = stack_entry.ty();
877 match ty {
878 StackValueType::Int | StackValueType::String | StackValueType::Builder => {
879 stack_entry.fmt_dump(f)
880 }
881 _ => {
882 if let Ok(cont) = stack_entry.as_cont() {
883 write!(f, "{{ {} }}", cont.display_dump(d))
884 } else {
885 write!(f, "<literal of type {:?}>", ty)
886 }
887 }
888 }
889}
890
891fn write_cont_name(
892 cont: &dyn FiftCont,
893 d: &Dictionary,
894 f: &mut std::fmt::Formatter<'_>,
895) -> std::fmt::Result {
896 if let Some(name) = d.resolve_name(cont) {
897 f.write_str(name.trim_end())
898 } else {
899 write!(f, "<continuation {:?}>", cont as *const _ as *const ())
900 }
901}